mirror of
https://github.com/foo-dogsquared/wiki.git
synced 2025-02-07 09:18:59 +00:00
Update notes on the Cloud native computing course
This commit is contained in:
parent
dd30ae7cc4
commit
1c1be4a496
@ -0,0 +1,23 @@
|
|||||||
|
import logging
|
||||||
|
from flask import Flask
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@app.route("/")
|
||||||
|
def hello():
|
||||||
|
logging.info("/ endpoint was reached")
|
||||||
|
return "Hello World!"
|
||||||
|
|
||||||
|
@app.route("/status")
|
||||||
|
def health_check():
|
||||||
|
logging.info("/status endpoint was reached")
|
||||||
|
return { "result": "OK - healthy" }
|
||||||
|
|
||||||
|
@app.route("/metrics")
|
||||||
|
def metrics():
|
||||||
|
logging.info("/metrics endpoint was reached")
|
||||||
|
return { "data": { "UserCount": 140, "UserCountActive": 23} }
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
logging.basicConfig(format="%(asctime)s, %(message)s", level=logging.DEBUG, filename="app.log")
|
||||||
|
app.run(host='0.0.0.0')
|
@ -0,0 +1,19 @@
|
|||||||
|
OWNER="foodogsquared"
|
||||||
|
IMG="go-helloworld"
|
||||||
|
VERSION="1.0.0"
|
||||||
|
REMOTE_IMG="${OWNER}/${IMG}:v${VERSION}"
|
||||||
|
|
||||||
|
# Build the image with the tag already in place.
|
||||||
|
podman build --tag "$IMG" .
|
||||||
|
|
||||||
|
# Run the packaged app.
|
||||||
|
podman run -d -p 6111:6111 "$IMG"
|
||||||
|
|
||||||
|
# Verify it's running.
|
||||||
|
podman ps
|
||||||
|
|
||||||
|
# Create another image to push it into the Docker registry with the proper naming.
|
||||||
|
podman tag "$IMG" "$REMOTE_IMG"
|
||||||
|
|
||||||
|
# Push the image to the Docker registry.
|
||||||
|
podman push "$REMOTE_IMG"
|
@ -0,0 +1,26 @@
|
|||||||
|
name: Docker build image
|
||||||
|
on: [push]
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v1
|
||||||
|
- name: Setup Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Build and push
|
||||||
|
id: docker_build
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
tags: ${{ secrets.DOCKERHUB_USERNAME }}/python-helloworld:latest
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
- name: Image digest
|
||||||
|
run: echo ${{ steps.docker_build.outputs.digest }}
|
@ -0,0 +1,17 @@
|
|||||||
|
from flask import Flask
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@app.route("/")
|
||||||
|
def hello():
|
||||||
|
return "Hello World!"
|
||||||
|
|
||||||
|
@app.route("/status")
|
||||||
|
def health_check():
|
||||||
|
return { "result": "OK - healthy" }
|
||||||
|
|
||||||
|
@app.route("/metrics")
|
||||||
|
def metrics():
|
||||||
|
return { "data": { "UserCount": 140, "UserCountActive": 23} }
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(host='0.0.0.0')
|
Binary file not shown.
After Width: | Height: | Size: 341 KiB |
@ -0,0 +1,55 @@
|
|||||||
|
article {
|
||||||
|
// Named after the LaTeX counters after `chapter` counter.
|
||||||
|
counter-reset: section subsection subsubsection paragraph subparagraph;
|
||||||
|
--counter-spacing: 0.5rem;
|
||||||
|
|
||||||
|
// <h2> is used as a section header since <h1> is the main title
|
||||||
|
h2 {
|
||||||
|
counter-reset: subsection;
|
||||||
|
counter-increment: section;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: counter(section) ".";
|
||||||
|
margin-right: var(--counter-spacing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
counter-reset: subsubsection;
|
||||||
|
counter-increment: subsection;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: counter(section) "." counter(subsection) ".";
|
||||||
|
margin-right: var(--counter-spacing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
counter-reset: paragraph;
|
||||||
|
counter-increment: subsubsection;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: counter(section) "." counter(subsection) "." counter(subsubsection) ".";
|
||||||
|
margin-right: var(--counter-spacing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
counter-reset: subparagraph;
|
||||||
|
counter-increment: paragraph;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: counter(section) "." counter(subsection) "." counter(subsubsection) "." counter(paragraph) ".";
|
||||||
|
margin-right: var(--counter-spacing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
counter-increment: subparagraph;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: counter(section) "." counter(subsection) "." counter(subsubsection) "." counter(paragraph) "." counter(subparagraph);
|
||||||
|
margin-right: var(--counter-spacing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
@use 'sass:string';
|
||||||
|
|
||||||
|
@function tier-heading($counters) {
|
||||||
|
$str: "";
|
||||||
|
@for $level from 1 through $counters {
|
||||||
|
$str: $str + 'counter(h#{$level})"."';
|
||||||
|
}
|
||||||
|
@return string.unquote($str);
|
||||||
|
}
|
||||||
|
|
||||||
|
article {
|
||||||
|
--counter-spacing: 0.5rem;
|
||||||
|
@for $level from 1 through 6 {
|
||||||
|
counter-reset: h#{$level};
|
||||||
|
|
||||||
|
h#{$level}{
|
||||||
|
@if $level != 6 {
|
||||||
|
counter-reset: h#{$level + 1};
|
||||||
|
}
|
||||||
|
counter-increment: h#{$level};
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: tier-heading($level);
|
||||||
|
margin-right: var(--counter-spacing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
:END:
|
:END:
|
||||||
#+title: Solutions to SUSE Cloud native fundamentals scholarship exercises
|
#+title: Solutions to SUSE Cloud native fundamentals scholarship exercises
|
||||||
#+date: "2021-06-08 23:23:35 +08:00"
|
#+date: "2021-06-08 23:23:35 +08:00"
|
||||||
#+date_modified: "2021-06-19 21:09:41 +08:00"
|
#+date_modified: "2021-06-21 10:54:53 +08:00"
|
||||||
#+language: en
|
#+language: en
|
||||||
|
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ CMD ["./helloworld"]
|
|||||||
|
|
||||||
As for the requirements of the images and running the containerized app, we'll summarize it with the following Bash script.
|
As for the requirements of the images and running the containerized app, we'll summarize it with the following Bash script.
|
||||||
|
|
||||||
#+begin_src bash
|
#+begin_src bash :tangle (my/concat-assets-folder "docker-packaging.sh")
|
||||||
OWNER="foodogsquared"
|
OWNER="foodogsquared"
|
||||||
IMG="go-helloworld"
|
IMG="go-helloworld"
|
||||||
VERSION="1.0.0"
|
VERSION="1.0.0"
|
||||||
@ -532,9 +532,9 @@ To set up these credentials refer to the following resources:
|
|||||||
|
|
||||||
After creating a DockerHub access token (that serves as an alternative to passwords) and creating a GitHub encrypted secret, the workflow should now work.
|
After creating a DockerHub access token (that serves as an alternative to passwords) and creating a GitHub encrypted secret, the workflow should now work.
|
||||||
|
|
||||||
Here's the resulting workflow file:
|
Here's the resulting GitHub Actions workflow file:
|
||||||
|
|
||||||
#+begin_src yaml
|
#+begin_src yaml :tangle (my/concat-assets-folder "github-docker-workflow.yaml")
|
||||||
name: Docker build image
|
name: Docker build image
|
||||||
on: [push]
|
on: [push]
|
||||||
jobs:
|
jobs:
|
||||||
|
17
structured/cloud.github-actions.org
Normal file
17
structured/cloud.github-actions.org
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#+title: GitHub Actions
|
||||||
|
#+date: "2021-06-20 18:58:48 +08:00"
|
||||||
|
#+date_modified: "2021-06-20 20:13:03 +08:00"
|
||||||
|
#+language: en
|
||||||
|
|
||||||
|
|
||||||
|
#+ATTR_ORG: :width 550
|
||||||
|
[[file:assets/cloud.github-actions/fds-visual-github-actions-description.png]]
|
||||||
|
|
||||||
|
- a CI/CD tool integrated into GitHub
|
||||||
|
- it is free for public repos but limited time per month for private repos
|
||||||
|
- focused into creating workflows which can be separate and applied in different contexts
|
||||||
|
+ a workflow is activated from an event
|
||||||
|
+ stored in ~.github/workflows~ in the remote repo
|
||||||
|
- each workflow can run a job which are composed of steps
|
||||||
|
- each step make uses an action which is basically a script;
|
||||||
|
it can interact with the repo or do something else entirely without ever touching it
|
105
structured/cookbook.css.implementing-numbered-headings.org
Normal file
105
structured/cookbook.css.implementing-numbered-headings.org
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
:PROPERTIES:
|
||||||
|
:ID: 6d425762-ab9c-463f-b17a-e2a116b12fa0
|
||||||
|
:END:
|
||||||
|
#+title: Implementing tiered headings with CSS
|
||||||
|
#+date: "2021-06-20 10:31:00 +08:00"
|
||||||
|
#+date_modified: "2021-06-20 18:16:24 +08:00"
|
||||||
|
#+language: en
|
||||||
|
|
||||||
|
|
||||||
|
You may have seen certain documents with [[https://practicaltypography.com/hierarchical-headings.html][tiered headings]].
|
||||||
|
To implement this with pure CSS, we'll make heavy use of [[https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Lists_and_Counters/Using_CSS_counters][CSS counters]].
|
||||||
|
|
||||||
|
Here is one rough implementation with SCSS.
|
||||||
|
|
||||||
|
#+begin_src scss :tangle (my/concat-assets-folder "naive-tiered-headings.scss")
|
||||||
|
article {
|
||||||
|
// Named after the LaTeX counters after `chapter` counter.
|
||||||
|
counter-reset: section subsection subsubsection paragraph subparagraph;
|
||||||
|
--counter-spacing: 0.5rem;
|
||||||
|
|
||||||
|
// <h2> is used as a section header since <h1> is the main title
|
||||||
|
h2 {
|
||||||
|
counter-reset: subsection;
|
||||||
|
counter-increment: section;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: counter(section) ".";
|
||||||
|
margin-right: var(--counter-spacing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
counter-reset: subsubsection;
|
||||||
|
counter-increment: subsection;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: counter(section) "." counter(subsection) ".";
|
||||||
|
margin-right: var(--counter-spacing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
counter-reset: paragraph;
|
||||||
|
counter-increment: subsubsection;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: counter(section) "." counter(subsection) "." counter(subsubsection) ".";
|
||||||
|
margin-right: var(--counter-spacing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
counter-reset: subparagraph;
|
||||||
|
counter-increment: paragraph;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: counter(section) "." counter(subsection) "." counter(subsubsection) "." counter(paragraph) ".";
|
||||||
|
margin-right: var(--counter-spacing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
counter-increment: subparagraph;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: counter(section) "." counter(subsection) "." counter(subsubsection) "." counter(paragraph) "." counter(subparagraph);
|
||||||
|
margin-right: var(--counter-spacing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
This is enough for CSS but since we're using SCSS, we can optimize it further.
|
||||||
|
You may notice that each level is similar with the difference being the content and their counter name.
|
||||||
|
|
||||||
|
#+begin_src scss :tangle (my/concat-assets-folder "optimized-tiered-headings.scss")
|
||||||
|
@use 'sass:string';
|
||||||
|
|
||||||
|
@function tier-heading($counters) {
|
||||||
|
$str: "";
|
||||||
|
@for $level from 1 through $counters {
|
||||||
|
$str: $str + 'counter(h#{$level})"."';
|
||||||
|
}
|
||||||
|
@return string.unquote($str);
|
||||||
|
}
|
||||||
|
|
||||||
|
article {
|
||||||
|
--counter-spacing: 0.5rem;
|
||||||
|
@for $level from 1 through 6 {
|
||||||
|
counter-reset: h#{$level};
|
||||||
|
|
||||||
|
h#{$level}{
|
||||||
|
@if $level != 6 {
|
||||||
|
counter-reset: h#{$level + 1};
|
||||||
|
}
|
||||||
|
counter-increment: h#{$level};
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: tier-heading($level);
|
||||||
|
margin-right: var(--counter-spacing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#+end_src
|
@ -1,6 +1,6 @@
|
|||||||
#+title: Network configuration in Linux
|
#+title: Network configuration in Linux
|
||||||
#+date: "2021-05-31 13:07:38 +08:00"
|
#+date: "2021-05-31 13:07:38 +08:00"
|
||||||
#+date_modified: "2021-05-31 14:49:03 +08:00"
|
#+date_modified: "2021-06-20 20:20:51 +08:00"
|
||||||
#+language: en
|
#+language: en
|
||||||
|
|
||||||
|
|
||||||
@ -9,6 +9,7 @@
|
|||||||
To access the internet, you need the following components:
|
To access the internet, you need the following components:
|
||||||
|
|
||||||
- The driver of the network device installed and enabled.
|
- The driver of the network device installed and enabled.
|
||||||
|
(See [[id:a7d9897e-fbaa-4ab1-a26d-4a86d2621df8][Linux drivers]] for more details.)
|
||||||
- A network manager to manage your network devices ;p
|
- A network manager to manage your network devices ;p
|
||||||
- A DNS resolver to access domain names which are aliases to IP addresses.
|
- A DNS resolver to access domain names which are aliases to IP addresses.
|
||||||
|
|
||||||
@ -18,17 +19,16 @@ To access the internet, you need the following components:
|
|||||||
* Network manager configuration
|
* Network manager configuration
|
||||||
|
|
||||||
With a systemd-ful environment, you can run the network daemon (i.e., =systemd-networkd=).
|
With a systemd-ful environment, you can run the network daemon (i.e., =systemd-networkd=).
|
||||||
Once enabled, you can run =networkctl= to list all of the network devices.
|
Once enabled, you can run =networkctl= to list all of the network devices. [fn:: You can also run ~ip address~ for it.]
|
||||||
[fn:: You can also run ~ip address~ for it.]
|
|
||||||
|
|
||||||
#+begin_src shell
|
#+begin_src shell :cache yes
|
||||||
networkctl
|
networkctl
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
#+results:
|
#+results[84c83a400d07ef38e6813bc9ce677cef8a38bd66]:
|
||||||
: IDX LINK TYPE OPERATIONAL SETUP
|
: IDX LINK TYPE OPERATIONAL SETUP
|
||||||
: 1 lo loopback carrier unmanaged
|
: 1 lo loopback carrier unmanaged
|
||||||
: 2 enp1s0 ether off unmanaged
|
: 2 enp1s0 ether routable configured
|
||||||
: 3 wlan0 wlan routable configured
|
: 3 wlan0 wlan routable configured
|
||||||
:
|
:
|
||||||
: 3 links listed.
|
: 3 links listed.
|
||||||
@ -60,8 +60,7 @@ RouteMetric=1024
|
|||||||
* DNS server configuration
|
* DNS server configuration
|
||||||
|
|
||||||
While the network manager is enabled, you can access the internet.
|
While the network manager is enabled, you can access the internet.
|
||||||
But only with raw IP addresses (e.g., 1.1.1.1 from Cloudflare, 93.174.95.27 for Library Genesis).
|
But only with raw IP addresses (e.g., 1.1.1.1 from Cloudflare, 93.174.95.27 for Library Genesis). [fn:: You can find the IP addresses with DNS clients such as [[https://github.com/ogham/dog][dog]] or the [[https://nodejs.org/api/dns.html][DNS library from NodeJS]].]
|
||||||
[fn:: You can find the IP addresses with DNS clients such as [[https://github.com/ogham/dog][dog]] or the [[https://nodejs.org/api/dns.html][DNS library from NodeJS]].]
|
|
||||||
|
|
||||||
Accessing the domain names as you would browse the web normally is an additional layer of the web.
|
Accessing the domain names as you would browse the web normally is an additional layer of the web.
|
||||||
To access a domain name, you need a DNS client that can resolve them.
|
To access a domain name, you need a DNS client that can resolve them.
|
||||||
|
Loading…
Reference in New Issue
Block a user