├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── user-story-template.md └── workflows │ ├── BasicHello.yml │ ├── EnvironmentWorkflow.yml │ ├── bicepdeploy.yml │ ├── osmatrix.yml │ └── readazurekeyvault.yml ├── Images └── logosmall.png ├── Part01Foundation ├── DevOpsMC2021-Part1Foundation-Handout.pdf └── DevOpsMC2021-Part1Foundation-Whiteboard.svg ├── Part02MasterGit ├── DevOpsMC2021-Part2MasterGit-Handout.pdf ├── DevOpsMC2021-Part2MasterGit-Whiteboard.svg ├── Script.ps1 └── WithoutSourceControl │ ├── importantfile.txt │ ├── importantfile_v2.txt │ ├── importantfile_v3_with_feature.txt │ ├── importantfile_v4_final.txt │ └── importantfile_v4_final_v2.txt ├── Part03ADOGitHub └── DevOpsMC2021-Part3ADOGitHub-Whiteboard.svg ├── Part04CICD ├── ADOPipelines │ └── sayhello.yml ├── DevOpsMC2021-Part4CICD-Whiteboard.svg └── GitHubPipelines │ └── readme.txt ├── Part05Secrets ├── CreateAzureCred.txt ├── DemoVMMngIdent.ps1 └── DevOpsMC2021-Part5Secrets-Whiteboard.svg ├── Part06IaC ├── DevOpsMC2021-Part6IaC-Whiteboard.svg ├── IISInstall.ps1 ├── demofile.ps1 ├── storageaccount-dev.bad.parameters.json ├── storageaccount-dev.parameters.json └── storageaccount.bicep ├── Part07Containers ├── AKSSQLServerDeployment.yaml ├── AKSStorageProviderandPVC.yaml ├── DevOpsMC2021-Part7Containers-Whiteboard.svg ├── Docker │ ├── badfather │ │ ├── Dockerfile │ │ └── website │ │ │ ├── default.htm │ │ │ ├── page2.htm │ │ │ ├── page3.htm │ │ │ ├── pic.jpg │ │ │ ├── pic2.jpg │ │ │ └── pic2zoom.jpg │ ├── badfatherapache │ │ ├── Dockerfile │ │ └── website │ │ │ ├── index.html │ │ │ ├── page2.htm │ │ │ ├── page3.htm │ │ │ ├── pic.jpg │ │ │ ├── pic2.jpg │ │ │ └── pic2zoom.jpg │ └── docker.ps1 ├── aks-badfather.yaml └── k8sdemo.ps1 ├── Part08MonitoringandFeedback └── DevOpsMC2021-Part8MonitorFeedback-Whiteboard.svg └── README.md /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/user-story-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: User Story Template 3 | about: Template for a user story 4 | title: New User Story 5 | labels: user story 6 | assignees: '' 7 | 8 | --- 9 | 10 | User story purpose 11 | 12 | Focus on the objective for a specific role and the motivation for it. 13 | 14 | This should be non-technical language focused on the value. 15 | 16 | What is acceptance criteria 17 | - [ ] Criteria 1 18 | - [ ] Criteria 2 19 | -------------------------------------------------------------------------------- /.github/workflows/BasicHello.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: BasicHello 4 | 5 | # Controls when the workflow will run 6 | on: 7 | # Allows you to run this workflow manually from the Actions tab 8 | workflow_dispatch: 9 | 10 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 11 | jobs: 12 | # This workflow contains a single job called "build" 13 | build: 14 | # The type of runner that the job will run on 15 | runs-on: ubuntu-latest 16 | 17 | # Steps represent a sequence of tasks that will be executed as part of the job 18 | steps: 19 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 20 | - uses: actions/checkout@v2 21 | 22 | # Runs a single command using the runners shell 23 | - name: Run a one-line script 24 | run: echo Hello, world! 25 | 26 | # Runs a set of commands using the runners shell 27 | - name: Run a multi-line script 28 | run: | 29 | echo Add other actions to build, 30 | echo test, and deploy your project. 31 | -------------------------------------------------------------------------------- /.github/workflows/EnvironmentWorkflow.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: EnvironmentWorkflow 4 | 5 | # Controls when the workflow will run 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the main branch 8 | #push: 9 | # branches: [ main ] 10 | #pull_request: 11 | # branches: [ main ] 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 17 | jobs: 18 | 19 | job1: 20 | # The type of runner that the job will run on 21 | runs-on: ubuntu-latest 22 | environment: TEST 23 | 24 | # Steps represent a sequence of tasks that will be executed as part of the job 25 | steps: 26 | # Runs a single command using the runners shell 27 | - name: Send greeting1 28 | env: 29 | SECRET: ${{ secrets.Greeting }} 30 | run: | 31 | echo "Job 1 running on Test" 32 | if [ $SECRET = "TestTestTest" ]; then echo "Test"; fi 33 | 34 | job2: 35 | runs-on: ubuntu-latest 36 | environment: QA 37 | needs: 38 | - job1 39 | 40 | steps: 41 | - name: Send greeting2 42 | env: 43 | SECRET: ${{ secrets.Greeting }} 44 | run: | 45 | echo "Job 2 running on QA" 46 | if [ $SECRET = "QAQAQA" ]; then echo "QA"; fi 47 | 48 | job3: 49 | runs-on: ubuntu-latest 50 | needs: 51 | - job2 52 | 53 | steps: 54 | - name: Send greeting3 55 | env: 56 | SECRET: ${{ secrets.Greeting }} 57 | run: | 58 | echo "Job 3 running on no specific environment" 59 | if [ $SECRET = "RepoRepoRepo" ]; then echo "Repo"; fi 60 | 61 | job4: 62 | runs-on: ubuntu-latest 63 | environment: PROD 64 | needs: 65 | - job2 66 | 67 | steps: 68 | - name: Send greeting4 69 | env: 70 | SECRET: ${{ secrets.Greeting }} 71 | run: | 72 | echo "Job 4 running on Prod" 73 | if [ $SECRET = "ProdProdProd" ]; then echo "Prod"; fi 74 | -------------------------------------------------------------------------------- /.github/workflows/bicepdeploy.yml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_dispatch: 3 | 4 | name: Deploy Bicep Demo 5 | 6 | permissions: 7 | id-token: write 8 | contents: read 9 | 10 | jobs: 11 | deploy-infrastructure: 12 | runs-on: ubuntu-latest 13 | environment: TEST 14 | 15 | steps: 16 | - name: Check out the repo 17 | uses: actions/checkout@v2 18 | 19 | - name: Login to Azure 20 | uses: azure/login@v1 21 | with: 22 | client-id: ${{ secrets.AZURE_CLIENT_ID }} 23 | tenant-id: ${{ secrets.AZURE_TENANT_ID }} 24 | subscription-id: ${{ secrets.AZURE_SUB_ID }} 25 | 26 | # Deploy Bicep file 27 | - name: Deploy the bicep file 28 | uses: azure/arm-deploy@v1 29 | with: 30 | subscriptionId: ${{ secrets.AZURE_SUB_ID }} 31 | resourceGroupName: RG_PolicyTest 32 | template: ./Part06IaC/storageaccount.bicep 33 | parameters: ./Part06IaC/storageaccount-dev.parameters.json 34 | -------------------------------------------------------------------------------- /.github/workflows/osmatrix.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: OSMatrix 4 | 5 | # Controls when the workflow will run 6 | on: 7 | workflow_dispatch: 8 | 9 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 10 | jobs: 11 | message: #name of job 12 | strategy: 13 | matrix: 14 | os: 15 | - ubuntu-latest 16 | - windows-latest 17 | - macos-latest 18 | runs-on: ${{ matrix.os }} 19 | 20 | steps: 21 | - name: Say hello to the OS 22 | run: echo "Hello from ${{ matrix.os }}" 23 | -------------------------------------------------------------------------------- /.github/workflows/readazurekeyvault.yml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_dispatch: 3 | 4 | name: ReadAzureKeyVault 5 | 6 | jobs: 7 | 8 | login-and-read-secret: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Check out the repo 12 | uses: actions/checkout@v2 13 | 14 | - name: Login to Azure 15 | uses: azure/login@v1 16 | with: 17 | creds: ${{ secrets.AZURE_CREDENTIALS }} 18 | 19 | - name: Azure key vault - Get Secret 20 | uses: Azure/get-keyvault-secrets@v1 21 | with: 22 | # Name of the azure key vault 23 | keyvault: SavillVaultRBAC 24 | # Name of the secret to be fetched 25 | secrets: Secret1 26 | id: getKeyVaultSecrets 27 | 28 | - name: Dumb thing to do with a secret 29 | env: 30 | SECRET: ${{ steps.getKeyVaultSecrets.outputs.Secret1 }} 31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 | run: | 33 | echo "Can I see $SECRET" 34 | if [ $SECRET = "Password" ]; then echo "That is a match"; fi 35 | -------------------------------------------------------------------------------- /Images/logosmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnthebrit/DevOpsMC/79dfbc0063ddf3622fd6bf6a9792a351a517b396/Images/logosmall.png -------------------------------------------------------------------------------- /Part01Foundation/DevOpsMC2021-Part1Foundation-Handout.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnthebrit/DevOpsMC/79dfbc0063ddf3622fd6bf6a9792a351a517b396/Part01Foundation/DevOpsMC2021-Part1Foundation-Handout.pdf -------------------------------------------------------------------------------- /Part02MasterGit/DevOpsMC2021-Part2MasterGit-Handout.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnthebrit/DevOpsMC/79dfbc0063ddf3622fd6bf6a9792a351a517b396/Part02MasterGit/DevOpsMC2021-Part2MasterGit-Handout.pdf -------------------------------------------------------------------------------- /Part02MasterGit/Script.ps1: -------------------------------------------------------------------------------- 1 | $scratch = 's:\scratch' 2 | $devopsmc = 'C:\Users\john\OneDrive\projects\GIT\DevOpsMC' 3 | 4 | #Check version 5 | git --version 6 | 7 | #Turn any folder into a repo which creates a sub .git folder 8 | git init 9 | git help init #to open man pages for detail or 10 | git init --help #to also open man page 11 | 12 | #View the hidden folder 13 | Get-ChildItem -Force #notice the .git 14 | 15 | #Clone the DevOps Master Class Repo into the current folder 16 | git clone https://github.com/johnthebrit/DevOpsMC.git . 17 | #Clone into a new subfolder auto created under current path 18 | git clone https://github.com/johnthebrit/DevOpsMC.git 19 | 20 | #You can clone a local folder the same way! 21 | git clone gitplay1 gitplay2 22 | git remote -v #would show repo1 as the origin as we cloned from it. More on this later 23 | 24 | #Looking at remote (again more later on all of this!) 25 | git remote -v 26 | git remote show origin 27 | 28 | #Set initial git configuration 29 | #Can replace --global with --local to set values for a specific repo if required 30 | git config --global --list #care about username and email 31 | 32 | git config --global user.name "John Savill" 33 | git config --global user.email john@savilltech.com 34 | 35 | git config --list --show-origin #see where coming from :q 36 | git config --list 37 | 38 | #Many other settings https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup 39 | git config --global init.defaultBranch main #this is very common to use instead of master 40 | 41 | #Git Internals 42 | #WB5 43 | #Create a repo again 44 | New-Item gitplay1 -ItemType "directory" 45 | Set-Location .\gitplay1 46 | git init 47 | code .\testfile.txt 48 | 49 | #Pay attention to the current .git folder content, especially the objects folder 50 | git add . 51 | #Notice we now have a new object in a 2 character folder name with 38 character name, i.e. 40 character hash 52 | git status 53 | git diff --cached #Difference between staged and what is commited 54 | git commit -m "Initial testfile.txt commit" 55 | #We have two new objects created! The path and the commit itself 56 | 57 | #NOTE Could combine the add and commit 58 | git commit -am "Initial testfile.txt commit" 59 | #or even 60 | git commit -a -m "Initial testfile.txt commit" 61 | 62 | #Look at the full commit. 63 | git log 64 | #Notice also our head pointer is pointing to main which is just a reference to a commit hash 65 | 66 | #look at the type 67 | git cat-file -t 68 | #look at the content 69 | git cat-file -p 70 | 71 | #look at the type 72 | git cat-file -t 73 | #look at the content. Notice here it points the blob we saw created before and now has a file name 74 | git cat-file -p 75 | 76 | #look at the type 77 | git cat-file -t 78 | #look at the content. Notice here it points the blob we saw created before and now has a file name 79 | git cat-file -p 80 | 81 | #Lets prove a point about it only storing unique content 82 | Copy-Item .\testfile.txt .\testfile2.txt 83 | git add . 84 | #what new object do we have? Nothing. 85 | git status 86 | git commit -m "testfile2.txt added" 87 | #We have new files. Look again 88 | 89 | git log --oneline --graph --decorate --all #I will be using this a lot 90 | git cat-file -p #Note it references the parent commit hash, again, can't change history as hash would not match 91 | git cat-file -p 92 | #WOW, two file names. SAME BLOB as had same content 93 | #Our main reference also now points to the new commit, it just moved along 94 | 95 | #I'm going to go ahead and create a function for my nice git log command. This may vary based on your CLI 96 | function gitgraph {git log --oneline --graph --decorate --all} 97 | #Could add this to your profile 98 | code $profile 99 | 100 | #Note when you create a new repo you can override the default initial branch 101 | git init --initial-branch=main 102 | git init -b main 103 | 104 | 105 | #WB06 106 | #Modify a file and stage 107 | code .\testfile.txt 108 | git add testfile.txt 109 | git status 110 | #add a 3rd file but don't stage 111 | code .\testfile3.txt 112 | git status 113 | 114 | git commit -m "updated testfile" 115 | git status 116 | #notice our untracked file, i.e. working is not changed but staging is now matching the repo 117 | 118 | gitgraph 119 | 120 | #We can look at the changes 121 | git log -p #also shows the diff/patch between the commits :q 122 | 123 | gitgraph 124 | git diff .. #diff between specific commits 125 | #Remember the complete snapshot is stored. All diffs are generated at time of command execution 126 | 127 | #WB07 128 | git status 129 | git add testfile3.txt 130 | code testfile.txt #make a change 131 | git status 132 | #Between what is staged and the HEAD commit (i.e. the REPO). Could also use --staged which is synonym of --cached 133 | git diff --cached 134 | #And what is working to staged 135 | git diff 136 | #Between working and the last commit (i.e. head) 137 | git diff HEAD #basically the sum of the above two 138 | 139 | 140 | #To remove content WB08 141 | #stage the removal (which will also delete from working) 142 | git rm 143 | #to ONLY stage the remove (but not delete from working) 144 | git rm --cached 145 | #Could also just delete from working then "add" all changes 146 | git add . 147 | 148 | #Then you need to commit as normal 149 | git commit -m "Removed file x" 150 | 151 | #Example 152 | code testfile4.txt 153 | git add testfile4.txt 154 | git commit -m "adding testfile4.txt" 155 | git status 156 | git rm testfile4.txt 157 | git status #Note the delete is staged 158 | ls #its gone from stage AND my working 159 | git commit -m "removed testfile4.txt" 160 | 161 | 162 | #Resetting WB09 163 | #Remove all staged content. This is actually using --mixed which is default. More later 164 | git reset 165 | #It does this by setting staged to match the last commit 166 | #It does NOT change your working dir 167 | git reset --hard 168 | #Would also change your working directory to match! 169 | 170 | #Can reset individual files 171 | code testfile.txt 172 | git add testfile.txt 173 | git status 174 | #Restore version in staged (from last commit HEAD) but NOT working 175 | git restore --staged testfile.txt 176 | git status 177 | #Restore working from stage 178 | git restore testfile.txt 179 | git status 180 | code testfile.txt 181 | #Restore to stage and working from last commit 182 | git restore --staged --worktree testfile.txt 183 | #Full version but not required is to say from where by this is default anyway but could specify different 184 | git restore --source=HEAD --staged --worktree testfile.txt 185 | 186 | 187 | #WB10 188 | #What if we want to undo a commit? 189 | #to view all 190 | git log 191 | gitgraph 192 | 193 | #Remember, a branch is just a pointer to a commit which points to its parent 194 | #We can just move the pointer backwards! 195 | #Move back 1 but do not change staging or working. Could go back 2, 3 etc ~2, ~3 196 | git reset HEAD~1 --soft 197 | gitgraph 198 | #Notice we have moved back but did not change staging or working 199 | git status 200 | #So staging still has the change that was part of the last commit that is no longer referenced 201 | 202 | #Could also reset by a specific commit ID 203 | git reset --soft 204 | 205 | #to also reset staging. Note as I'm not specifying a commit its resetting working to the current commit which i've rolled back already 206 | #--mixed is actually the default, i.e. same as git reset which we did before to reset staging! 207 | git reset --mixed 208 | git status 209 | 210 | #Now to also reset working. Again since no commit specified its just setting to match current commit. This should look familiar! 211 | #--hard changes staging and working 212 | git reset --hard 213 | git status 214 | #Now clean 215 | 216 | #Could do all in one go 217 | gitgraph 218 | git reset HEAD~1 --hard 219 | gitgraph 220 | git status 221 | #all clean since --hard reset all levels back 222 | 223 | #The now unreferenced commit will eventually be garbage collected 224 | 225 | 226 | #TAGS WB11 227 | gitgraph 228 | #remember commits just form a chain as they point to their parent. 229 | #Notice I'm using HEAD which just points to a reference which points to a commit! 230 | git cat-file -t HEAD 231 | git cat-file -p HEAD 232 | 233 | #I can create a tag at the current location 234 | git tag v1.0.0 235 | gitgraph 236 | git tag v0.9.1 237 | gitgraph 238 | git tag --list 239 | 240 | #lets look at a commit that is tagged. Show gives information about an object. For a commit the log message and diff 241 | git show v1.0.0 242 | #We just see the commit object 243 | 244 | #These are lightweight tags. There is also an annotated type which is a full object with its own message 245 | git tag -a v0.0.1 -m "First version" 246 | git show v0.0.1 247 | #we see the TAG information AND then the commit it references 248 | git cat-file -t v0.0.1 249 | git cat-file -t v1.0.0 250 | 251 | #Note tags have to be pushed to a remote origin for them to be visible there. We will cover later 252 | git push --tag 253 | 254 | 255 | #WB12 256 | #Remote Origin Part 1 257 | cd $devopsmc 258 | git remote -v 259 | 260 | cd $scratch\gitplay1 261 | git remote -v 262 | 263 | #Create an empty repo on GitHub under your account called gitplay1 264 | #It has help about next steps 265 | 266 | #Add it as the remote origin. Origin is just a name but common standard 267 | git remote add origin https://github.com/johnthebrit/gitplay1 268 | #git branch -M main # RENAMES the branch from master to main 269 | 270 | git remote -v 271 | gitgraph 272 | 273 | #Push to the remote referened as origin 274 | git push -u origin main 275 | #Look at it on github. All there. Except tags 276 | git push --tag 277 | #Much better 278 | 279 | gitgraph 280 | #Now has origin/main pointer known 281 | 282 | #Make a change directly on the github repo! 283 | gitgraph 284 | git status 285 | #We don't know about it 286 | 287 | #Pull down remote changes 288 | git pull 289 | #Can specify where to pull from and branch 290 | git pull origin main 291 | #Pull from all remotes 292 | git pull --all 293 | #It pulled down the changes and MERGED with a fast-forward. Remember that 294 | git status 295 | gitgraph 296 | 297 | #git pull actually is doing two things 298 | #To just get remote content 299 | git fetch 300 | #can be explicit 301 | git fetch origin main 302 | 303 | git cat-file -p origin/main 304 | #Content is now on our box, just not "merged" 305 | gitgraph 306 | git status 307 | #we can see its just ahead as a direct child of our commit so a straight line to it 308 | git merge 309 | #fast forward again 310 | gitgraph 311 | 312 | 313 | #WB14 314 | #Likewise if we change locally we need to push to the remote 315 | #As a best practice pull first (fetch and merge) to ensure all clean 316 | git pull 317 | #make a change 318 | code testfile.txt 319 | git commit -am "Updated testfile.txt" 320 | git status 321 | gitgraph 322 | git push 323 | #git push --tags 324 | 325 | 326 | #.gitignore 327 | code .gitignore #add *.log /debug/* 328 | git add . 329 | git commit -m "added ignore file" 330 | git push 331 | git status 332 | code test.log 333 | code debug\file.txt 334 | ls 335 | git status 336 | #Nothing to see here! 337 | 338 | 339 | #Branches! 340 | #Start fresh 341 | cd .. 342 | mkdir JLRepo 343 | cd JLRepo 344 | git init 345 | git status 346 | #we see main which remember just references a commit (that won't exist yet) 347 | 348 | code jl.csv 349 | git add jl.csv 350 | git commit -m "Initial JL roster CSV" 351 | #WB-15black (down) 352 | 353 | #View all branches. * is current 354 | git branch --list 355 | #View remotes 356 | git branch -r 357 | #View all (local and remote) 358 | git branch -a 359 | 360 | #WB15-orange 361 | #Create a new branch pointing to where we are called branch1 362 | git branch branch1 363 | gitgraph 364 | #Notice point to same commit at this time 365 | 366 | #WB15-red 367 | git branch --list 368 | git checkout branch1 369 | #or better move to new switch that is based around movement to separate commands 370 | #switch only allows a branch to be specified. Checkout allows a commit hash (so could checkout a detached head) 371 | git switch branch1 372 | git branch --list 373 | gitgraph 374 | #When we switch it also updates the staging and working directory for the checked out branch 375 | 376 | #To create and checkout in one step: 377 | git checkout -c branch1 378 | 379 | #To push a branch to a remote. 380 | #The -u sets up tracking between local and remote branch. Allows argumentless git pull in future. Will do this later 381 | git push -u 382 | 383 | #Check which branch we are on 384 | git branch 385 | 386 | #WB16 387 | #Make a change to jl.csv adding Diana 388 | code jl.csv 389 | git add -p 390 | #Yep the above shows the actual changed chunks and can select parts! Now commit 391 | git commit -m "Added Wonder Woman" 392 | gitgraph 393 | #Notice the branch is now ahead of main 394 | #Make another change adding Barry 395 | code jl.csv 396 | git add . 397 | git commit -m "Added The Flash" 398 | gitgraph 399 | git status 400 | #all clean 401 | 402 | git switch main 403 | type jl.csv 404 | git status 405 | git switch branch1 406 | type jl.csv 407 | git status 408 | #Notice as I switch it does that update of not only the branch but gets the stage and working to same state 409 | 410 | gitgraph 411 | #the branch1 is now 2 ahead but its a straight line from the main 412 | 413 | #WB16b 414 | #Now we want to merge the changes into main 415 | #Make sure everything clean 416 | git status 417 | #Move to main 418 | git switch main 419 | #we can look at the differences 420 | git diff main..branch1 421 | #If happy lets merge them. Remember we already switched to main. We are going to merge into this from branch1 422 | git merge branch1 423 | #Done. Notice was a fast-forward. Lets look at merged branches 424 | git branch --merged 425 | 426 | gitgraph 427 | 428 | #We no longer need branch1. Remember use tags if you want some long lived reference 429 | #This would only delete locally 430 | #Remember to ALWAYS check it has been merged first before deleting 431 | git branch --merged 432 | git branch -d branch1 433 | #To delete on a remote 434 | git push origin --delete branch1 435 | 436 | 437 | #You may not want fast-forward. Maybe in the history you want to see it was a separate branch that got merged in 438 | #I am now going to mess around with time. Remember a branch is nothing more than a pointer to a commit 439 | #I can go backwards. In this case I'm going to move main BACK to before I made the last two changes 440 | gitgraph 441 | #Remember --hard also updates staging and working 442 | git reset --hard HEAD~2 443 | gitgraph 444 | #The other two commits are still out there but nothing references them. They will eventually get cleaned up 445 | #We can look and still see via the reference logs 446 | git reflog 447 | 448 | #Lets do it all again 449 | #WB17 450 | git branch branch1 451 | git switch branch1 452 | code jl.csv 453 | git add . 454 | git commit -m "Added Wonder Woman" 455 | code jl.csv 456 | git add . 457 | git commit -m "Added The Flash" 458 | gitgraph 459 | git status 460 | #looks familiar and all clean 461 | 462 | #This time specify NOT to perform a fast forward 463 | git switch main 464 | git diff main..branch1 465 | git merge --no-ff branch1 466 | git branch --merged 467 | 468 | gitgraph 469 | #Notice the merge was a new commit 470 | 471 | #We can still delete branch1 as its still merged 472 | git branch --merged 473 | git branch -d branch1 474 | #History is kept there was a branch 475 | gitgraph 476 | 477 | 478 | #WB18 479 | #Lets make it more complicated 480 | #Rewind time again (only doing this so our view is simpler) 481 | #Note using ^ instead of ~. This is because NOW main has two parents. 482 | #I'm saying go back to the first parent instead of ~ for number of generations 483 | git reset --hard HEAD^1 484 | gitgraph 485 | 486 | #Make the branch1 again with two commits 487 | git branch branch1 488 | git switch branch1 489 | code jl.csv 490 | git add . 491 | git commit -m "Added Wonder Woman" 492 | code jl.csv 493 | git add . 494 | git commit -m "Added The Flash" 495 | gitgraph 496 | git status 497 | 498 | #Switch to main 499 | git switch main 500 | code jl.csv 501 | git add . 502 | git commit -m "Added Cyborg" 503 | 504 | gitgraph 505 | #More interesting. There is now NOT a direct path from branch1 to main 506 | git status 507 | #We will have conflicts given the changes we made 508 | git merge branch1 509 | #We need to fix them by editing the file it tells us and conflicts have been marked 510 | code jl.csv 511 | #We are in conflict status: 512 | git status 513 | git add . 514 | git commit -m "Merged with branch1" 515 | 516 | gitgraph 517 | #Shows the 3-way merge is complete 518 | #Take a little screen shot of this and paste next to 3-way merge picture! 519 | 520 | git branch --merged 521 | #Could delete the branch now BUT I DON'T WANT TO 522 | #git branch -d branch1 523 | gitgraph 524 | 525 | #There is another option. Rebase 526 | #Lets rewind before the merge by going back 1 527 | git reset --hard HEAD~1 528 | gitgraph 529 | 530 | #WB19 531 | #Need to be ON the branch we are performing the action on. We are rebasing branch1 532 | git switch branch1 533 | #check its clean 534 | git status 535 | #Lets rebase off main 536 | git rebase main 537 | #We will get conflicts as it replays each of the changes so each time will need to address and continue 538 | code jl.csv 539 | git add jl.csv 540 | git rebase --continue 541 | 542 | gitgraph 543 | #Cleaner path. Copy next to the rebase whiteboard to compare! 544 | 545 | #If now merge would just be a fast-forward since now a straight line from main and NOW 3-way merge 546 | git status 547 | git switch main 548 | git merge branch1 549 | #Cleanup 550 | git branch --merged 551 | git branch -d branch1 552 | #Note if the remote master has changes you don't have and want to base on can git pull --rebase 553 | 554 | 555 | #Interactive changes 556 | #Change message of last commit 557 | git commit --amend 558 | gitgraph 559 | #Add new files to staging but don't update the message 560 | git commit --ament --no-edit 561 | #These will all mean a new hash as we are changing history and commits are immutable! 562 | #Can modify in an interactive way 563 | #Lets go back 3 changes! 564 | git rebase -i HEAD~3 565 | #s to squash commits together, d to drop. Many other options 566 | 567 | #Protect a branch in github 568 | 569 | #Pull Request! 570 | #WB20 571 | #Create a new GitHub repo (remember, this could really be any provider) 572 | git remote add origin https://github.com/johnthebrit/JLRepo.git 573 | git push -u origin main 574 | 575 | #Now as Clark in GitHub create a fork of the repo 576 | #On clarks machine we could now clone OUR copy 577 | git clone https://github.com/clarkthesuper/JLRepo.git 578 | cd JLRepo 579 | #Look at the remotes 580 | git remote -v 581 | #We may want to add Johns as an origin so we could pull down any changes they may have occured 582 | git remote add upstream https://github.com/johnthebrit/JLRepo.git 583 | git remote -v 584 | #Now we have Clarks origin and John's upstream 585 | #Could pull from John, e.g. 586 | git fetch upstream 587 | function gitgraph {git log --oneline --graph --decorate --all} 588 | gitgraph 589 | git branch branch1 590 | git switch branch1 591 | code jl.csv 592 | git add . 593 | git commit -m "Changed who the Flash is" 594 | 595 | #Push the branch to our origin 596 | git push -u origin branch1 597 | 598 | #In Clarks repo can change to branch1 and under contribute select "Open pull request" 599 | #It shows the planned submit, i.e. to main on John's repo 600 | 601 | #Now as John will see the pull request and can accept 602 | #This is a nice status and shows no conflicts and I can accept 603 | #Note if there were problems I could reject, maybe I had moved main up so Clark would need to rebase and submite again 604 | #Once confirmed will auto update on Clarks repo that is was merged and closed 605 | 606 | #On John machine 607 | git pull 608 | gitgraph 609 | 610 | #At this point on Clarks repo would pull down from upstream, delete the branch 611 | gitgraph 612 | #Knows nothing yet 613 | git fetch upstream 614 | git switch main 615 | #merge in the changes from John's repo (upstream) 616 | git merge upstream/main 617 | gitgraph 618 | #Check we are merged and delete branch1 619 | git branch --merged 620 | git branch -d branch1 621 | git status 622 | #Update OUR copy of the repo in GitHub by pushing up to it 623 | git push origin main 624 | git status 625 | #Push to our copy the remove of branch1 626 | git push origin --delete branch1 627 | 628 | #annnndddd done! -------------------------------------------------------------------------------- /Part02MasterGit/WithoutSourceControl/importantfile.txt: -------------------------------------------------------------------------------- 1 | not really, why are you looking in this. -------------------------------------------------------------------------------- /Part02MasterGit/WithoutSourceControl/importantfile_v2.txt: -------------------------------------------------------------------------------- 1 | not really, why are you looking in this. -------------------------------------------------------------------------------- /Part02MasterGit/WithoutSourceControl/importantfile_v3_with_feature.txt: -------------------------------------------------------------------------------- 1 | not really, why are you looking in this. -------------------------------------------------------------------------------- /Part02MasterGit/WithoutSourceControl/importantfile_v4_final.txt: -------------------------------------------------------------------------------- 1 | not really, why are you looking in this. -------------------------------------------------------------------------------- /Part02MasterGit/WithoutSourceControl/importantfile_v4_final_v2.txt: -------------------------------------------------------------------------------- 1 | not really, why are you looking in this. -------------------------------------------------------------------------------- /Part04CICD/ADOPipelines/sayhello.yml: -------------------------------------------------------------------------------- 1 | # Starter pipeline 2 | 3 | trigger: 4 | - main 5 | 6 | pool: 7 | vmImage: ubuntu-latest 8 | 9 | stages: 10 | - stage: A 11 | jobs: 12 | - job: A1 13 | steps: 14 | - script: echo Hello, world! 15 | displayName: 'Run a one-line script' 16 | 17 | - stage: B 18 | dependsOn: [] #Will run in parallel as removed implicit dependency 19 | jobs: 20 | - job: B1 21 | steps: 22 | - script: | 23 | echo Another hello 24 | echo From here! 25 | displayName: 'Run a multi-line script' 26 | 27 | - stage: C 28 | dependsOn: 29 | - A 30 | - B 31 | jobs: 32 | - deployment: C1 33 | displayName: C1 deploy 34 | environment: Test 35 | strategy: 36 | runOnce: 37 | deploy: 38 | steps: 39 | - script: echo Running in the Test environment as deployment job 40 | displayName: 'Test based stage' 41 | 42 | - stage: D 43 | jobs: 44 | - deployment: D1 45 | displayName: D1 deploy 46 | environment: QA 47 | strategy: 48 | runOnce: 49 | deploy: 50 | steps: 51 | - script: echo Running in the QA environment as deployment job 52 | displayName: 'QA based stage' 53 | -------------------------------------------------------------------------------- /Part04CICD/GitHubPipelines/readme.txt: -------------------------------------------------------------------------------- 1 | See the root .github\workflows folder for the pipelines used for GitHub demos -------------------------------------------------------------------------------- /Part05Secrets/CreateAzureCred.txt: -------------------------------------------------------------------------------- 1 | az ad sp create-for-rbac --name "github-devops" --sdk-auth --role contributor \ 2 | --scopes /subscriptions/YOURSUBID 3 | 4 | Note can change the role AND the scope. I will use this credential to deploy to any resource group in the entire subscription 5 | 6 | OUTPUT: 7 | 8 | { 9 | "clientId": "CLIENTID", 10 | "clientSecret": "CLIENTSECRET", 11 | "subscriptionId": "YOURSUBID", 12 | "tenantId": "TENANTID", 13 | "activeDirectoryEndpointUrl": "https://login.microsoftonline.com", 14 | "resourceManagerEndpointUrl": "https://management.azure.com/", 15 | "activeDirectoryGraphResourceId": "https://graph.windows.net/", 16 | "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/", 17 | "galleryEndpointUrl": "https://gallery.azure.com/", 18 | "managementEndpointUrl": "https://management.core.windows.net/" 19 | } -------------------------------------------------------------------------------- /Part05Secrets/DemoVMMngIdent.ps1: -------------------------------------------------------------------------------- 1 | Connect-AzAccount -Identity 2 | Get-AzContext 3 | 4 | #Note the -UseConnectedAccount to connect to storage using AAD data plane instead of account keys 5 | New-AzStorageContext -UseConnectedAccount -StorageAccountName sascussavilltech ` 6 | | Get-AzStorageBlobContent -Container 'images' -Blob 'OllieandEddieCerealEating.jpg' -Destination d:\ 7 | 8 | #View the service principal for the resource 9 | Get-AzADServicePrincipal -DisplayNameBeginsWith DemoVM #VM 10 | 11 | #View the system-assigned identity 12 | $VM = Get-AzVM -ResourceGroupName RG-DemoVM -Name DemoVM 13 | $VM.Identity.PrincipalId 14 | 15 | #Interact with Key Vault 16 | $secret = Get-AzKeyVaultSecret -VaultName 'SavillVaultRBAC' -Name 'Secret1' 17 | $text = $secret.SecretValue | ConvertFrom-SecureString -AsPlainText 18 | write-output $text -------------------------------------------------------------------------------- /Part06IaC/IISInstall.ps1: -------------------------------------------------------------------------------- 1 | Configuration WebConfig 2 | { 3 | param 4 | ( 5 | # Target nodes to apply the configuration 6 | [string[]]$NodeName = 'localhost' 7 | ) 8 | # Import the module that defines custom resources 9 | Import-DscResource -Module xWebAdministration 10 | Node $NodeName 11 | { 12 | # Install the IIS role 13 | WindowsFeature IIS 14 | { 15 | Ensure = "Present" 16 | Name = "Web-Server" 17 | } 18 | #Install ASP.NET 4.5 19 | WindowsFeature ASPNet45 20 | { 21 | Ensure = “Present” 22 | Name = “Web-Asp-Net45” 23 | } 24 | # Stop the default website 25 | xWebsite DefaultSite 26 | { 27 | Ensure = "Present" 28 | Name = "Default Web Site" 29 | State = "Stopped" 30 | PhysicalPath = "C:\inetpub\wwwroot" 31 | DependsOn = "[WindowsFeature]IIS" 32 | } 33 | # Copy the website content 34 | File WebContent 35 | { 36 | Ensure = "Present" 37 | SourcePath = "C:\Program Files\WindowsPowerShell\Modules\xWebAdministration\SavillSite" 38 | DestinationPath = "C:\inetpub\SavillSite" 39 | Recurse = $true 40 | Type = "Directory" 41 | DependsOn = "[WindowsFeature]AspNet45" 42 | } 43 | # Create a new website 44 | xWebsite SavTechWebSite 45 | { 46 | Ensure = "Present" 47 | Name = "SavillSite" 48 | State = "Started" 49 | PhysicalPath = "C:\inetpub\SavillSite" 50 | DependsOn = "[File]WebContent" 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /Part06IaC/demofile.ps1: -------------------------------------------------------------------------------- 1 | #Create a storage account 2 | #DEMO1 3 | New-AzStorageAccount -ResourceGroupName RG_PolicyTest ` 4 | -Name 'savilldemoavailable' ` 5 | -Location northeurope ` 6 | -SkuName Standard_ZRS ` 7 | -Kind StorageV2 8 | 9 | $errorlast = get-error 10 | $errorlast.Exception.Response.Content | ConvertFrom-Json | convertto-json -Depth 100 11 | 12 | 13 | #Bicep deploy 14 | #DEMO2 15 | cd .\Part06IaC 16 | New-AzResourceGroupDeployment -TemplateFile "storageaccount.bicep" -ResourceGroupName RG_PolicyTest ` 17 | -TemplateParameterFile "storageaccount-dev.bad.parameters.json" ` 18 | -WhatIf 19 | 20 | New-AzResourceGroupDeployment -TemplateFile "storageaccount.bicep" -ResourceGroupName RG_PolicyTest ` 21 | -TemplateParameterFile "storageaccount-dev.parameters.json" ` 22 | -WhatIf 23 | 24 | #Actually deploy 25 | New-AzResourceGroupDeployment -TemplateFile "storageaccount.bicep" -ResourceGroupName RG_PolicyTest ` 26 | -TemplateParameterFile "storageaccount-dev.parameters.json" 27 | 28 | #Declarative so can run again and update my new desired state 29 | New-AzResourceGroupDeployment -TemplateFile "storageaccount.bicep" -ResourceGroupName RG_PolicyTest ` 30 | -TemplateParameterFile "storageaccount-dev.parameters.json" ` 31 | -storageSku 'Standard_GRS' 32 | -------------------------------------------------------------------------------- /Part06IaC/storageaccount-dev.bad.parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "storageName": { 6 | "value": "sasavilleus007" 7 | }, 8 | "storageSku": { 9 | "value": "Standard_ZRS" 10 | }, 11 | "location": { 12 | "value": "northeurope" 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Part06IaC/storageaccount-dev.parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "storageName": { 6 | "value": "sasavilleus007007" 7 | }, 8 | "storageSku": { 9 | "value": "Standard_LRS" 10 | }, 11 | "location": { 12 | "value": "eastus" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Part06IaC/storageaccount.bicep: -------------------------------------------------------------------------------- 1 | param storageName string // must be globally unique 2 | param storageSku string = 'Standard_LRS' 3 | param location string = resourceGroup().location 4 | 5 | resource stg 'Microsoft.Storage/storageAccounts@2021-04-01' = { 6 | name: storageName 7 | location: location 8 | kind: 'Storage' 9 | sku: { 10 | name: storageSku // reference variable 11 | } 12 | } 13 | 14 | output storageId string = stg.id // output resourceId of storage account 15 | -------------------------------------------------------------------------------- /Part07Containers/AKSSQLServerDeployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: mssql-deployment 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: mssql 10 | template: 11 | metadata: 12 | labels: 13 | app: mssql 14 | spec: 15 | terminationGracePeriodSeconds: 10 16 | containers: 17 | - name: mssql 18 | image: mcr.microsoft.com/mssql/server:2019-latest 19 | ports: 20 | - containerPort: 1433 21 | env: 22 | - name: MSSQL_PID 23 | value: "Developer" 24 | - name: ACCEPT_EULA 25 | value: "Y" 26 | - name: SA_PASSWORD 27 | valueFrom: 28 | secretKeyRef: 29 | name: mssql 30 | key: SA_PASSWORD 31 | volumeMounts: 32 | - name: mssqldb 33 | mountPath: /var/opt/mssql 34 | volumes: 35 | - name: mssqldb 36 | persistentVolumeClaim: 37 | claimName: mssql-data 38 | --- 39 | apiVersion: v1 40 | kind: Service 41 | metadata: 42 | name: mssql-deployment 43 | spec: 44 | selector: 45 | app: mssql 46 | ports: 47 | - protocol: TCP 48 | port: 1433 49 | targetPort: 1433 50 | type: LoadBalancer 51 | -------------------------------------------------------------------------------- /Part07Containers/AKSStorageProviderandPVC.yaml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1 3 | metadata: 4 | name: azure-disk-custom 5 | provisioner: kubernetes.io/azure-disk 6 | reclaimPolicy: Retain 7 | allowVolumeExpansion: true 8 | parameters: 9 | storageaccounttype: Standard_LRS 10 | kind: Managed 11 | --- 12 | kind: PersistentVolumeClaim 13 | apiVersion: v1 14 | metadata: 15 | name: mssql-data 16 | spec: 17 | accessModes: 18 | - ReadWriteOnce 19 | storageClassName: azure-disk-custom 20 | resources: 21 | requests: 22 | storage: 8Gi -------------------------------------------------------------------------------- /Part07Containers/Docker/badfather/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/windows/servercore/iis 2 | RUN del C:\inetpub\wwwroot\iisstart.htm 3 | COPY /website /inetpub/wwwroot 4 | -------------------------------------------------------------------------------- /Part07Containers/Docker/badfather/website/default.htm: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Untitled 1 7 | 12 | 13 | 14 | 15 | 16 |

 

17 | 18 |

19 |

20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Part07Containers/Docker/badfather/website/page2.htm: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Untitled 1 7 | 12 | 13 | 14 | 15 | 16 |

 

17 |

 

18 |

19 |

20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Part07Containers/Docker/badfather/website/page3.htm: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Untitled 1 7 | 8 | 9 | 10 | 11 |

12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Part07Containers/Docker/badfather/website/pic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnthebrit/DevOpsMC/79dfbc0063ddf3622fd6bf6a9792a351a517b396/Part07Containers/Docker/badfather/website/pic.jpg -------------------------------------------------------------------------------- /Part07Containers/Docker/badfather/website/pic2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnthebrit/DevOpsMC/79dfbc0063ddf3622fd6bf6a9792a351a517b396/Part07Containers/Docker/badfather/website/pic2.jpg -------------------------------------------------------------------------------- /Part07Containers/Docker/badfather/website/pic2zoom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnthebrit/DevOpsMC/79dfbc0063ddf3622fd6bf6a9792a351a517b396/Part07Containers/Docker/badfather/website/pic2zoom.jpg -------------------------------------------------------------------------------- /Part07Containers/Docker/badfatherapache/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM httpd 2 | RUN rm /usr/local/apache2/htdocs/* 3 | COPY /website /usr/local/apache2/htdocs/ 4 | -------------------------------------------------------------------------------- /Part07Containers/Docker/badfatherapache/website/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Untitled 1 7 | 12 | 13 | 14 | 15 | 16 |

 

17 | 18 |

19 |

20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Part07Containers/Docker/badfatherapache/website/page2.htm: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Untitled 1 7 | 12 | 13 | 14 | 15 | 16 |

 

17 |

 

18 |

19 |

20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Part07Containers/Docker/badfatherapache/website/page3.htm: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Untitled 1 7 | 8 | 9 | 10 | 11 |

12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Part07Containers/Docker/badfatherapache/website/pic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnthebrit/DevOpsMC/79dfbc0063ddf3622fd6bf6a9792a351a517b396/Part07Containers/Docker/badfatherapache/website/pic.jpg -------------------------------------------------------------------------------- /Part07Containers/Docker/badfatherapache/website/pic2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnthebrit/DevOpsMC/79dfbc0063ddf3622fd6bf6a9792a351a517b396/Part07Containers/Docker/badfatherapache/website/pic2.jpg -------------------------------------------------------------------------------- /Part07Containers/Docker/badfatherapache/website/pic2zoom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnthebrit/DevOpsMC/79dfbc0063ddf3622fd6bf6a9792a351a517b396/Part07Containers/Docker/badfatherapache/website/pic2zoom.jpg -------------------------------------------------------------------------------- /Part07Containers/Docker/docker.ps1: -------------------------------------------------------------------------------- 1 | #region Windows Containers 2 | #This demo requires Windows Containers 3 | docker run -it mcr.microsoft.com/windows/servercore cmd.exe 4 | docker run -it --name demo1 -v C:\containerdata:c:\data mcr.microsoft.com/windows/servercore cmd.exe 5 | 6 | docker images 7 | #MS moved from docker hub https://github.com/microsoft/containerregistry/blob/main/docs/dockerhub-to-mcr-repo-mapping.md 8 | #mcr does NOT have a latest tag. Must specify a version 9 | docker pull mcr.microsoft.com/windows/servercore:ltsc2022 #previously microsoft/windowsservercore 10 | docker pull mcr.microsoft.com/windows/nanoserver:ltsc2022 11 | docker search sql 12 | docker pull mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2022 #previously microsoft/iis 13 | docker image history mcr.microsoft.com/windows/servercore/iis 14 | 15 | #Quick image 16 | Set-Location badfather 17 | docker build -t badfather . 18 | 19 | #Windows examples 20 | docker run --name iisdemo -it -p 80:80 badfather cmd 21 | #add --isolation=hyperv to make a Hyper-V container instead 22 | 23 | docker rmi badfather 24 | #endregion 25 | 26 | #region Linux Containers 27 | #Apache image 28 | docker images 29 | docker search --filter is-official=true httpd 30 | docker pull httpd 31 | docker image history httpd #view the layers 32 | docker image inspect httpd #detailed info about image 33 | docker run --name httpdrun -dit httpd bash 34 | 35 | #list containers 36 | docker ps -a 37 | $dockid = $(docker ps -a -q --filter "name=httpdrun") 38 | docker attach $dockid #Ctrl P Q to exit and leave running. Or exit to stop 39 | docker start $dockid 40 | docker stop $dockid 41 | docker rm $dockid 42 | 43 | Set-Location badfatherapache 44 | docker build -t badfather . 45 | docker history badfather 46 | docker images 47 | 48 | docker run -dit --name badfather-app -p 80:80 badfather 49 | $dockid = $(docker ps -a -q --filter "name=badfather-app") 50 | docker rmi badfather 51 | 52 | #Networking 53 | docker network ls 54 | docker network inspect bridge 55 | 56 | #endregion 57 | 58 | #region Azure and Docker Hub Interactions 59 | #Need to be logged into Azure first 60 | #https://docs.microsoft.com/en-us/azure/container-registry/container-registry-get-started-docker-cli?tabs=azure-cli#log-in-to-a-registry 61 | az acr login --name savilltech 62 | 63 | docker tag badfather savilltech.azurecr.io/images/badfather 64 | docker push savilltech.azurecr.io/images/badfather 65 | docker pull savilltech.azurecr.io/images/badfather 66 | docker image history savilltech.azurecr.io/images/badfather 67 | 68 | #Cleanup 69 | docker rmi savilltech.azurecr.io/images/badfather 70 | docker rmi badfather 71 | docker rmi httpd 72 | 73 | #talk to running ACI instance 74 | az container list --output table 75 | az container exec -g RG-ACI --name bad1 --container-name bad1 --exec-command "/bin/bash" 76 | 77 | 78 | #Docker Hub demo 79 | docker login #johnthebrit 80 | docker images 81 | docker tag a93a249d820c johnthebrit/badfather:latest 82 | docker push johnthebrit/badfather 83 | docker pull johnthebrit/badfather 84 | #endregion 85 | 86 | #region Bulk Cleanup 87 | #Remove all containers 88 | docker rm $(docker ps -a -q) 89 | 90 | #Remove all container images 91 | docker rmi $(docker images -q) 92 | #endregion -------------------------------------------------------------------------------- /Part07Containers/aks-badfather.yaml: -------------------------------------------------------------------------------- 1 | #https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: azure-badfather-web1 6 | spec: 7 | replicas: 2 8 | selector: 9 | matchLabels: 10 | app: azure-badfather-web1 11 | template: 12 | metadata: 13 | labels: 14 | app: azure-badfather-web1 15 | spec: 16 | containers: 17 | - name: azure-badfather-web1 18 | image: savilltech.azurecr.io/images/badfather 19 | resources: 20 | requests: 21 | cpu: 100m 22 | memory: 128Mi 23 | limits: 24 | cpu: 250m 25 | memory: 256Mi 26 | ports: 27 | - containerPort: 80 28 | --- 29 | apiVersion: v1 30 | kind: Service 31 | metadata: 32 | name: azure-badfather-web1 33 | annotations: 34 | service.beta.kubernetes.io/azure-load-balancer-tcp-idle-timeout: "4" 35 | # service.beta.kubernetes.io/azure-load-balancer-internal: "true" 36 | # service.beta.kubernetes.io/azure-load-balancer-internal-subnet: "svc" 37 | spec: 38 | type: LoadBalancer 39 | ports: 40 | - port: 80 41 | selector: 42 | app: azure-badfather-web1 43 | -------------------------------------------------------------------------------- /Part07Containers/k8sdemo.ps1: -------------------------------------------------------------------------------- 1 | az aks get-credentials --resource-group RG-AKS --name AKSCNI 2 | 3 | #View service principal for cluster 4 | az aks show --resource-group RG-AKS --name AKSCNI --query servicePrincipalProfile.clientId 5 | az ad sp show --id (az aks show --resource-group RG-AKS --name AKSCNI --query servicePrincipalProfile.clientId) 6 | 7 | #Install kubectl then have to update path to include it 8 | az aks install-cli 9 | 10 | #Get basic info 11 | kubectl cluster-info 12 | kubectl get nodes 13 | 14 | #Apply deployment 15 | kubectl apply -f aks-badfather.yaml 16 | 17 | #View information 18 | kubectl get pods -o wide 19 | kubectl get pods --show-labels 20 | kubectl get service 21 | kubectl describe svc azure-badfather-web1 22 | #note the endpoints for the frontend points to the IP of the frontend pod IP 23 | #this is the SERVICE in K8S, NOT the Azure Load Balancer 24 | kubectl get endpoints azure-badfather-web1 25 | 26 | 27 | #General other 28 | kubectl get service --all-namespaces 29 | #delete deployment 30 | kubectl delete -f aks-badfather.yaml -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Repository for John Savill's DevOps Master Class # 2 | 3 | ![DevOps Master Class](/Images/logosmall.png) 4 | 5 | This is the repository for the materials related to the DevOps Master Class 6 | 7 | All content Copyright 2021 John Savill. All rights reserved 8 | No part of this course to be used without express permission from the author 9 | john@savilltech.com 10 | @NTFAQGuy 11 | https://savilltech.com 12 | https://youtube.com/NTFAQGuy 13 | 14 | ## DevOps Master Class Assets 15 | 16 | [DevOps Master Class YouTube Playlist](https://www.youtube.com/playlist?list=PLlVtbbG169nFr8RzQ4GIxUEznpNR53ERq "DevOps Master Class Playlist") 17 | 18 | The class is designed to be viewed from start to finish in sequence as each module builds on the last. This repository provides a folder for each module. In each folder will typically find: 19 | 20 | - PDF in handout format of slides used 21 | - Image of the whiteboard created 22 | - Any other artifacts such as code samples 23 | 24 | Additionally, there are many recommended videos to watch for each module which are shown below. 25 | 26 | | Module | Additional Recommended Videos | 27 | |--|--| 28 | | [1 Foundation](https://youtu.be/YMdtaWfU_QE) | | 29 | | [2 Master Git](https://youtu.be/hQJktcBzJUs) | | 30 | | [3 ADO and GitHub](https://youtu.be/Z9evyML2I6M) | [VS Code in the browser](https://youtu.be/OyZyImXt4fc) | 31 | | [4 CI/CD](https://youtu.be/nLRHV2sRTe8) | [GitHub Actions Azure Deploy](https://youtu.be/FeSMRFkaRIU)| 32 | | [5 Secrets](https://youtu.be/b5F0WuTISAE) |[Managed Identity Overview](https://youtu.be/1NOZv2M3q2k)
[Unattended Authentication](https://youtu.be/7VMPtrqCehE)
[Azure Key Vault Deep Dive](https://youtu.be/kP7KpfToMkg)
[Azure Key Vault Auth Options](https://youtu.be/oYzFWOrZMKc) | 33 | | [6 Infrastructure as Code](https://youtu.be/8AgEwM8RhAU) | [Imperative vs Declarative](https://youtu.be/scH6M1oRucA)
[Terraform with Azure](https://youtu.be/JKVkblsp3cM)
[Project Bicep Overview](https://youtu.be/_yvb6NVx61Y)
[GitHub Actions Azure Deploy](https://youtu.be/FeSMRFkaRIU)
[Azure Naming Convention](https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming)
[Azure Tagging](https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-tagging)| 34 | | [7 Containers & Friends](https://youtu.be/r6YIlPEC4y4) | [AKS Networking Deep Dive](https://youtu.be/6TZsd4toIbg)
[AKS High Availaiblity](https://youtu.be/gksFrKiZjMc) | 35 | | [8 Monitoring & Feedback](https://youtu.be/ypT4S17kiJw) | [Azure Monitoring](https://youtu.be/hTS8jXEX_88) | 36 | 37 | ## Getting a Clone 38 | Once Git is installed to have a local clone of the repository: 39 | 40 | ```sh 41 | mkdir C:\DevOpsMC 42 | cd c:\DevOpsMC 43 | git clone https://github.com/johnthebrit/DevOpsMC.git . 44 | ``` 45 | 46 | To update, make sure you are in the folder downloaded to and run 47 | 48 | ```sh 49 | git pull 50 | ``` 51 | 52 | ## Useful Links and Info 53 | 54 | | Feature | Link | 55 | |----------------------|----------------------------------------------------------------------------------| 56 | | Visual Studio Code | https://code.visualstudio.com/Download | 57 | | Git | https://git-scm.com/downloads | 58 | | Azure Sub | https://azure.microsoft.com/en-us/free/ | 59 | | GitHub Account | https://github.com/pricing | 60 | | Azure DevOps Account | https://azure.microsoft.com/en-us/pricing/details/devops/azure-devops-services/ | --------------------------------------------------------------------------------