Upload 176 files
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +2 -35
- .github/SECURITY.md +16 -0
- .github/workflows/test.yml +30 -0
- .gitignore +3 -0
- Dockerfile +23 -0
- Dockerfile.l2 +27 -0
- LICENSE +21 -0
- api.go +82 -0
- config/config.go +78 -0
- docker-compose.yml +42 -0
- docker/docker.go +546 -0
- docker/factory.go +70 -0
- docker/factory_mock.go +20 -0
- docker/local_cached_factory.go +113 -0
- docker/mock.go +160 -0
- dockerfiles/dind/.editorconfig +14 -0
- dockerfiles/dind/.gitconfig +2 -0
- dockerfiles/dind/.inputrc +73 -0
- dockerfiles/dind/.profile +6 -0
- dockerfiles/dind/.vimrc +6 -0
- dockerfiles/dind/Dockerfile +69 -0
- dockerfiles/dind/Dockerfile.dind-ee +54 -0
- dockerfiles/dind/copy_certs.ps1 +114 -0
- dockerfiles/dind/daemon.json +17 -0
- dockerfiles/dind/docker-prompt +22 -0
- dockerfiles/dind/ee/cert.pem +29 -0
- dockerfiles/dind/ee/daemon.json +10 -0
- dockerfiles/dind/ee/key.pem +51 -0
- dockerfiles/dind/ee/ucp-cert.pem +63 -0
- dockerfiles/dind/ee/ucp-key.pem +28 -0
- dockerfiles/dind/motd +8 -0
- dockerfiles/dind/ssh_config +2 -0
- dockerfiles/dind/sudo +5 -0
- dockerfiles/dind/ucp-beta.sh +98 -0
- dockerfiles/dind/ucp-config.toml +2 -0
- dockerfiles/dind/ucp.sh +94 -0
- dockerfiles/dind/workshop.lic +1 -0
- dockerfiles/k8s/.bashrc +3 -0
- dockerfiles/k8s/Dockerfile +44 -0
- dockerfiles/k8s/daemon.json +14 -0
- dockerfiles/k8s/docker.service +30 -0
- dockerfiles/k8s/kubelet.env +6 -0
- dockerfiles/k8s/kubelet.service +4 -0
- dockerfiles/k8s/kubernetes.repo +7 -0
- dockerfiles/k8s/motd +28 -0
- dockerfiles/k8s/resolv.conf.override +1 -0
- dockerfiles/k8s/systemctl +281 -0
- dockerfiles/k8s/tokens.csv +1 -0
- dockerfiles/k8s/wrapkubeadm.sh +153 -0
- dockerfiles/pwm/.gitconfig +2 -0
.gitattributes
CHANGED
|
@@ -1,35 +1,2 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 1 |
+
config/gen_bindata.go linguist-generated
|
| 2 |
+
handlers/www/assets/swarm.png filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.github/SECURITY.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Security Policy
|
| 2 |
+
|
| 3 |
+
## Reporting a Vulnerability
|
| 4 |
+
|
| 5 |
+
If there are any vulnerabilities in this project or in [the playground](https://labs.play-with-docker.com), don't hesitate to _report them_.
|
| 6 |
+
|
| 7 |
+
1. Write an email to marcosnils (at) gmail.com
|
| 8 |
+
2. Describe the vulnerability.
|
| 9 |
+
|
| 10 |
+
If you have a fix, that is most welcome -- please attach or summarize it in your message!
|
| 11 |
+
|
| 12 |
+
3. We will evaluate the vulnerability and, if necessary, release a fix or mitigating steps to address it. We will contact you to let you know the outcome, and will credit you in the report.
|
| 13 |
+
|
| 14 |
+
Please **do not disclose the vulnerability publicly** until a fix is released!
|
| 15 |
+
|
| 16 |
+
4. Once we have either a) published a fix, or b) declined to address the vulnerability for whatever reason, you are free to publicly disclose it.
|
.github/workflows/test.yml
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
on:
|
| 2 |
+
push:
|
| 3 |
+
branches:
|
| 4 |
+
- master
|
| 5 |
+
pull_request:
|
| 6 |
+
branches:
|
| 7 |
+
- '**'
|
| 8 |
+
|
| 9 |
+
name: Go
|
| 10 |
+
jobs:
|
| 11 |
+
test:
|
| 12 |
+
strategy:
|
| 13 |
+
fail-fast: false
|
| 14 |
+
matrix:
|
| 15 |
+
os: [ubuntu-latest]
|
| 16 |
+
go_version: ["1.16.0"]
|
| 17 |
+
runs-on: ${{ matrix.os }}
|
| 18 |
+
steps:
|
| 19 |
+
- name: Checkout code
|
| 20 |
+
uses: actions/checkout@v2
|
| 21 |
+
- name: Install Go
|
| 22 |
+
uses: actions/setup-go@v2
|
| 23 |
+
with:
|
| 24 |
+
go-version: ${{ matrix.go_version }}
|
| 25 |
+
- name: Generate
|
| 26 |
+
run: go generate ./...
|
| 27 |
+
- name: Test
|
| 28 |
+
run: go test ./...
|
| 29 |
+
- name: Verify clean commit
|
| 30 |
+
run: test -z "$(git status --porcelain)" || (git status; git diff; false)
|
.gitignore
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
play-with-docker
|
| 2 |
+
node_modules
|
| 3 |
+
/vendor
|
Dockerfile
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM golang:1.16
|
| 2 |
+
|
| 3 |
+
COPY . /go/src/github.com/play-with-docker/play-with-docker
|
| 4 |
+
|
| 5 |
+
WORKDIR /go/src/github.com/play-with-docker/play-with-docker
|
| 6 |
+
|
| 7 |
+
RUN ssh-keygen -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key >/dev/null
|
| 8 |
+
|
| 9 |
+
RUN CGO_ENABLED=0 go build -a -installsuffix nocgo -o /go/bin/play-with-docker .
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
FROM alpine
|
| 13 |
+
|
| 14 |
+
RUN apk --update add ca-certificates
|
| 15 |
+
RUN mkdir -p /app/pwd
|
| 16 |
+
|
| 17 |
+
COPY --from=0 /go/bin/play-with-docker /app/play-with-docker
|
| 18 |
+
COPY --from=0 /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_rsa_key
|
| 19 |
+
|
| 20 |
+
WORKDIR /app
|
| 21 |
+
CMD ["./play-with-docker"]
|
| 22 |
+
|
| 23 |
+
EXPOSE 3000
|
Dockerfile.l2
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM golang:1.9
|
| 2 |
+
|
| 3 |
+
# Copy the runtime dockerfile into the context as Dockerfile
|
| 4 |
+
COPY . /go/src/github.com/play-with-docker/play-with-docker
|
| 5 |
+
|
| 6 |
+
WORKDIR /go/src/github.com/play-with-docker/play-with-docker
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
RUN ssh-keygen -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key >/dev/null
|
| 10 |
+
|
| 11 |
+
WORKDIR /go/src/github.com/play-with-docker/play-with-docker/router/l2
|
| 12 |
+
|
| 13 |
+
RUN CGO_ENABLED=0 go build -a -installsuffix nocgo -o /go/bin/play-with-docker-l2 .
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
FROM alpine
|
| 17 |
+
|
| 18 |
+
RUN apk --update add ca-certificates
|
| 19 |
+
RUN mkdir /app
|
| 20 |
+
|
| 21 |
+
COPY --from=0 /go/bin/play-with-docker-l2 /app/play-with-docker-l2
|
| 22 |
+
COPY --from=0 /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_rsa_key
|
| 23 |
+
|
| 24 |
+
WORKDIR /app
|
| 25 |
+
CMD ["./play-with-docker-l2", "-ssh_key_path", "/etc/ssh/ssh_host_rsa_key"]
|
| 26 |
+
|
| 27 |
+
EXPOSE 22 53 443 8080
|
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2016 Marcos Lilljedhal and Jonathan Leibiusky
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
api.go
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package main
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"log"
|
| 5 |
+
"os"
|
| 6 |
+
"time"
|
| 7 |
+
|
| 8 |
+
"github.com/play-with-docker/play-with-docker/config"
|
| 9 |
+
"github.com/play-with-docker/play-with-docker/docker"
|
| 10 |
+
"github.com/play-with-docker/play-with-docker/event"
|
| 11 |
+
"github.com/play-with-docker/play-with-docker/handlers"
|
| 12 |
+
"github.com/play-with-docker/play-with-docker/id"
|
| 13 |
+
"github.com/play-with-docker/play-with-docker/k8s"
|
| 14 |
+
"github.com/play-with-docker/play-with-docker/provisioner"
|
| 15 |
+
"github.com/play-with-docker/play-with-docker/pwd"
|
| 16 |
+
"github.com/play-with-docker/play-with-docker/pwd/types"
|
| 17 |
+
"github.com/play-with-docker/play-with-docker/scheduler"
|
| 18 |
+
"github.com/play-with-docker/play-with-docker/scheduler/task"
|
| 19 |
+
"github.com/play-with-docker/play-with-docker/storage"
|
| 20 |
+
)
|
| 21 |
+
|
| 22 |
+
func main() {
|
| 23 |
+
config.ParseFlags()
|
| 24 |
+
|
| 25 |
+
e := initEvent()
|
| 26 |
+
s := initStorage()
|
| 27 |
+
df := initDockerFactory(s)
|
| 28 |
+
kf := initK8sFactory(s)
|
| 29 |
+
|
| 30 |
+
ipf := provisioner.NewInstanceProvisionerFactory(provisioner.NewWindowsASG(df, s), provisioner.NewDinD(id.XIDGenerator{}, df, s))
|
| 31 |
+
sp := provisioner.NewOverlaySessionProvisioner(df)
|
| 32 |
+
|
| 33 |
+
core := pwd.NewPWD(df, e, s, sp, ipf)
|
| 34 |
+
|
| 35 |
+
tasks := []scheduler.Task{
|
| 36 |
+
task.NewCheckPorts(e, df),
|
| 37 |
+
task.NewCheckSwarmPorts(e, df),
|
| 38 |
+
task.NewCheckSwarmStatus(e, df),
|
| 39 |
+
task.NewCollectStats(e, df, s),
|
| 40 |
+
task.NewCheckK8sClusterStatus(e, kf),
|
| 41 |
+
task.NewCheckK8sClusterExposedPorts(e, kf),
|
| 42 |
+
}
|
| 43 |
+
sch, err := scheduler.NewScheduler(tasks, s, e, core)
|
| 44 |
+
if err != nil {
|
| 45 |
+
log.Fatal("Error initializing the scheduler: ", err)
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
sch.Start()
|
| 49 |
+
|
| 50 |
+
d, err := time.ParseDuration("2h")
|
| 51 |
+
if err != nil {
|
| 52 |
+
log.Fatalf("Cannot parse duration Got: %v", err)
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
playground := types.Playground{Domain: config.PlaygroundDomain, DefaultDinDInstanceImage: "franela/dind", AvailableDinDInstanceImages: []string{"franela/dind"}, AllowWindowsInstances: config.NoWindows, DefaultSessionDuration: d, Extras: map[string]interface{}{"LoginRedirect": "http://localhost:3000"}, Privileged: true}
|
| 56 |
+
if _, err := core.PlaygroundNew(playground); err != nil {
|
| 57 |
+
log.Fatalf("Cannot create default playground. Got: %v", err)
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
handlers.Bootstrap(core, e)
|
| 61 |
+
handlers.Register(nil)
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
func initStorage() storage.StorageApi {
|
| 65 |
+
s, err := storage.NewFileStorage(config.SessionsFile)
|
| 66 |
+
if err != nil && !os.IsNotExist(err) {
|
| 67 |
+
log.Fatal("Error initializing StorageAPI: ", err)
|
| 68 |
+
}
|
| 69 |
+
return s
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
func initEvent() event.EventApi {
|
| 73 |
+
return event.NewLocalBroker()
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
func initDockerFactory(s storage.StorageApi) docker.FactoryApi {
|
| 77 |
+
return docker.NewLocalCachedFactory(s)
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
func initK8sFactory(s storage.StorageApi) k8s.FactoryApi {
|
| 81 |
+
return k8s.NewLocalCachedFactory(s)
|
| 82 |
+
}
|
config/config.go
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package config
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"flag"
|
| 5 |
+
"os"
|
| 6 |
+
"regexp"
|
| 7 |
+
|
| 8 |
+
"github.com/gorilla/securecookie"
|
| 9 |
+
|
| 10 |
+
"golang.org/x/oauth2"
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
const (
|
| 14 |
+
PWDHostnameRegex = "[0-9]{1,3}-[0-9]{1,3}-[0-9]{1,3}-[0-9]{1,3}"
|
| 15 |
+
PortRegex = "[0-9]{1,5}"
|
| 16 |
+
AliasnameRegex = "[0-9|a-z|A-Z|-]*"
|
| 17 |
+
AliasSessionRegex = "[0-9|a-z|A-Z]{8}"
|
| 18 |
+
AliasGroupRegex = "(" + AliasnameRegex + ")-(" + AliasSessionRegex + ")"
|
| 19 |
+
PWDHostPortGroupRegex = "^.*ip(" + PWDHostnameRegex + ")(?:-?(" + PortRegex + "))?(?:\\..*)?$"
|
| 20 |
+
AliasPortGroupRegex = "^.*pwd" + AliasGroupRegex + "(?:-?(" + PortRegex + "))?\\..*$"
|
| 21 |
+
)
|
| 22 |
+
|
| 23 |
+
var (
|
| 24 |
+
NameFilter = regexp.MustCompile(PWDHostPortGroupRegex)
|
| 25 |
+
AliasFilter = regexp.MustCompile(AliasPortGroupRegex)
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
var (
|
| 29 |
+
PortNumber, SessionsFile, PWDContainerName, L2ContainerName, L2Subdomain, HashKey, SSHKeyPath, L2RouterIP, CookieHashKey, CookieBlockKey string
|
| 30 |
+
UseLetsEncrypt, ExternalDindVolume, NoWindows bool
|
| 31 |
+
LetsEncryptCertsDir string
|
| 32 |
+
MaxLoadAvg float64
|
| 33 |
+
ForceTLS bool
|
| 34 |
+
SecureCookie *securecookie.SecureCookie
|
| 35 |
+
AdminToken string
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
// Unsafe enables a number of unsafe features when set. It is principally
|
| 39 |
+
// intended to be used in development. For example, it allows the caller to
|
| 40 |
+
// specify the Docker networks to join.
|
| 41 |
+
var Unsafe bool
|
| 42 |
+
|
| 43 |
+
var PlaygroundDomain string
|
| 44 |
+
|
| 45 |
+
var SegmentId string
|
| 46 |
+
|
| 47 |
+
// TODO move this to a sync map so it can be updated on demand when the configuration for a playground changes
|
| 48 |
+
var Providers = map[string]map[string]*oauth2.Config{}
|
| 49 |
+
|
| 50 |
+
func ParseFlags() {
|
| 51 |
+
flag.StringVar(&LetsEncryptCertsDir, "letsencrypt-certs-dir", "/certs", "Path where let's encrypt certs will be stored")
|
| 52 |
+
flag.BoolVar(&UseLetsEncrypt, "letsencrypt-enable", false, "Enabled let's encrypt tls certificates")
|
| 53 |
+
flag.BoolVar(&ForceTLS, "tls", false, "Use TLS to connect to docker daemons")
|
| 54 |
+
flag.StringVar(&PortNumber, "port", "3000", "Port number")
|
| 55 |
+
flag.StringVar(&SessionsFile, "save", "./pwd/sessions", "Tell where to store sessions file")
|
| 56 |
+
flag.StringVar(&PWDContainerName, "name", "pwd", "Container name used to run PWD (used to be able to connect it to the networks it creates)")
|
| 57 |
+
flag.StringVar(&L2ContainerName, "l2", "l2", "Container name used to run L2 Router")
|
| 58 |
+
flag.StringVar(&L2RouterIP, "l2-ip", "", "Host IP address for L2 router ping response")
|
| 59 |
+
flag.StringVar(&L2Subdomain, "l2-subdomain", "direct", "Subdomain to the L2 Router")
|
| 60 |
+
flag.StringVar(&HashKey, "hash_key", "salmonrosado", "Hash key to use for cookies")
|
| 61 |
+
flag.BoolVar(&NoWindows, "win-disable", false, "Disable windows instances")
|
| 62 |
+
flag.BoolVar(&ExternalDindVolume, "dind-external-volume", false, "Use external dind volume though XFS volume driver")
|
| 63 |
+
flag.Float64Var(&MaxLoadAvg, "maxload", 100, "Maximum allowed load average before failing ping requests")
|
| 64 |
+
flag.StringVar(&SSHKeyPath, "ssh_key_path", "", "SSH Private Key to use")
|
| 65 |
+
flag.StringVar(&CookieHashKey, "cookie-hash-key", "", "Hash key to use to validate cookies")
|
| 66 |
+
flag.StringVar(&CookieBlockKey, "cookie-block-key", "", "Block key to use to encrypt cookies")
|
| 67 |
+
|
| 68 |
+
flag.StringVar(&PlaygroundDomain, "playground-domain", "localhost", "Domain to use for the playground")
|
| 69 |
+
flag.StringVar(&AdminToken, "admin-token", "", "Token to validate admin user for admin endpoints")
|
| 70 |
+
|
| 71 |
+
flag.StringVar(&SegmentId, "segment-id", "", "Segment id to post metrics")
|
| 72 |
+
|
| 73 |
+
flag.BoolVar(&Unsafe, "unsafe", os.Getenv("PWD_UNSAFE") == "true", "Operate in unsafe mode")
|
| 74 |
+
|
| 75 |
+
flag.Parse()
|
| 76 |
+
|
| 77 |
+
SecureCookie = securecookie.New([]byte(CookieHashKey), []byte(CookieBlockKey))
|
| 78 |
+
}
|
docker-compose.yml
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version: '3.2'
|
| 2 |
+
services:
|
| 3 |
+
haproxy:
|
| 4 |
+
container_name: haproxy
|
| 5 |
+
image: haproxy
|
| 6 |
+
ports:
|
| 7 |
+
- "80:8080"
|
| 8 |
+
volumes:
|
| 9 |
+
- ./haproxy:/usr/local/etc/haproxy
|
| 10 |
+
|
| 11 |
+
pwd:
|
| 12 |
+
# pwd daemon container always needs to be named this way
|
| 13 |
+
container_name: pwd
|
| 14 |
+
# use the latest golang image
|
| 15 |
+
image: golang
|
| 16 |
+
# go to the right place and starts the app
|
| 17 |
+
command: /bin/sh -c 'ssh-keygen -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key >/dev/null; cd /go/src/; if [ -e /runbin/pwd ]; then /runbin/pwd -save /pwd/sessions -name l2; else go run api.go -save /pwd/sessions -name l2; fi'
|
| 18 |
+
environment:
|
| 19 |
+
- APPARMOR_PROFILE=docker-dind
|
| 20 |
+
volumes:
|
| 21 |
+
# since this app creates networks and launches containers, we need to talk to docker daemon
|
| 22 |
+
- /var/run/docker.sock:/var/run/docker.sock
|
| 23 |
+
# mount the box mounted shared folder to the container
|
| 24 |
+
- $PWD:/go/src
|
| 25 |
+
- sessions:/pwd
|
| 26 |
+
l2:
|
| 27 |
+
container_name: l2
|
| 28 |
+
# use the latest golang image
|
| 29 |
+
image: golang
|
| 30 |
+
# go to the right place and starts the app
|
| 31 |
+
command: /bin/sh -c 'ssh-keygen -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key >/dev/null; cd /go/src/router/l2; if [ -e /runbin/l2 ]; then /runbin/l2 -ssh_key_path /etc/ssh/ssh_host_rsa_key -name l2 -save /pwd/networks; else go run l2.go -ssh_key_path /etc/ssh/ssh_host_rsa_key -name l2 -save /pwd/networks; fi'
|
| 32 |
+
volumes:
|
| 33 |
+
- /var/run/docker.sock:/var/run/docker.sock
|
| 34 |
+
- $PWD:/go/src
|
| 35 |
+
- networks:/pwd
|
| 36 |
+
ports:
|
| 37 |
+
- "8022:22"
|
| 38 |
+
- "8053:53"
|
| 39 |
+
- "443:443"
|
| 40 |
+
volumes:
|
| 41 |
+
sessions:
|
| 42 |
+
networks:
|
docker/docker.go
ADDED
|
@@ -0,0 +1,546 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package docker
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"archive/tar"
|
| 5 |
+
"bytes"
|
| 6 |
+
"context"
|
| 7 |
+
"fmt"
|
| 8 |
+
"io"
|
| 9 |
+
"io/ioutil"
|
| 10 |
+
"log"
|
| 11 |
+
"net"
|
| 12 |
+
"os"
|
| 13 |
+
"strconv"
|
| 14 |
+
"strings"
|
| 15 |
+
"time"
|
| 16 |
+
|
| 17 |
+
"github.com/containerd/containerd/reference"
|
| 18 |
+
"github.com/docker/docker/api/types"
|
| 19 |
+
"github.com/docker/docker/api/types/container"
|
| 20 |
+
"github.com/docker/docker/api/types/network"
|
| 21 |
+
"github.com/docker/docker/api/types/swarm"
|
| 22 |
+
"github.com/docker/docker/api/types/volume"
|
| 23 |
+
"github.com/docker/docker/client"
|
| 24 |
+
"github.com/play-with-docker/play-with-docker/config"
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
const (
|
| 28 |
+
Byte = 1
|
| 29 |
+
Kilobyte = 1024 * Byte
|
| 30 |
+
Megabyte = 1024 * Kilobyte
|
| 31 |
+
)
|
| 32 |
+
|
| 33 |
+
type DockerApi interface {
|
| 34 |
+
GetClient() *client.Client
|
| 35 |
+
|
| 36 |
+
NetworkCreate(id string, opts types.NetworkCreate) error
|
| 37 |
+
NetworkConnect(container, network, ip string) (string, error)
|
| 38 |
+
NetworkInspect(id string) (types.NetworkResource, error)
|
| 39 |
+
NetworkDelete(id string) error
|
| 40 |
+
NetworkDisconnect(containerId, networkId string) error
|
| 41 |
+
|
| 42 |
+
DaemonInfo() (types.Info, error)
|
| 43 |
+
DaemonHost() string
|
| 44 |
+
|
| 45 |
+
GetSwarmPorts() ([]string, []uint16, error)
|
| 46 |
+
GetPorts() ([]uint16, error)
|
| 47 |
+
|
| 48 |
+
ContainerStats(name string) (io.ReadCloser, error)
|
| 49 |
+
ContainerResize(name string, rows, cols uint) error
|
| 50 |
+
ContainerRename(old, new string) error
|
| 51 |
+
ContainerDelete(name string) error
|
| 52 |
+
ContainerCreate(opts CreateContainerOpts) error
|
| 53 |
+
ContainerIPs(id string) (map[string]string, error)
|
| 54 |
+
ExecAttach(instanceName string, command []string, out io.Writer) (int, error)
|
| 55 |
+
Exec(instanceName string, command []string) (int, error)
|
| 56 |
+
|
| 57 |
+
CreateAttachConnection(name string) (net.Conn, error)
|
| 58 |
+
CopyToContainer(containerName, destination, fileName string, content io.Reader) error
|
| 59 |
+
CopyFromContainer(containerName, filePath string) (io.Reader, error)
|
| 60 |
+
SwarmInit(advertiseAddr string) (*SwarmTokens, error)
|
| 61 |
+
SwarmJoin(addr, token string) error
|
| 62 |
+
|
| 63 |
+
ConfigCreate(name string, labels map[string]string, data []byte) error
|
| 64 |
+
ConfigDelete(name string) error
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
type SwarmTokens struct {
|
| 68 |
+
Manager string
|
| 69 |
+
Worker string
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
type docker struct {
|
| 73 |
+
c *client.Client
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
func (d *docker) GetClient() *client.Client {
|
| 77 |
+
return d.c
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
func (d *docker) ConfigCreate(name string, labels map[string]string, data []byte) error {
|
| 81 |
+
config := swarm.ConfigSpec{}
|
| 82 |
+
config.Name = name
|
| 83 |
+
config.Labels = labels
|
| 84 |
+
config.Data = data
|
| 85 |
+
_, err := d.c.ConfigCreate(context.Background(), config)
|
| 86 |
+
return err
|
| 87 |
+
}
|
| 88 |
+
func (d *docker) ConfigDelete(name string) error {
|
| 89 |
+
return d.c.ConfigRemove(context.Background(), name)
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
func (d *docker) NetworkCreate(id string, opts types.NetworkCreate) error {
|
| 93 |
+
_, err := d.c.NetworkCreate(context.Background(), id, opts)
|
| 94 |
+
|
| 95 |
+
if err != nil {
|
| 96 |
+
log.Printf("Starting session err [%s]\n", err)
|
| 97 |
+
|
| 98 |
+
return err
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
return nil
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
func (d *docker) NetworkConnect(containerId, networkId, ip string) (string, error) {
|
| 105 |
+
settings := &network.EndpointSettings{}
|
| 106 |
+
if ip != "" {
|
| 107 |
+
settings.IPAddress = ip
|
| 108 |
+
}
|
| 109 |
+
err := d.c.NetworkConnect(context.Background(), networkId, containerId, settings)
|
| 110 |
+
|
| 111 |
+
if err != nil && !strings.Contains(err.Error(), "already exists") {
|
| 112 |
+
log.Printf("Connection container to network err [%s]\n", err)
|
| 113 |
+
|
| 114 |
+
return "", err
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
// Obtain the IP of the PWD container in this network
|
| 118 |
+
container, err := d.c.ContainerInspect(context.Background(), containerId)
|
| 119 |
+
if err != nil {
|
| 120 |
+
return "", err
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
n, found := container.NetworkSettings.Networks[networkId]
|
| 124 |
+
if !found {
|
| 125 |
+
return "", fmt.Errorf("Container [%s] connected to the network [%s] but couldn't obtain it's IP address", containerId, networkId)
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
return n.IPAddress, nil
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
func (d *docker) NetworkInspect(id string) (types.NetworkResource, error) {
|
| 132 |
+
return d.c.NetworkInspect(context.Background(), id, types.NetworkInspectOptions{})
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
func (d *docker) DaemonInfo() (types.Info, error) {
|
| 136 |
+
return d.c.Info(context.Background())
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
func (d *docker) DaemonHost() string {
|
| 140 |
+
return d.c.DaemonHost()
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
func (d *docker) GetSwarmPorts() ([]string, []uint16, error) {
|
| 144 |
+
hosts := []string{}
|
| 145 |
+
ports := []uint16{}
|
| 146 |
+
|
| 147 |
+
nodesIdx := map[string]string{}
|
| 148 |
+
nodes, nodesErr := d.c.NodeList(context.Background(), types.NodeListOptions{})
|
| 149 |
+
if nodesErr != nil {
|
| 150 |
+
return nil, nil, nodesErr
|
| 151 |
+
}
|
| 152 |
+
for _, n := range nodes {
|
| 153 |
+
nodesIdx[n.ID] = n.Description.Hostname
|
| 154 |
+
hosts = append(hosts, n.Description.Hostname)
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
services, err := d.c.ServiceList(context.Background(), types.ServiceListOptions{})
|
| 158 |
+
if err != nil {
|
| 159 |
+
return nil, nil, err
|
| 160 |
+
}
|
| 161 |
+
for _, service := range services {
|
| 162 |
+
for _, p := range service.Endpoint.Ports {
|
| 163 |
+
ports = append(ports, uint16(p.PublishedPort))
|
| 164 |
+
}
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
return hosts, ports, nil
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
func (d *docker) GetPorts() ([]uint16, error) {
|
| 171 |
+
opts := types.ContainerListOptions{}
|
| 172 |
+
containers, err := d.c.ContainerList(context.Background(), opts)
|
| 173 |
+
if err != nil {
|
| 174 |
+
return nil, err
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
openPorts := []uint16{}
|
| 178 |
+
for _, c := range containers {
|
| 179 |
+
for _, p := range c.Ports {
|
| 180 |
+
// When port is not published on the host docker return public port as 0, so we need to avoid it
|
| 181 |
+
if p.PublicPort != 0 {
|
| 182 |
+
openPorts = append(openPorts, p.PublicPort)
|
| 183 |
+
}
|
| 184 |
+
}
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
return openPorts, nil
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
func (d *docker) ContainerStats(name string) (io.ReadCloser, error) {
|
| 191 |
+
stats, err := d.c.ContainerStats(context.Background(), name, false)
|
| 192 |
+
|
| 193 |
+
return stats.Body, err
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
func (d *docker) ContainerResize(name string, rows, cols uint) error {
|
| 197 |
+
return d.c.ContainerResize(context.Background(), name, types.ResizeOptions{Height: rows, Width: cols})
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
func (d *docker) ContainerRename(old, new string) error {
|
| 201 |
+
return d.c.ContainerRename(context.Background(), old, new)
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
func (d *docker) CreateAttachConnection(name string) (net.Conn, error) {
|
| 205 |
+
ctx := context.Background()
|
| 206 |
+
|
| 207 |
+
conf := types.ContainerAttachOptions{true, true, true, true, "ctrl-^,ctrl-^", true}
|
| 208 |
+
conn, err := d.c.ContainerAttach(ctx, name, conf)
|
| 209 |
+
if err != nil {
|
| 210 |
+
return nil, err
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
return conn.Conn, nil
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
func (d *docker) CopyToContainer(containerName, destination, fileName string, content io.Reader) error {
|
| 217 |
+
contents, err := ioutil.ReadAll(content)
|
| 218 |
+
if err != nil {
|
| 219 |
+
return err
|
| 220 |
+
}
|
| 221 |
+
var buf bytes.Buffer
|
| 222 |
+
t := tar.NewWriter(&buf)
|
| 223 |
+
if err := t.WriteHeader(&tar.Header{Name: fileName, Mode: 0600, Size: int64(len(contents)), ModTime: time.Now()}); err != nil {
|
| 224 |
+
return err
|
| 225 |
+
}
|
| 226 |
+
if _, err := t.Write(contents); err != nil {
|
| 227 |
+
return err
|
| 228 |
+
}
|
| 229 |
+
if err := t.Close(); err != nil {
|
| 230 |
+
return err
|
| 231 |
+
}
|
| 232 |
+
return d.c.CopyToContainer(context.Background(), containerName, destination, &buf, types.CopyToContainerOptions{AllowOverwriteDirWithFile: true, CopyUIDGID: true})
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
func (d *docker) CopyFromContainer(containerName, filePath string) (io.Reader, error) {
|
| 236 |
+
rc, stat, err := d.c.CopyFromContainer(context.Background(), containerName, filePath)
|
| 237 |
+
if err != nil {
|
| 238 |
+
return nil, err
|
| 239 |
+
}
|
| 240 |
+
if stat.Mode.IsDir() {
|
| 241 |
+
return nil, fmt.Errorf("Copying directories is not supported")
|
| 242 |
+
}
|
| 243 |
+
tr := tar.NewReader(rc)
|
| 244 |
+
// advance to the only possible file in the tar archive
|
| 245 |
+
tr.Next()
|
| 246 |
+
return tr, nil
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
func (d *docker) ContainerDelete(name string) error {
|
| 250 |
+
err := d.c.ContainerRemove(context.Background(), name, types.ContainerRemoveOptions{Force: true, RemoveVolumes: true})
|
| 251 |
+
d.c.VolumeRemove(context.Background(), name, true)
|
| 252 |
+
return err
|
| 253 |
+
}
|
| 254 |
+
|
| 255 |
+
type CreateContainerOpts struct {
|
| 256 |
+
Image string
|
| 257 |
+
SessionId string
|
| 258 |
+
ContainerName string
|
| 259 |
+
Hostname string
|
| 260 |
+
ServerCert []byte
|
| 261 |
+
ServerKey []byte
|
| 262 |
+
CACert []byte
|
| 263 |
+
Privileged bool
|
| 264 |
+
HostFQDN string
|
| 265 |
+
Labels map[string]string
|
| 266 |
+
Networks []string
|
| 267 |
+
DindVolumeSize string
|
| 268 |
+
Envs []string
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
func (d *docker) ContainerCreate(opts CreateContainerOpts) (err error) {
|
| 272 |
+
// Make sure directories are available for the new instance container
|
| 273 |
+
containerDir := "/opt/pwd"
|
| 274 |
+
containerCertDir := fmt.Sprintf("%s/certs", containerDir)
|
| 275 |
+
|
| 276 |
+
env := append(opts.Envs, fmt.Sprintf("SESSION_ID=%s", opts.SessionId))
|
| 277 |
+
|
| 278 |
+
// Write certs to container cert dir
|
| 279 |
+
if len(opts.ServerCert) > 0 {
|
| 280 |
+
env = append(env, `DOCKER_TLSCERT=\/opt\/pwd\/certs\/cert.pem`)
|
| 281 |
+
}
|
| 282 |
+
if len(opts.ServerKey) > 0 {
|
| 283 |
+
env = append(env, `DOCKER_TLSKEY=\/opt\/pwd\/certs\/key.pem`)
|
| 284 |
+
}
|
| 285 |
+
if len(opts.CACert) > 0 {
|
| 286 |
+
// if ca cert is specified, verify that clients that connects present a certificate signed by the CA
|
| 287 |
+
env = append(env, `DOCKER_TLSCACERT=\/opt\/pwd\/certs\/ca.pem`)
|
| 288 |
+
}
|
| 289 |
+
if len(opts.ServerCert) > 0 || len(opts.ServerKey) > 0 || len(opts.CACert) > 0 {
|
| 290 |
+
// if any of the certs is specified, enable TLS
|
| 291 |
+
env = append(env, "DOCKER_TLSENABLE=true")
|
| 292 |
+
} else {
|
| 293 |
+
env = append(env, "DOCKER_TLSENABLE=false")
|
| 294 |
+
}
|
| 295 |
+
|
| 296 |
+
h := &container.HostConfig{
|
| 297 |
+
NetworkMode: container.NetworkMode(opts.SessionId),
|
| 298 |
+
Privileged: opts.Privileged,
|
| 299 |
+
AutoRemove: true,
|
| 300 |
+
LogConfig: container.LogConfig{Config: map[string]string{"max-size": "10m", "max-file": "1"}},
|
| 301 |
+
}
|
| 302 |
+
|
| 303 |
+
if os.Getenv("APPARMOR_PROFILE") != "" {
|
| 304 |
+
h.SecurityOpt = []string{fmt.Sprintf("apparmor=%s", os.Getenv("APPARMOR_PROFILE"))}
|
| 305 |
+
}
|
| 306 |
+
|
| 307 |
+
if os.Getenv("STORAGE_SIZE") != "" {
|
| 308 |
+
// assing 10GB size FS for each container
|
| 309 |
+
h.StorageOpt = map[string]string{"size": os.Getenv("STORAGE_SIZE")}
|
| 310 |
+
}
|
| 311 |
+
|
| 312 |
+
var pidsLimit = int64(1000)
|
| 313 |
+
if envLimit := os.Getenv("MAX_PROCESSES"); envLimit != "" {
|
| 314 |
+
if i, err := strconv.Atoi(envLimit); err == nil {
|
| 315 |
+
pidsLimit = int64(i)
|
| 316 |
+
}
|
| 317 |
+
}
|
| 318 |
+
h.Resources.PidsLimit = &pidsLimit
|
| 319 |
+
|
| 320 |
+
if memLimit := os.Getenv("MAX_MEMORY_MB"); memLimit != "" {
|
| 321 |
+
if i, err := strconv.Atoi(memLimit); err == nil {
|
| 322 |
+
h.Resources.Memory = int64(i) * Megabyte
|
| 323 |
+
}
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
+
t := true
|
| 327 |
+
h.Resources.OomKillDisable = &t
|
| 328 |
+
|
| 329 |
+
env = append(env, fmt.Sprintf("PWD_HOST_FQDN=%s", opts.HostFQDN))
|
| 330 |
+
cf := &container.Config{
|
| 331 |
+
Hostname: opts.Hostname,
|
| 332 |
+
Image: opts.Image,
|
| 333 |
+
Tty: true,
|
| 334 |
+
OpenStdin: true,
|
| 335 |
+
AttachStdin: true,
|
| 336 |
+
AttachStdout: true,
|
| 337 |
+
AttachStderr: true,
|
| 338 |
+
Env: env,
|
| 339 |
+
Labels: opts.Labels,
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
networkConf := &network.NetworkingConfig{
|
| 343 |
+
EndpointsConfig: map[string]*network.EndpointSettings{opts.Networks[0]: &network.EndpointSettings{}},
|
| 344 |
+
}
|
| 345 |
+
|
| 346 |
+
if config.ExternalDindVolume {
|
| 347 |
+
_, err = d.c.VolumeCreate(context.Background(), volume.VolumeCreateBody{
|
| 348 |
+
Driver: "xfsvol",
|
| 349 |
+
DriverOpts: map[string]string{
|
| 350 |
+
"size": opts.DindVolumeSize,
|
| 351 |
+
},
|
| 352 |
+
Name: opts.ContainerName,
|
| 353 |
+
})
|
| 354 |
+
if err != nil {
|
| 355 |
+
return
|
| 356 |
+
}
|
| 357 |
+
h.Binds = []string{fmt.Sprintf("%s:/var/lib/docker", opts.ContainerName)}
|
| 358 |
+
|
| 359 |
+
defer func() {
|
| 360 |
+
if err != nil {
|
| 361 |
+
d.c.VolumeRemove(context.Background(), opts.SessionId, true)
|
| 362 |
+
}
|
| 363 |
+
}()
|
| 364 |
+
}
|
| 365 |
+
|
| 366 |
+
container, err := d.c.ContainerCreate(context.Background(), cf, h, networkConf, opts.ContainerName)
|
| 367 |
+
|
| 368 |
+
if err != nil {
|
| 369 |
+
//if client.IsErrImageNotFound(err) {
|
| 370 |
+
//log.Printf("Unable to find image '%s' locally\n", opts.Image)
|
| 371 |
+
//if err = d.pullImage(context.Background(), opts.Image); err != nil {
|
| 372 |
+
//return "", err
|
| 373 |
+
//}
|
| 374 |
+
//container, err = d.c.ContainerCreate(context.Background(), cf, h, networkConf, opts.ContainerName)
|
| 375 |
+
//if err != nil {
|
| 376 |
+
//return "", err
|
| 377 |
+
//}
|
| 378 |
+
//} else {
|
| 379 |
+
return err
|
| 380 |
+
//}
|
| 381 |
+
}
|
| 382 |
+
|
| 383 |
+
//connect remaining networks if there are any
|
| 384 |
+
if len(opts.Networks) > 1 {
|
| 385 |
+
for _, nid := range opts.Networks {
|
| 386 |
+
err = d.c.NetworkConnect(context.Background(), nid, container.ID, &network.EndpointSettings{})
|
| 387 |
+
if err != nil {
|
| 388 |
+
return
|
| 389 |
+
}
|
| 390 |
+
}
|
| 391 |
+
}
|
| 392 |
+
|
| 393 |
+
if err = d.copyIfSet(opts.ServerCert, "cert.pem", containerCertDir, opts.ContainerName); err != nil {
|
| 394 |
+
return
|
| 395 |
+
}
|
| 396 |
+
if err = d.copyIfSet(opts.ServerKey, "key.pem", containerCertDir, opts.ContainerName); err != nil {
|
| 397 |
+
return
|
| 398 |
+
}
|
| 399 |
+
if err = d.copyIfSet(opts.CACert, "ca.pem", containerCertDir, opts.ContainerName); err != nil {
|
| 400 |
+
return
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
err = d.c.ContainerStart(context.Background(), container.ID, types.ContainerStartOptions{})
|
| 404 |
+
if err != nil {
|
| 405 |
+
return
|
| 406 |
+
}
|
| 407 |
+
|
| 408 |
+
return
|
| 409 |
+
}
|
| 410 |
+
|
| 411 |
+
func (d *docker) ContainerIPs(id string) (map[string]string, error) {
|
| 412 |
+
cinfo, err := d.c.ContainerInspect(context.Background(), id)
|
| 413 |
+
if err != nil {
|
| 414 |
+
return nil, err
|
| 415 |
+
}
|
| 416 |
+
|
| 417 |
+
ips := map[string]string{}
|
| 418 |
+
for networkId, conf := range cinfo.NetworkSettings.Networks {
|
| 419 |
+
ips[networkId] = conf.IPAddress
|
| 420 |
+
}
|
| 421 |
+
return ips, nil
|
| 422 |
+
|
| 423 |
+
}
|
| 424 |
+
|
| 425 |
+
func (d *docker) pullImage(ctx context.Context, image string) error {
|
| 426 |
+
_, err := reference.Parse(image)
|
| 427 |
+
if err != nil {
|
| 428 |
+
return err
|
| 429 |
+
}
|
| 430 |
+
|
| 431 |
+
options := types.ImageCreateOptions{}
|
| 432 |
+
|
| 433 |
+
responseBody, err := d.c.ImageCreate(ctx, image, options)
|
| 434 |
+
if err != nil {
|
| 435 |
+
return err
|
| 436 |
+
}
|
| 437 |
+
_, err = io.Copy(ioutil.Discard, responseBody)
|
| 438 |
+
|
| 439 |
+
return err
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
func (d *docker) copyIfSet(content []byte, fileName, path, containerName string) error {
|
| 443 |
+
if len(content) > 0 {
|
| 444 |
+
return d.CopyToContainer(containerName, path, fileName, bytes.NewReader(content))
|
| 445 |
+
}
|
| 446 |
+
return nil
|
| 447 |
+
}
|
| 448 |
+
|
| 449 |
+
func (d *docker) ExecAttach(instanceName string, command []string, out io.Writer) (int, error) {
|
| 450 |
+
e, err := d.c.ContainerExecCreate(context.Background(), instanceName, types.ExecConfig{Cmd: command, AttachStdout: true, AttachStderr: true, Tty: true})
|
| 451 |
+
if err != nil {
|
| 452 |
+
return 0, err
|
| 453 |
+
}
|
| 454 |
+
resp, err := d.c.ContainerExecAttach(context.Background(), e.ID, types.ExecStartCheck{
|
| 455 |
+
Tty: true,
|
| 456 |
+
})
|
| 457 |
+
if err != nil {
|
| 458 |
+
return 0, err
|
| 459 |
+
}
|
| 460 |
+
io.Copy(out, resp.Reader)
|
| 461 |
+
var ins types.ContainerExecInspect
|
| 462 |
+
for _ = range time.Tick(1 * time.Second) {
|
| 463 |
+
ins, err = d.c.ContainerExecInspect(context.Background(), e.ID)
|
| 464 |
+
if ins.Running {
|
| 465 |
+
continue
|
| 466 |
+
}
|
| 467 |
+
if err != nil {
|
| 468 |
+
return 0, err
|
| 469 |
+
}
|
| 470 |
+
break
|
| 471 |
+
}
|
| 472 |
+
return ins.ExitCode, nil
|
| 473 |
+
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
func (d *docker) Exec(instanceName string, command []string) (int, error) {
|
| 477 |
+
e, err := d.c.ContainerExecCreate(context.Background(), instanceName, types.ExecConfig{Cmd: command})
|
| 478 |
+
if err != nil {
|
| 479 |
+
return 0, err
|
| 480 |
+
}
|
| 481 |
+
err = d.c.ContainerExecStart(context.Background(), e.ID, types.ExecStartCheck{})
|
| 482 |
+
if err != nil {
|
| 483 |
+
return 0, err
|
| 484 |
+
}
|
| 485 |
+
var ins types.ContainerExecInspect
|
| 486 |
+
for _ = range time.Tick(1 * time.Second) {
|
| 487 |
+
ins, err = d.c.ContainerExecInspect(context.Background(), e.ID)
|
| 488 |
+
if ins.Running {
|
| 489 |
+
continue
|
| 490 |
+
}
|
| 491 |
+
if err != nil {
|
| 492 |
+
return 0, err
|
| 493 |
+
}
|
| 494 |
+
break
|
| 495 |
+
}
|
| 496 |
+
return ins.ExitCode, nil
|
| 497 |
+
}
|
| 498 |
+
|
| 499 |
+
func (d *docker) NetworkDisconnect(containerId, networkId string) error {
|
| 500 |
+
err := d.c.NetworkDisconnect(context.Background(), networkId, containerId, true)
|
| 501 |
+
|
| 502 |
+
if err != nil {
|
| 503 |
+
log.Printf("Disconnection of container from network err [%s]\n", err)
|
| 504 |
+
|
| 505 |
+
return err
|
| 506 |
+
}
|
| 507 |
+
|
| 508 |
+
return nil
|
| 509 |
+
}
|
| 510 |
+
|
| 511 |
+
func (d *docker) NetworkDelete(id string) error {
|
| 512 |
+
err := d.c.NetworkRemove(context.Background(), id)
|
| 513 |
+
|
| 514 |
+
if err != nil {
|
| 515 |
+
return err
|
| 516 |
+
}
|
| 517 |
+
|
| 518 |
+
return nil
|
| 519 |
+
}
|
| 520 |
+
|
| 521 |
+
func (d *docker) SwarmInit(advertiseAddr string) (*SwarmTokens, error) {
|
| 522 |
+
req := swarm.InitRequest{AdvertiseAddr: advertiseAddr, ListenAddr: "0.0.0.0:2377"}
|
| 523 |
+
_, err := d.c.SwarmInit(context.Background(), req)
|
| 524 |
+
|
| 525 |
+
if err != nil {
|
| 526 |
+
return nil, err
|
| 527 |
+
}
|
| 528 |
+
|
| 529 |
+
swarmInfo, err := d.c.SwarmInspect(context.Background())
|
| 530 |
+
if err != nil {
|
| 531 |
+
return nil, err
|
| 532 |
+
}
|
| 533 |
+
|
| 534 |
+
return &SwarmTokens{
|
| 535 |
+
Worker: swarmInfo.JoinTokens.Worker,
|
| 536 |
+
Manager: swarmInfo.JoinTokens.Manager,
|
| 537 |
+
}, nil
|
| 538 |
+
}
|
| 539 |
+
func (d *docker) SwarmJoin(addr, token string) error {
|
| 540 |
+
req := swarm.JoinRequest{RemoteAddrs: []string{addr}, JoinToken: token, ListenAddr: "0.0.0.0:2377", AdvertiseAddr: "eth0"}
|
| 541 |
+
return d.c.SwarmJoin(context.Background(), req)
|
| 542 |
+
}
|
| 543 |
+
|
| 544 |
+
func NewDocker(c *client.Client) *docker {
|
| 545 |
+
return &docker{c: c}
|
| 546 |
+
}
|
docker/factory.go
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package docker
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"crypto/tls"
|
| 5 |
+
"fmt"
|
| 6 |
+
"net"
|
| 7 |
+
"net/http"
|
| 8 |
+
"net/url"
|
| 9 |
+
"time"
|
| 10 |
+
|
| 11 |
+
"github.com/docker/docker/api"
|
| 12 |
+
"github.com/docker/docker/client"
|
| 13 |
+
"github.com/docker/go-connections/tlsconfig"
|
| 14 |
+
"github.com/play-with-docker/play-with-docker/pwd/types"
|
| 15 |
+
"github.com/play-with-docker/play-with-docker/router"
|
| 16 |
+
)
|
| 17 |
+
|
| 18 |
+
type FactoryApi interface {
|
| 19 |
+
GetForSession(session *types.Session) (DockerApi, error)
|
| 20 |
+
GetForInstance(instance *types.Instance) (DockerApi, error)
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
func NewClient(instance *types.Instance, proxyHost string) (*client.Client, error) {
|
| 24 |
+
var host string
|
| 25 |
+
var durl string
|
| 26 |
+
|
| 27 |
+
var tlsConfig *tls.Config
|
| 28 |
+
if (len(instance.Cert) > 0 && len(instance.Key) > 0) || instance.Tls {
|
| 29 |
+
host = router.EncodeHost(instance.SessionId, instance.RoutableIP, router.HostOpts{EncodedPort: 2376})
|
| 30 |
+
tlsConfig = tlsconfig.ClientDefault()
|
| 31 |
+
tlsConfig.InsecureSkipVerify = true
|
| 32 |
+
tlsConfig.ServerName = host
|
| 33 |
+
if len(instance.Cert) > 0 && len(instance.Key) > 0 {
|
| 34 |
+
tlsCert, err := tls.X509KeyPair(instance.Cert, instance.Key)
|
| 35 |
+
if err != nil {
|
| 36 |
+
return nil, fmt.Errorf("Could not load X509 key pair: %v. Make sure the key is not encrypted", err)
|
| 37 |
+
}
|
| 38 |
+
tlsConfig.Certificates = []tls.Certificate{tlsCert}
|
| 39 |
+
}
|
| 40 |
+
} else {
|
| 41 |
+
host = router.EncodeHost(instance.SessionId, instance.RoutableIP, router.HostOpts{EncodedPort: 2375})
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
transport := &http.Transport{
|
| 45 |
+
DialContext: (&net.Dialer{
|
| 46 |
+
Timeout: 1 * time.Second,
|
| 47 |
+
KeepAlive: 30 * time.Second,
|
| 48 |
+
}).DialContext,
|
| 49 |
+
MaxIdleConnsPerHost: 5,
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
if tlsConfig != nil {
|
| 53 |
+
transport.TLSClientConfig = tlsConfig
|
| 54 |
+
durl = fmt.Sprintf("https://%s", proxyHost)
|
| 55 |
+
} else {
|
| 56 |
+
transport.Proxy = http.ProxyURL(&url.URL{Host: proxyHost})
|
| 57 |
+
durl = fmt.Sprintf("http://%s", host)
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
cli := &http.Client{
|
| 61 |
+
Transport: transport,
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
dc, err := client.NewClient(durl, api.DefaultVersion, cli, nil)
|
| 65 |
+
if err != nil {
|
| 66 |
+
return nil, fmt.Errorf("Could not connect to DinD docker daemon: %v", err)
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
return dc, nil
|
| 70 |
+
}
|
docker/factory_mock.go
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package docker
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"github.com/play-with-docker/play-with-docker/pwd/types"
|
| 5 |
+
"github.com/stretchr/testify/mock"
|
| 6 |
+
)
|
| 7 |
+
|
| 8 |
+
type FactoryMock struct {
|
| 9 |
+
mock.Mock
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
func (m *FactoryMock) GetForSession(session *types.Session) (DockerApi, error) {
|
| 13 |
+
args := m.Called(session)
|
| 14 |
+
return args.Get(0).(DockerApi), args.Error(1)
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
func (m *FactoryMock) GetForInstance(instance *types.Instance) (DockerApi, error) {
|
| 18 |
+
args := m.Called(instance)
|
| 19 |
+
return args.Get(0).(DockerApi), args.Error(1)
|
| 20 |
+
}
|
docker/local_cached_factory.go
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package docker
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"context"
|
| 5 |
+
"fmt"
|
| 6 |
+
"log"
|
| 7 |
+
"sync"
|
| 8 |
+
"time"
|
| 9 |
+
|
| 10 |
+
"github.com/docker/docker/client"
|
| 11 |
+
"github.com/play-with-docker/play-with-docker/pwd/types"
|
| 12 |
+
"github.com/play-with-docker/play-with-docker/storage"
|
| 13 |
+
)
|
| 14 |
+
|
| 15 |
+
type localCachedFactory struct {
|
| 16 |
+
rw sync.Mutex
|
| 17 |
+
irw sync.Mutex
|
| 18 |
+
sessionClient DockerApi
|
| 19 |
+
instanceClients map[string]*instanceEntry
|
| 20 |
+
storage storage.StorageApi
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
type instanceEntry struct {
|
| 24 |
+
rw sync.Mutex
|
| 25 |
+
client DockerApi
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
func (f *localCachedFactory) GetForSession(session *types.Session) (DockerApi, error) {
|
| 29 |
+
f.rw.Lock()
|
| 30 |
+
defer f.rw.Unlock()
|
| 31 |
+
|
| 32 |
+
if f.sessionClient != nil {
|
| 33 |
+
if err := f.check(f.sessionClient.GetClient()); err == nil {
|
| 34 |
+
return f.sessionClient, nil
|
| 35 |
+
} else {
|
| 36 |
+
f.sessionClient.GetClient().Close()
|
| 37 |
+
}
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
c, err := client.NewClientWithOpts()
|
| 41 |
+
if err != nil {
|
| 42 |
+
return nil, err
|
| 43 |
+
}
|
| 44 |
+
err = f.check(c)
|
| 45 |
+
if err != nil {
|
| 46 |
+
return nil, err
|
| 47 |
+
}
|
| 48 |
+
d := NewDocker(c)
|
| 49 |
+
f.sessionClient = d
|
| 50 |
+
return f.sessionClient, nil
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
func (f *localCachedFactory) GetForInstance(instance *types.Instance) (DockerApi, error) {
|
| 54 |
+
key := instance.Name
|
| 55 |
+
|
| 56 |
+
f.irw.Lock()
|
| 57 |
+
c, found := f.instanceClients[key]
|
| 58 |
+
if !found {
|
| 59 |
+
c := &instanceEntry{}
|
| 60 |
+
f.instanceClients[key] = c
|
| 61 |
+
}
|
| 62 |
+
c = f.instanceClients[key]
|
| 63 |
+
f.irw.Unlock()
|
| 64 |
+
|
| 65 |
+
c.rw.Lock()
|
| 66 |
+
defer c.rw.Unlock()
|
| 67 |
+
|
| 68 |
+
if c.client != nil {
|
| 69 |
+
if err := f.check(c.client.GetClient()); err == nil {
|
| 70 |
+
return c.client, nil
|
| 71 |
+
} else {
|
| 72 |
+
c.client.GetClient().Close()
|
| 73 |
+
}
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
dc, err := NewClient(instance, "l2:443")
|
| 77 |
+
if err != nil {
|
| 78 |
+
return nil, err
|
| 79 |
+
}
|
| 80 |
+
err = f.check(dc)
|
| 81 |
+
if err != nil {
|
| 82 |
+
return nil, err
|
| 83 |
+
}
|
| 84 |
+
dockerClient := NewDocker(dc)
|
| 85 |
+
c.client = dockerClient
|
| 86 |
+
|
| 87 |
+
return dockerClient, nil
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
func (f *localCachedFactory) check(c *client.Client) error {
|
| 91 |
+
ok := false
|
| 92 |
+
for i := 0; i < 5; i++ {
|
| 93 |
+
_, err := c.Ping(context.Background())
|
| 94 |
+
if err != nil {
|
| 95 |
+
log.Printf("Connection to [%s] has failed, maybe instance is not ready yet, sleeping and retrying in 1 second. Try #%d. Got: %v\n", c.DaemonHost(), i+1, err)
|
| 96 |
+
time.Sleep(time.Second)
|
| 97 |
+
continue
|
| 98 |
+
}
|
| 99 |
+
ok = true
|
| 100 |
+
break
|
| 101 |
+
}
|
| 102 |
+
if !ok {
|
| 103 |
+
return fmt.Errorf("Connection to docker daemon was not established.")
|
| 104 |
+
}
|
| 105 |
+
return nil
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
func NewLocalCachedFactory(s storage.StorageApi) *localCachedFactory {
|
| 109 |
+
return &localCachedFactory{
|
| 110 |
+
instanceClients: make(map[string]*instanceEntry),
|
| 111 |
+
storage: s,
|
| 112 |
+
}
|
| 113 |
+
}
|
docker/mock.go
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package docker
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"io"
|
| 5 |
+
"net"
|
| 6 |
+
"time"
|
| 7 |
+
|
| 8 |
+
"github.com/docker/docker/api/types"
|
| 9 |
+
"github.com/docker/docker/client"
|
| 10 |
+
"github.com/stretchr/testify/mock"
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
type Mock struct {
|
| 14 |
+
mock.Mock
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
func (m *Mock) GetClient() *client.Client {
|
| 18 |
+
args := m.Called()
|
| 19 |
+
return args.Get(0).(*client.Client)
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
func (m *Mock) NetworkCreate(id string, opts types.NetworkCreate) error {
|
| 23 |
+
args := m.Called(id, opts)
|
| 24 |
+
return args.Error(0)
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
func (m *Mock) NetworkConnect(container, network, ip string) (string, error) {
|
| 28 |
+
args := m.Called(container, network, ip)
|
| 29 |
+
return args.String(0), args.Error(1)
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
func (m *Mock) NetworkInspect(id string) (types.NetworkResource, error) {
|
| 33 |
+
args := m.Called(id)
|
| 34 |
+
return args.Get(0).(types.NetworkResource), args.Error(1)
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
func (m *Mock) DaemonInfo() (types.Info, error) {
|
| 38 |
+
args := m.Called()
|
| 39 |
+
return args.Get(0).(types.Info), args.Error(1)
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
func (m *Mock) DaemonHost() string {
|
| 43 |
+
args := m.Called()
|
| 44 |
+
return args.String(0)
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
func (m *Mock) GetSwarmPorts() ([]string, []uint16, error) {
|
| 48 |
+
args := m.Called()
|
| 49 |
+
return args.Get(0).([]string), args.Get(1).([]uint16), args.Error(2)
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
func (m *Mock) GetPorts() ([]uint16, error) {
|
| 53 |
+
args := m.Called()
|
| 54 |
+
return args.Get(0).([]uint16), args.Error(1)
|
| 55 |
+
}
|
| 56 |
+
func (m *Mock) ContainerStats(name string) (io.ReadCloser, error) {
|
| 57 |
+
args := m.Called(name)
|
| 58 |
+
return args.Get(0).(io.ReadCloser), args.Error(1)
|
| 59 |
+
}
|
| 60 |
+
func (m *Mock) ContainerResize(name string, rows, cols uint) error {
|
| 61 |
+
args := m.Called(name, rows, cols)
|
| 62 |
+
return args.Error(0)
|
| 63 |
+
}
|
| 64 |
+
func (m *Mock) ContainerRename(old, new string) error {
|
| 65 |
+
args := m.Called(old, new)
|
| 66 |
+
return args.Error(0)
|
| 67 |
+
}
|
| 68 |
+
func (m *Mock) CreateAttachConnection(name string) (net.Conn, error) {
|
| 69 |
+
args := m.Called(name)
|
| 70 |
+
return args.Get(0).(net.Conn), args.Error(1)
|
| 71 |
+
}
|
| 72 |
+
func (m *Mock) CopyToContainer(containerName, destination, fileName string, content io.Reader) error {
|
| 73 |
+
args := m.Called(containerName, destination, fileName, content)
|
| 74 |
+
return args.Error(0)
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
func (m *Mock) CopyFromContainer(containerName, filePath string) (io.Reader, error) {
|
| 78 |
+
args := m.Called(containerName, filePath)
|
| 79 |
+
return args.Get(0).(io.Reader), args.Error(1)
|
| 80 |
+
}
|
| 81 |
+
func (m *Mock) ContainerDelete(id string) error {
|
| 82 |
+
args := m.Called(id)
|
| 83 |
+
return args.Error(0)
|
| 84 |
+
}
|
| 85 |
+
func (m *Mock) ContainerCreate(opts CreateContainerOpts) error {
|
| 86 |
+
args := m.Called(opts)
|
| 87 |
+
return args.Error(0)
|
| 88 |
+
}
|
| 89 |
+
func (m *Mock) ContainerIPs(id string) (map[string]string, error) {
|
| 90 |
+
args := m.Called(id)
|
| 91 |
+
return args.Get(0).(map[string]string), args.Error(1)
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
func (m *Mock) ExecAttach(instanceName string, command []string, out io.Writer) (int, error) {
|
| 95 |
+
args := m.Called(instanceName, command, out)
|
| 96 |
+
return args.Int(0), args.Error(1)
|
| 97 |
+
}
|
| 98 |
+
func (m *Mock) NetworkDisconnect(containerId, networkId string) error {
|
| 99 |
+
args := m.Called(containerId, networkId)
|
| 100 |
+
return args.Error(0)
|
| 101 |
+
}
|
| 102 |
+
func (m *Mock) NetworkDelete(id string) error {
|
| 103 |
+
args := m.Called(id)
|
| 104 |
+
return args.Error(0)
|
| 105 |
+
}
|
| 106 |
+
func (m *Mock) Exec(instanceName string, command []string) (int, error) {
|
| 107 |
+
args := m.Called(instanceName, command)
|
| 108 |
+
return args.Int(0), args.Error(1)
|
| 109 |
+
}
|
| 110 |
+
func (m *Mock) SwarmInit(advertiseAddr string) (*SwarmTokens, error) {
|
| 111 |
+
args := m.Called(advertiseAddr)
|
| 112 |
+
return args.Get(0).(*SwarmTokens), args.Error(1)
|
| 113 |
+
}
|
| 114 |
+
func (m *Mock) SwarmJoin(addr, token string) error {
|
| 115 |
+
args := m.Called(addr, token)
|
| 116 |
+
return args.Error(0)
|
| 117 |
+
}
|
| 118 |
+
func (m *Mock) ConfigCreate(name string, labels map[string]string, data []byte) error {
|
| 119 |
+
args := m.Called(name, labels, data)
|
| 120 |
+
return args.Error(0)
|
| 121 |
+
}
|
| 122 |
+
func (m *Mock) ConfigDelete(name string) error {
|
| 123 |
+
args := m.Called(name)
|
| 124 |
+
return args.Error(0)
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
type MockConn struct {
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
func (m *MockConn) Read(b []byte) (n int, err error) {
|
| 131 |
+
return len(b), nil
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
func (m *MockConn) Write(b []byte) (n int, err error) {
|
| 135 |
+
return len(b), nil
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
func (m *MockConn) Close() error {
|
| 139 |
+
return nil
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
func (m *MockConn) LocalAddr() net.Addr {
|
| 143 |
+
return &net.IPAddr{}
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
func (m *MockConn) RemoteAddr() net.Addr {
|
| 147 |
+
return &net.IPAddr{}
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
func (m *MockConn) SetDeadline(t time.Time) error {
|
| 151 |
+
return nil
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
func (m *MockConn) SetReadDeadline(t time.Time) error {
|
| 155 |
+
return nil
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
func (m *MockConn) SetWriteDeadline(t time.Time) error {
|
| 159 |
+
return nil
|
| 160 |
+
}
|
dockerfiles/dind/.editorconfig
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# top-most EditorConfig file
|
| 2 |
+
root = true
|
| 3 |
+
|
| 4 |
+
# Unix-style newlines with a newline ending every file
|
| 5 |
+
[*]
|
| 6 |
+
end_of_line = lf
|
| 7 |
+
insert_final_newline = true
|
| 8 |
+
charset = utf-8
|
| 9 |
+
indent_style = space
|
| 10 |
+
indent_size = 4
|
| 11 |
+
|
| 12 |
+
# Tab indentation (no size specified)
|
| 13 |
+
[{Makefile,*.go}]
|
| 14 |
+
indent_style = tab
|
dockerfiles/dind/.gitconfig
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[url "https://"]
|
| 2 |
+
insteadOf = git://
|
dockerfiles/dind/.inputrc
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# /etc/inputrc - global inputrc for libreadline
|
| 2 |
+
# See readline(3readline) and `info rluserman' for more information.
|
| 3 |
+
|
| 4 |
+
# Be 8 bit clean.
|
| 5 |
+
set input-meta on
|
| 6 |
+
set output-meta on
|
| 7 |
+
|
| 8 |
+
# To allow the use of 8bit-characters like the german umlauts, uncomment
|
| 9 |
+
# the line below. However this makes the meta key not work as a meta key,
|
| 10 |
+
# which is annoying to those which don't need to type in 8-bit characters.
|
| 11 |
+
|
| 12 |
+
# set convert-meta off
|
| 13 |
+
|
| 14 |
+
# try to enable the application keypad when it is called. Some systems
|
| 15 |
+
# need this to enable the arrow keys.
|
| 16 |
+
# set enable-keypad on
|
| 17 |
+
|
| 18 |
+
# see /usr/share/doc/bash/inputrc.arrows for other codes of arrow keys
|
| 19 |
+
|
| 20 |
+
# do not bell on tab-completion
|
| 21 |
+
# set bell-style none
|
| 22 |
+
# set bell-style visible
|
| 23 |
+
|
| 24 |
+
# some defaults / modifications for the emacs mode
|
| 25 |
+
$if mode=emacs
|
| 26 |
+
|
| 27 |
+
# allow the use of the Home/End keys
|
| 28 |
+
"\e[1~": beginning-of-line
|
| 29 |
+
"\e[4~": end-of-line
|
| 30 |
+
|
| 31 |
+
# allow the use of the Delete/Insert keys
|
| 32 |
+
"\e[3~": delete-char
|
| 33 |
+
"\e[2~": quoted-insert
|
| 34 |
+
|
| 35 |
+
# mappings for "page up" and "page down" to step to the beginning/end
|
| 36 |
+
# of the history
|
| 37 |
+
# "\e[5~": beginning-of-history
|
| 38 |
+
# "\e[6~": end-of-history
|
| 39 |
+
|
| 40 |
+
# alternate mappings for "page up" and "page down" to search the history
|
| 41 |
+
# "\e[5~": history-search-backward
|
| 42 |
+
# "\e[6~": history-search-forward
|
| 43 |
+
|
| 44 |
+
# mappings for Ctrl-left-arrow and Ctrl-right-arrow for word moving
|
| 45 |
+
"\e[1;5C": forward-word
|
| 46 |
+
"\e[1;5D": backward-word
|
| 47 |
+
"\e[5C": forward-word
|
| 48 |
+
"\e[5D": backward-word
|
| 49 |
+
"\e\e[C": forward-word
|
| 50 |
+
"\e\e[D": backward-word
|
| 51 |
+
|
| 52 |
+
$if term=rxvt
|
| 53 |
+
"\e[7~": beginning-of-line
|
| 54 |
+
"\e[8~": end-of-line
|
| 55 |
+
"\eOc": forward-word
|
| 56 |
+
"\eOd": backward-word
|
| 57 |
+
$endif
|
| 58 |
+
|
| 59 |
+
# for non RH/Debian xterm, can't hurt for RH/Debian xterm
|
| 60 |
+
# "\eOH": beginning-of-line
|
| 61 |
+
# "\eOF": end-of-line
|
| 62 |
+
|
| 63 |
+
# for freebsd console
|
| 64 |
+
# "\e[H": beginning-of-line
|
| 65 |
+
# "\e[F": end-of-line
|
| 66 |
+
|
| 67 |
+
$endif
|
| 68 |
+
|
| 69 |
+
# faster completion
|
| 70 |
+
set show-all-if-ambiguous on
|
| 71 |
+
|
| 72 |
+
"\e[A": history-search-backward
|
| 73 |
+
"\e[B": history-search-forward
|
dockerfiles/dind/.profile
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export PS1='\e[1m\e[31m[\h] \e[32m($(docker-prompt)) \e[34m\u@$(hostname -i)\e[35m \w\e[0m\n$ '
|
| 2 |
+
alias vi='vim'
|
| 3 |
+
export PATH=$PATH:/root/go/bin
|
| 4 |
+
export DOCKER_HOST=""
|
| 5 |
+
cat /etc/motd
|
| 6 |
+
echo $BASHPID > /var/run/cwd
|
dockerfiles/dind/.vimrc
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
syntax on
|
| 2 |
+
set autoindent
|
| 3 |
+
set expandtab
|
| 4 |
+
set number
|
| 5 |
+
set shiftwidth=2
|
| 6 |
+
set softtabstop=2
|
dockerfiles/dind/Dockerfile
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
ARG VERSION=docker:dind
|
| 2 |
+
FROM ${VERSION}
|
| 3 |
+
|
| 4 |
+
RUN apk add --no-cache py-pip python3-dev libffi-dev openssl-dev git tmux apache2-utils vim build-base gettext-dev curl bash-completion bash util-linux jq openssh openssl tree \
|
| 5 |
+
&& ln -s /usr/local/bin/docker /usr/bin/docker
|
| 6 |
+
|
| 7 |
+
ENV GOPATH /root/go
|
| 8 |
+
ENV IPTABLES_LEGACY /usr/local/sbin/.iptables-legacy/
|
| 9 |
+
ENV PATH $IPTABLES_LEGACY:$GOPATH:$PATH
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
ENV DOCKER_TLS_CERTDIR=""
|
| 13 |
+
ENV DOCKER_CLI_EXPERIMENTAL=enabled
|
| 14 |
+
|
| 15 |
+
# Install compose
|
| 16 |
+
ENV COMPOSE_VERSION=2.18.1
|
| 17 |
+
RUN mkdir -p /usr/lib/docker/cli-plugins \
|
| 18 |
+
&& curl -LsS https://github.com/docker/compose/releases/download/v$COMPOSE_VERSION/docker-compose-linux-x86_64 -o /usr/lib/docker/cli-plugins/docker-compose \
|
| 19 |
+
&& chmod +x /usr/lib/docker/cli-plugins/docker-compose
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
# Install scout
|
| 23 |
+
ENV SCOUT_VERSION=1.0.9
|
| 24 |
+
RUN wget -O /tmp/scout.tar.gz https://github.com/docker/scout-cli/releases/download/v1.0.9/docker-scout_1.0.9_linux_amd64.tar.gz \
|
| 25 |
+
&& tar -xvf /tmp/scout.tar.gz docker-scout -C /usr/local/bin \
|
| 26 |
+
&& chmod +x /usr/local/bin/docker-scout \
|
| 27 |
+
&& ln -s $(which docker-scout) /usr/lib/docker/cli-plugins \
|
| 28 |
+
&& rm /tmp/scout.tar.gz
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
# Add bash completion and set bash as default shell
|
| 33 |
+
RUN curl -sS https://raw.githubusercontent.com/docker/cli/refs/heads/master/contrib/completion/bash/docker -o /etc/bash_completion.d/docker \
|
| 34 |
+
&& sed -i "s/ash/bash/" /etc/passwd
|
| 35 |
+
|
| 36 |
+
# Replace modprobe with a no-op to get rid of spurious warnings
|
| 37 |
+
# (note: we can't just symlink to /bin/true because it might be busybox)
|
| 38 |
+
RUN rm /sbin/modprobe && echo '#!/bin/true' >/sbin/modprobe && chmod +x /sbin/modprobe
|
| 39 |
+
|
| 40 |
+
# Install a nice vimrc file and prompt (by soulshake)
|
| 41 |
+
COPY ["docker-prompt", "sudo", "/usr/local/bin/"]
|
| 42 |
+
COPY [".vimrc", ".profile", ".inputrc", ".gitconfig", "./root/"]
|
| 43 |
+
COPY ["motd", "/etc/motd"]
|
| 44 |
+
COPY ["daemon.json", "/etc/docker/"]
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
# Move to our home
|
| 48 |
+
WORKDIR /root
|
| 49 |
+
|
| 50 |
+
# Setup certs and ssh keys
|
| 51 |
+
RUN mkdir -p /var/run/pwd/certs && mkdir -p /var/run/pwd/uploads \
|
| 52 |
+
&& ssh-keygen -N "" -t ed25519 -f /etc/ssh/ssh_host_ed25519_key >/dev/null \
|
| 53 |
+
&& mkdir ~/.ssh && ssh-keygen -N "" -t ed25519 -f ~/.ssh/id_rsa \
|
| 54 |
+
&& cat ~/.ssh/id_rsa.pub > ~/.ssh/authorized_keys
|
| 55 |
+
|
| 56 |
+
# Remove IPv6 alias for localhost and start docker in the background ...
|
| 57 |
+
CMD cat /etc/hosts >/etc/hosts.bak && \
|
| 58 |
+
sed 's/^::1.*//' /etc/hosts.bak > /etc/hosts && \
|
| 59 |
+
sed -i "s/\PWD_IP_ADDRESS/$PWD_IP_ADDRESS/" /etc/docker/daemon.json && \
|
| 60 |
+
sed -i "s/\DOCKER_TLSENABLE/$DOCKER_TLSENABLE/" /etc/docker/daemon.json && \
|
| 61 |
+
sed -i "s/\DOCKER_TLSCACERT/$DOCKER_TLSCACERT/" /etc/docker/daemon.json && \
|
| 62 |
+
sed -i "s/\DOCKER_TLSCERT/$DOCKER_TLSCERT/" /etc/docker/daemon.json && \
|
| 63 |
+
sed -i "s/\DOCKER_TLSKEY/$DOCKER_TLSKEY/" /etc/docker/daemon.json && \
|
| 64 |
+
mount -t securityfs none /sys/kernel/security && \
|
| 65 |
+
echo "root:root" | chpasswd &> /dev/null && \
|
| 66 |
+
/usr/sbin/sshd -o PermitRootLogin=yes -o PrintMotd=no 2>/dev/null && \
|
| 67 |
+
dockerd &>/docker.log & \
|
| 68 |
+
while true ; do script -q -c "/bin/bash -l" /dev/null ; done
|
| 69 |
+
# ... and then put a shell in the foreground, restarting it if it exits
|
dockerfiles/dind/Dockerfile.dind-ee
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
ARG VERSION=franela/docker:ubuntu-19.03ee
|
| 2 |
+
#ARG VERSION=franela/docker:18.09.2-ee-dind
|
| 3 |
+
|
| 4 |
+
FROM ${VERSION}
|
| 5 |
+
|
| 6 |
+
RUN apt-get update \
|
| 7 |
+
&& apt-get install -y git tmux python-pip apache2-utils vim curl jq bash-completion screen tree zip \
|
| 8 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 9 |
+
|
| 10 |
+
# Add kubectl client
|
| 11 |
+
RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.11.7/bin/linux/amd64/kubectl \
|
| 12 |
+
&& chmod +x ./kubectl \
|
| 13 |
+
&& mv ./kubectl /usr/local/bin/kubectl
|
| 14 |
+
|
| 15 |
+
ENV COMPOSE_VERSION=1.22.0
|
| 16 |
+
|
| 17 |
+
RUN pip install docker-compose==${COMPOSE_VERSION}
|
| 18 |
+
RUN curl -L https://github.com/docker/machine/releases/download/${MACHINE_VERSION}/docker-machine-Linux-x86_64 \
|
| 19 |
+
-o /usr/bin/docker-machine && chmod +x /usr/bin/docker-machine
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
# Install a nice vimrc file and prompt (by soulshake)
|
| 23 |
+
COPY ["docker-prompt", "sudo", "ucp-beta.sh", "/usr/local/bin/"]
|
| 24 |
+
COPY [".vimrc",".profile", ".inputrc", ".gitconfig", "workshop_beta.lic", "ucp-config.toml", "./root/"]
|
| 25 |
+
COPY ["motd", "/etc/motd"]
|
| 26 |
+
COPY ["ee/daemon.json", "/etc/docker/"]
|
| 27 |
+
COPY ["ee/cert.pem", "ee/key.pem", "/opt/pwd/certs/"]
|
| 28 |
+
COPY ["ee/ucp-key.pem", "./root/key.pem"]
|
| 29 |
+
COPY ["ee/ucp-cert.pem", "./root/cert.pem"]
|
| 30 |
+
|
| 31 |
+
# Move to our home
|
| 32 |
+
WORKDIR /root
|
| 33 |
+
|
| 34 |
+
# Setup certs and uploads folders
|
| 35 |
+
RUN mkdir -p /opt/pwd/certs /opt/pwd/uploads
|
| 36 |
+
|
| 37 |
+
VOLUME ["/var/lib/kubelet"]
|
| 38 |
+
|
| 39 |
+
# Remove IPv6 alias for localhost and start docker in the background ...
|
| 40 |
+
CMD cat /etc/hosts >/etc/hosts.bak && \
|
| 41 |
+
sed 's/^::1.*//' /etc/hosts.bak > /etc/hosts && \
|
| 42 |
+
sed -i "s/\PWD_IP_ADDRESS/$PWD_IP_ADDRESS/" /etc/docker/daemon.json && \
|
| 43 |
+
sed -i "s/\DOCKER_TLSENABLE/$DOCKER_TLSENABLE/" /etc/docker/daemon.json && \
|
| 44 |
+
sed -i "s/\DOCKER_TLSCACERT/$DOCKER_TLSCACERT/" /etc/docker/daemon.json && \
|
| 45 |
+
sed -i "s/\DOCKER_TLSCERT/$DOCKER_TLSCERT/" /etc/docker/daemon.json && \
|
| 46 |
+
sed -i "s/\DOCKER_TLSKEY/$DOCKER_TLSKEY/" /etc/docker/daemon.json && \
|
| 47 |
+
mount -t securityfs none /sys/kernel/security && \
|
| 48 |
+
mount --make-rshared / && \
|
| 49 |
+
#mount --make-rshared -t tmpfs tmpfs /run && \
|
| 50 |
+
#mount --make-rshared /var/lib/kubelet && \
|
| 51 |
+
#mount --make-rshared /var/lib/docker && \
|
| 52 |
+
dockerd > /docker.log 2>&1 & \
|
| 53 |
+
while true ; do script -q -c "/bin/bash -l" /dev/null ; done
|
| 54 |
+
# ... and then put a shell in the foreground, restarting it if it exits
|
dockerfiles/dind/copy_certs.ps1
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
param (
|
| 2 |
+
[Parameter(Mandatory = $true)]
|
| 3 |
+
[string] $Node,
|
| 4 |
+
[Parameter(Mandatory = $true)]
|
| 5 |
+
[string] $SessionId,
|
| 6 |
+
[Parameter(Mandatory = $true)]
|
| 7 |
+
[string] $FQDN
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
function GetDirectUrlFromIp ($ip) {
|
| 12 |
+
$ip_dash=$ip -replace "\.","-"
|
| 13 |
+
$url="https://ip${ip_dash}-${SessionId}.direct.${FQDN}"
|
| 14 |
+
return $url
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
function WaitForUrl ($url) {
|
| 18 |
+
write-host $url
|
| 19 |
+
do {
|
| 20 |
+
try{
|
| 21 |
+
invoke-webrequest -UseBasicParsing -uri $url | Out-Null
|
| 22 |
+
} catch {}
|
| 23 |
+
$status = $?
|
| 24 |
+
sleep 1
|
| 25 |
+
} until($status)
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
function GetNodeRoutableIp ($nodeName) {
|
| 29 |
+
$JQFilter='.instances[] | select (.hostname == \"{0}\") | .routable_ip' -f $nodeName
|
| 30 |
+
$rip = (invoke-webrequest -UseBasicParsing -uri "https://$FQDN/sessions/$SessionId").Content | jq -r $JQFilter
|
| 31 |
+
|
| 32 |
+
IF([string]::IsNullOrEmpty($rip)) {
|
| 33 |
+
Write-Host "Could not fetch IP for node $nodeName"
|
| 34 |
+
exit 1
|
| 35 |
+
}
|
| 36 |
+
return $rip
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
function Set-UseUnsafeHeaderParsing
|
| 40 |
+
{
|
| 41 |
+
param(
|
| 42 |
+
[Parameter(Mandatory,ParameterSetName='Enable')]
|
| 43 |
+
[switch]$Enable,
|
| 44 |
+
|
| 45 |
+
[Parameter(Mandatory,ParameterSetName='Disable')]
|
| 46 |
+
[switch]$Disable
|
| 47 |
+
)
|
| 48 |
+
|
| 49 |
+
$ShouldEnable = $PSCmdlet.ParameterSetName -eq 'Enable'
|
| 50 |
+
|
| 51 |
+
$netAssembly = [Reflection.Assembly]::GetAssembly([System.Net.Configuration.SettingsSection])
|
| 52 |
+
|
| 53 |
+
if($netAssembly)
|
| 54 |
+
{
|
| 55 |
+
$bindingFlags = [Reflection.BindingFlags] 'Static,GetProperty,NonPublic'
|
| 56 |
+
$settingsType = $netAssembly.GetType('System.Net.Configuration.SettingsSectionInternal')
|
| 57 |
+
|
| 58 |
+
$instance = $settingsType.InvokeMember('Section', $bindingFlags, $null, $null, @())
|
| 59 |
+
|
| 60 |
+
if($instance)
|
| 61 |
+
{
|
| 62 |
+
$bindingFlags = 'NonPublic','Instance'
|
| 63 |
+
$useUnsafeHeaderParsingField = $settingsType.GetField('useUnsafeHeaderParsing', $bindingFlags)
|
| 64 |
+
|
| 65 |
+
if($useUnsafeHeaderParsingField)
|
| 66 |
+
{
|
| 67 |
+
$useUnsafeHeaderParsingField.SetValue($instance, $ShouldEnable)
|
| 68 |
+
}
|
| 69 |
+
}
|
| 70 |
+
}
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
$ProgressPreference = 'SilentlyContinue'
|
| 75 |
+
$ErrorActionPreference = 'Stop'
|
| 76 |
+
|
| 77 |
+
Set-UseUnsafeHeaderParsing -Enable
|
| 78 |
+
|
| 79 |
+
Start-Transcript -path ("C:\{0}.log" -f $MyInvocation.MyCommand.Name) -append
|
| 80 |
+
|
| 81 |
+
add-type @"
|
| 82 |
+
using System.Net;
|
| 83 |
+
using System.Security.Cryptography.X509Certificates;
|
| 84 |
+
|
| 85 |
+
public class IDontCarePolicy : ICertificatePolicy {
|
| 86 |
+
public IDontCarePolicy() {}
|
| 87 |
+
public bool CheckValidationResult(
|
| 88 |
+
ServicePoint sPoint, X509Certificate cert,
|
| 89 |
+
WebRequest wRequest, int certProb) {
|
| 90 |
+
return true;
|
| 91 |
+
}
|
| 92 |
+
}
|
| 93 |
+
"@
|
| 94 |
+
|
| 95 |
+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
| 96 |
+
|
| 97 |
+
[System.Net.ServicePointManager]::CertificatePolicy = new-object IDontCarePolicy
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
$dtr_ip = GetNodeRoutableIp $Node
|
| 101 |
+
$dtr_url = GetDirectUrlFromIp $dtr_ip
|
| 102 |
+
$dtr_hostname = $dtr_url -replace "https://",""
|
| 103 |
+
|
| 104 |
+
WaitForUrl "${dtr_url}/ca"
|
| 105 |
+
|
| 106 |
+
invoke-webrequest -UseBasicParsing -uri "$dtr_url/ca" -o c:\ca.crt
|
| 107 |
+
|
| 108 |
+
$cert = new-object System.Security.Cryptography.X509Certificates.X509Certificate2 c:\ca.crt
|
| 109 |
+
$store = new-object System.Security.Cryptography.X509Certificates.X509Store('Root','localmachine')
|
| 110 |
+
$store.Open('ReadWrite')
|
| 111 |
+
$store.Add($cert)
|
| 112 |
+
$store.Close()
|
| 113 |
+
|
| 114 |
+
Stop-Transcript
|
dockerfiles/dind/daemon.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"experimental": true,
|
| 3 |
+
"debug": true,
|
| 4 |
+
"log-level": "info",
|
| 5 |
+
"registry-mirrors": ["https://mirror.gcr.io"],
|
| 6 |
+
"insecure-registries": [
|
| 7 |
+
"127.0.0.1"
|
| 8 |
+
],
|
| 9 |
+
"hosts": [
|
| 10 |
+
"unix:///var/run/docker.sock",
|
| 11 |
+
"tcp://0.0.0.0:2375"
|
| 12 |
+
],
|
| 13 |
+
"tls": DOCKER_TLSENABLE,
|
| 14 |
+
"tlscacert": "DOCKER_TLSCACERT",
|
| 15 |
+
"tlscert": "DOCKER_TLSCERT",
|
| 16 |
+
"tlskey": "DOCKER_TLSKEY"
|
| 17 |
+
}
|
dockerfiles/dind/docker-prompt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
#!/bin/sh
|
| 3 |
+
case "$DOCKER_HOST" in
|
| 4 |
+
*:3376)
|
| 5 |
+
echo swarm
|
| 6 |
+
;;
|
| 7 |
+
*:2376)
|
| 8 |
+
echo $DOCKER_MACHINE_NAME
|
| 9 |
+
;;
|
| 10 |
+
*:2375)
|
| 11 |
+
echo $DOCKER_MACHINE_NAME
|
| 12 |
+
;;
|
| 13 |
+
*:55555)
|
| 14 |
+
echo $DOCKER_MACHINE_NAME
|
| 15 |
+
;;
|
| 16 |
+
"")
|
| 17 |
+
echo local
|
| 18 |
+
;;
|
| 19 |
+
*)
|
| 20 |
+
echo unknown
|
| 21 |
+
;;
|
| 22 |
+
esac
|
dockerfiles/dind/ee/cert.pem
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-----BEGIN CERTIFICATE-----
|
| 2 |
+
MIIE9jCCAt6gAwIBAgIQSCiXatddwed3bL9M9bierjANBgkqhkiG9w0BAQsFADAO
|
| 3 |
+
MQwwCgYDVQQKEwNVQ1AwHhcNMTcwOTE1MjAzMzAwWhcNMjAwODMwMjAzMzAwWjAO
|
| 4 |
+
MQwwCgYDVQQKEwNVQ1AwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCq
|
| 5 |
+
prmPRweArtZQ6HHDeYCSC3WxQOy6hakc3VZa6JEldbEoVjOc7MqZNPvTIp8b/W8H
|
| 6 |
+
O10ibEGZ03vyeq10UsiFQiYmdhn1SqEilZnFSo892PSpGaN7VO325uUnIccJqc3O
|
| 7 |
+
0YOdvNCdp9roZZ/K7z9nuC37cLy6+Lq2oLr1WYAxncJHedUi3LQCC+2qEBIVL+md
|
| 8 |
+
9yE8amFrYbDhbNqmIcAJ2KmkqBPa0Pa+Qe1FxqQI5zJOT5rOJgF3JbWeqFpm0Zjx
|
| 9 |
+
CPTt0cPY4lyQ2U9lyMXJmS4+R0wekkZXywaU1mJi3JJIlMSBMWmWoTrx5mLVWOLv
|
| 10 |
+
u44hYerfOmN+ImXRWq4NAPLi4722/OLzCmFn81fdUHOFyxg2Tr23b6I6sMyUfLJ0
|
| 11 |
+
lqS+thJ7N/tcQe3nTeQm9dcruDbJpjJQrQkjq9CFFsxNEXBT6EFMRp8oDutOAyHf
|
| 12 |
+
guVeqdH5kz6vprNiLfSTqqZSEeQokRkHTyxpZ4grBBCiocsAxm8yLNqhcg3w44CN
|
| 13 |
+
9G/3pylgu7xYSEXHYnnlxsk0MHxDFZ4NTo0UBuyIuozoePIS63GvsyBsBzKzO/RZ
|
| 14 |
+
NsnPm3klZ4QnT3dIe0eRtCyu/prRmEMD/zC20fRcAuiG7jyV9NB/9mbLeDjAAngW
|
| 15 |
+
1UhrWpAMiObQZN4h5+ofc0EXFHVvOWaqBmYXlNlEeQIDAQABo1AwTjAOBgNVHQ8B
|
| 16 |
+
Af8EBAMCA6gwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMAwGA1UdEwEB
|
| 17 |
+
/wQCMAAwDwYDVR0RBAgwBocEfwAAATANBgkqhkiG9w0BAQsFAAOCAgEAFT1PFimD
|
| 18 |
+
KGg8fVjuUO9IXf12LA7c+M6Eltyz22Ffxgopl1eHi4xHEfU94ueUAmODrag7Rc4E
|
| 19 |
+
VmvrMFIsuFrX/xYjiu2gpHPOP2nQjNRAwKDU0gr2bZ+y98EBtlYO/aFMmYCxJr7B
|
| 20 |
+
6esyA7I/cwLTxaNoTh67VTdPhfDmuEshoQn7Mtop38suevU5YBMTmUl7cp8bVdib
|
| 21 |
+
j7UkTq0oRKmAchMAz3W0TgGw9ZKJzU6zEck/3Csz5RWlTI9HV7R7J8aGEIeHGf/i
|
| 22 |
+
G+tfg0T8h+rQPkyCic5DIYuQzZ/P9pfJkedZuQU/mu0U/0IsNdkv9NX/4RQazu/Q
|
| 23 |
+
OzQ71FOO2HR/S3hcLzS1Iy2zrHbARwji/Sr95gVE1Z4QCK2xSvyy9aqzHwRfc4SX
|
| 24 |
+
AzaJhkACCnY7VDK6WJW7jnfkYco+l0tczDkyPjE7h3wP35tCuAZAvGkcrIbBL4oR
|
| 25 |
+
8bnwYAOqiG0cPBmFDBYW7v19qIspw5XDjfMu4YEHon7pYdiKK0Brf0iL+Ep4b1oB
|
| 26 |
+
8uvAysbc2Z/gIj1AsfnwSnrzcvzO6H1oCye277cSn2Z/ebiBaQi+kR3mubX96aPy
|
| 27 |
+
bFc9Xb11/y0Y7kYmJ3ifHDJkWerpz5bWEm2KDq1qsFRH9zUMEVfJAXThITawqfuG
|
| 28 |
+
3UBYWv8RePLnRbbnPuSaO9slNCoKl3NLqyk=
|
| 29 |
+
-----END CERTIFICATE-----
|
dockerfiles/dind/ee/daemon.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"experimental": true,
|
| 3 |
+
"debug": true,
|
| 4 |
+
"log-level": "info",
|
| 5 |
+
"insecure-registries": ["127.0.0.1"],
|
| 6 |
+
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"],
|
| 7 |
+
"tls": true,
|
| 8 |
+
"tlscert": "/opt/pwd/certs/cert.pem",
|
| 9 |
+
"tlskey": "/opt/pwd/certs/key.pem"
|
| 10 |
+
}
|
dockerfiles/dind/ee/key.pem
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-----BEGIN RSA PRIVATE KEY-----
|
| 2 |
+
MIIJJwIBAAKCAgEAqqa5j0cHgK7WUOhxw3mAkgt1sUDsuoWpHN1WWuiRJXWxKFYz
|
| 3 |
+
nOzKmTT70yKfG/1vBztdImxBmdN78nqtdFLIhUImJnYZ9UqhIpWZxUqPPdj0qRmj
|
| 4 |
+
e1Tt9ublJyHHCanNztGDnbzQnafa6GWfyu8/Z7gt+3C8uvi6tqC69VmAMZ3CR3nV
|
| 5 |
+
Ity0AgvtqhASFS/pnfchPGpha2Gw4WzapiHACdippKgT2tD2vkHtRcakCOcyTk+a
|
| 6 |
+
ziYBdyW1nqhaZtGY8Qj07dHD2OJckNlPZcjFyZkuPkdMHpJGV8sGlNZiYtySSJTE
|
| 7 |
+
gTFplqE68eZi1Vji77uOIWHq3zpjfiJl0VquDQDy4uO9tvzi8wphZ/NX3VBzhcsY
|
| 8 |
+
Nk69t2+iOrDMlHyydJakvrYSezf7XEHt503kJvXXK7g2yaYyUK0JI6vQhRbMTRFw
|
| 9 |
+
U+hBTEafKA7rTgMh34LlXqnR+ZM+r6azYi30k6qmUhHkKJEZB08saWeIKwQQoqHL
|
| 10 |
+
AMZvMizaoXIN8OOAjfRv96cpYLu8WEhFx2J55cbJNDB8QxWeDU6NFAbsiLqM6Hjy
|
| 11 |
+
Eutxr7MgbAcyszv0WTbJz5t5JWeEJ093SHtHkbQsrv6a0ZhDA/8wttH0XALohu48
|
| 12 |
+
lfTQf/Zmy3g4wAJ4FtVIa1qQDIjm0GTeIefqH3NBFxR1bzlmqgZmF5TZRHkCAwEA
|
| 13 |
+
AQKCAgBDSNmBFJBwvH7kB8JTQGThMIOHEAJGyMyVBPA3h9sy2eSv8s0G4pY/MhTY
|
| 14 |
+
ep4hext7znw6RlTXQfts79HUO4+0exBvucEiZfqCmFm44Fz6FcDhq6o5xpLM9t0D
|
| 15 |
+
QN4pgToUgadTWk8m2jgFyYvnh82IJ6Z5rUm8rrVvrJAKjO9uoLUpWXAf/sU6yVk7
|
| 16 |
+
5Ho8wFdsYTRJjeg7XplPSIwtVMFTIIpC0cKCVEH1YikbiebDW+UJ23k+Lt4FDGk/
|
| 17 |
+
1UFPqPSUlON9oWeG7DlzIzua9j6F7k+9Xn80zpfNpc9CgATq1e0XkRCpn8HyEkAb
|
| 18 |
+
gKsXU6SmwVyY7PKecXcpFIbwtMBK2zTG4VrmgsjwptK1S8lbqYftQeTxvNYdhjxA
|
| 19 |
+
gdkBG5qIBkLcr8m796V2fDtJ6wvsVi+yDh+H7T8/vZuB9iaHJ3L1v36WiTODLTFW
|
| 20 |
+
/OlgfimiBXuK8Z1EiB6+w522TdmhKOiWfjHdl7JSzsOla5i5cbcdeaD4AUzlmvGZ
|
| 21 |
+
RCBE9Cd7RWGmDxnWz4NWFepwSfnOOQI9W95QkcRgwH61Y2axcdio0xJpQnUXiKHH
|
| 22 |
+
rHhPTW0eDD7yoIqqKKK3evCOxpbJy6M/+fVqNZYWEfJ0cb7+Ska6aW3rUv8aeYFj
|
| 23 |
+
xzitqKuL/0nFKpeppAkvXvoZf/mM0QtG+lgUHgOngwweYrrkwQKCAQEA3JtXFZDQ
|
| 24 |
+
mIfkv0mAiwV5QbzQ63OxkO0MtPqSq50I8F6S+fIz+ILhxbMjcGq5dCbnJCFGJqn3
|
| 25 |
+
7PXrT6nFXZ8j2/dcXmtxala2VAAq+GyA0TY/DQ6seTaKhsLq50vnzMXHT0pU8s/2
|
| 26 |
+
4n7euf66lzQ1ByKrqXZCAyNajUXPoL37HFgFtCrEJlvi//K8x+tHr3QgF4Si8l31
|
| 27 |
+
A1HLq2+KbppWXzc//knanstsCIxPvEelV0GZn3r5opiOczS30rYo87wKI9aCRgLZ
|
| 28 |
+
GEKrMwlNVwwhScJd4msEYMsXUUxzDcNr5oi+iQmEDJpBKd98+3/Sp9XWVXUbik9a
|
| 29 |
+
QfOvUcQMfDc1pwKCAQEAxgeiaYBb369Z6CW7rC3b3YnwOBJVK23PYcpN2DtnhRRI
|
| 30 |
+
ARZgZBhwYKxDQ3djXZCiPEVtwO4WO8fCcY0GUFP2aVWuaokGjk1gNFwN6F046OdY
|
| 31 |
+
WGETEe7AUCLuuwAv7Aqqug3Y6bxCtPGN3MNHT8qjTH99EMHx8L2+0UiIXnQreGmH
|
| 32 |
+
VL/HEnpfDDZK4nfrwxdJOSueGdyOlflUIpDgmScIbKvIsyKhB2UstFBsCuDzhfE/
|
| 33 |
+
a0VWDnZHgZPA/JhyhRy5eL9QGOqsdnzSxgvEbOyCR5p2jtO9otFw9fxpxF7uA0Yq
|
| 34 |
+
EBye0gidmnF/FKDNK0iggtk34LTrDv2fz4tclXM43wKCAQBY79NC4XgHFjoVGBfX
|
| 35 |
+
dCR3aRy8346Fg9uslpxMzWlOJoKQe6GSHYnRvy+ZYZ1Ug16KBVQXwEwwXtA39JSZ
|
| 36 |
+
8s9tHaNCeYRmv4CQCuVH885XCcyPggvsbh2YyLoU91gDCPUaNThcD5VTqJw4VcZ5
|
| 37 |
+
sNV0A/k6v29LfpRCAhP7lLvIqH/cK6WaZU71qrGK04K57FIHyTQ8C778UJyQh85C
|
| 38 |
+
WrxZdJe696FIhXAPXinDGQtCSzMYxWYgs+ox7d3x9/g4kuVvn0oz2XAWRMJqN+TT
|
| 39 |
+
JBPDfbWF02kXcKj84Jo9wTwd26Ec9BYlUobUz8G+TsDpYt8e4rBwqR8VGZ3jk+sI
|
| 40 |
+
pOVfAoIBAA78xO33KPzk6IkJUgrV7a32opeby5Zd2TQte3bCCDOqNUjfyKvKrbaj
|
| 41 |
+
UvPoNTz/lUe6eXQAkO41UCIH6lJqCFwwf+LQPA7JDF7qGKNdatE1sRn/PtI8n5Fx
|
| 42 |
+
E2BTw0y6AfHS2nfWJ7ZKEdKDdQI08+b2PyDljMoLkkWEl82OPTv/wJ5JZWegm1Dx
|
| 43 |
+
SvmY2d8KBCCvjGeoqaHwHM4A6P6uVZTj62yjUkyc+6Up8QNhwwyAFayosrqleQP1
|
| 44 |
+
isWTRBeO9PqOgCFioWrWR511hog33iRNLGvi2pdYApSbZeXWyWy2Arj1cY+z1zm5
|
| 45 |
+
HUUSZnTAKmW8yt3W03Nu/olWossszUECggEAD+dqDccmWF30yg82mxIMPb8pMV27
|
| 46 |
+
+ciQssiibGmhFvPcIfzish9FunXqLG7q+4M4M+O4WQ9unuaTH+z9TU7w3Foo4Xdf
|
| 47 |
+
GePuwmZdpuYxClHAsNALuKWEJcjfFOdETLkAbk81+ghtyFblkPPI82wofs4K8OII
|
| 48 |
+
1KPPDKoxeXmKXVF1UmOJX1KFyMnEjv0+Z1GrHnNV4703cNTMpDybaGpHsE77Vqd0
|
| 49 |
+
ToZY9VG9eDLzaB6n5emSyFGBG73WQFU4EbLKjEBxtthgu8J9b17x96eF1NGZsEl1
|
| 50 |
+
wEJvZpg7v6wyHK5XcYpwLY19+0khtvXwA7KKEr+sHqzF6arIqhl5hDLDAQ==
|
| 51 |
+
-----END RSA PRIVATE KEY-----
|
dockerfiles/dind/ee/ucp-cert.pem
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-----BEGIN CERTIFICATE-----
|
| 2 |
+
MIIGPDCCBSSgAwIBAgISA4MIK4JV9npV+QdQS7wVa48rMA0GCSqGSIb3DQEBCwUA
|
| 3 |
+
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
|
| 4 |
+
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xODAzMzEyMTQ3MjZaFw0x
|
| 5 |
+
ODA2MjkyMTQ3MjZaMDQxMjAwBgNVBAMMKSouZGlyZWN0LmJldGEtaHlicmlkLnBs
|
| 6 |
+
YXktd2l0aC1kb2NrZXIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
|
| 7 |
+
AQEA6PQCi9Rqr7Ka1KXSGCfBQVzgPyx/hh+uST1dz7PDw2epghYyaqNByaQEVKNR
|
| 8 |
+
3ubPvOoASzhdJ1dZdyUzKUoU/jm8hgVK7HHdQDpFEX60az+r4Xo32R6WirG5+GXd
|
| 9 |
+
hU3M0yRzbu0zZx7eVZognP/HcXJDhuf16hiHKmCr6MYXV4JY9xLMxExZOTB4fpGA
|
| 10 |
+
Loiyvn2OEZAhREhiSX+6n4x7KJga8gYn/0f89o7up1DYQSwev+gQgRjTGlo1xrgu
|
| 11 |
+
Oztekc3ydvbhGv7aL7Uj/zqPcVvXnDfnioQV7kEDcz8gupFyV7gZKolR1G8IQJdm
|
| 12 |
+
TaYHguzFXF5Q3lKVWx19/CSZ8wIDAQABo4IDMDCCAywwDgYDVR0PAQH/BAQDAgWg
|
| 13 |
+
MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0G
|
| 14 |
+
A1UdDgQWBBTVloZoUI5vKAN+D1PTgtYBgU184zAfBgNVHSMEGDAWgBSoSmpjBH3d
|
| 15 |
+
uubRObemRWXv86jsoTBvBggrBgEFBQcBAQRjMGEwLgYIKwYBBQUHMAGGImh0dHA6
|
| 16 |
+
Ly9vY3NwLmludC14My5sZXRzZW5jcnlwdC5vcmcwLwYIKwYBBQUHMAKGI2h0dHA6
|
| 17 |
+
Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5vcmcvMDQGA1UdEQQtMCuCKSouZGly
|
| 18 |
+
ZWN0LmJldGEtaHlicmlkLnBsYXktd2l0aC1kb2NrZXIuY29tMIH+BgNVHSAEgfYw
|
| 19 |
+
gfMwCAYGZ4EMAQIBMIHmBgsrBgEEAYLfEwEBATCB1jAmBggrBgEFBQcCARYaaHR0
|
| 20 |
+
cDovL2Nwcy5sZXRzZW5jcnlwdC5vcmcwgasGCCsGAQUFBwICMIGeDIGbVGhpcyBD
|
| 21 |
+
ZXJ0aWZpY2F0ZSBtYXkgb25seSBiZSByZWxpZWQgdXBvbiBieSBSZWx5aW5nIFBh
|
| 22 |
+
cnRpZXMgYW5kIG9ubHkgaW4gYWNjb3JkYW5jZSB3aXRoIHRoZSBDZXJ0aWZpY2F0
|
| 23 |
+
ZSBQb2xpY3kgZm91bmQgYXQgaHR0cHM6Ly9sZXRzZW5jcnlwdC5vcmcvcmVwb3Np
|
| 24 |
+
dG9yeS8wggEDBgorBgEEAdZ5AgQCBIH0BIHxAO8AdQDbdK/uyynssf7KPnFtLOW5
|
| 25 |
+
qrs294Rxg8ddnU83th+/ZAAAAWJ+PniYAAAEAwBGMEQCIDngZdWcYWY0fPfUGTqX
|
| 26 |
+
/Vt2qx+PRN5DN+m13TnA37e2AiBHIi5kMSxlvKNc3xzuJrvt/RKaj9xsBLmc8+uW
|
| 27 |
+
ckaEdAB2ACk8UZZUyDlluqpQ/FgH1Ldvv1h6KXLcpMMM9OVFR/R4AAABYn4+eLUA
|
| 28 |
+
AAQDAEcwRQIhAMkf8SYdt1egjzBE6nzOrY+f4WMS/N6XWN+gFl0mQIkhAiBn9+GG
|
| 29 |
+
0XbLw33+WNJLUkau2ZdTo5kTw2qdUXdYpWJwrDANBgkqhkiG9w0BAQsFAAOCAQEA
|
| 30 |
+
TAl62gFi+2l/yLItjNIrXeWh2ICH/epjeWlmF+rAb7Sb4iz9U8fsNBdDBQh25xJo
|
| 31 |
+
6nLOlS2NG0hdUScylCYyGJZe6PeQvGO+qSLDamXf1DvXWvzbmQOCUkejgD7Uwbol
|
| 32 |
+
5huuCAKoW4SsiaMku0J3545MEQx4Q5cPetsPawaByY5sgr2GZJzgM7lvtzr4hKWg
|
| 33 |
+
x5QAns/bmcqe9LCJ2NLcgArliYu6dOHtS62kB7/Dz2DQRtCvpV553RaBe4k9Ruwl
|
| 34 |
+
0ndHvjEC5OWa5sW1hwow5W3PC7Db7s0zqpt63EITkhrUOqtqtkwOMYBAkFIIe1eR
|
| 35 |
+
T5fSFAdirKUOt5GnRJ40qw==
|
| 36 |
+
-----END CERTIFICATE-----
|
| 37 |
+
-----BEGIN CERTIFICATE-----
|
| 38 |
+
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
|
| 39 |
+
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
|
| 40 |
+
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
|
| 41 |
+
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
|
| 42 |
+
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
| 43 |
+
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
|
| 44 |
+
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
|
| 45 |
+
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
|
| 46 |
+
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
|
| 47 |
+
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
|
| 48 |
+
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
|
| 49 |
+
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
|
| 50 |
+
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
|
| 51 |
+
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
|
| 52 |
+
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
|
| 53 |
+
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
|
| 54 |
+
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
|
| 55 |
+
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
|
| 56 |
+
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
|
| 57 |
+
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
|
| 58 |
+
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
|
| 59 |
+
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
|
| 60 |
+
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
|
| 61 |
+
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
|
| 62 |
+
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
|
| 63 |
+
-----END CERTIFICATE-----
|
dockerfiles/dind/ee/ucp-key.pem
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-----BEGIN PRIVATE KEY-----
|
| 2 |
+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDo9AKL1GqvsprU
|
| 3 |
+
pdIYJ8FBXOA/LH+GH65JPV3Ps8PDZ6mCFjJqo0HJpARUo1He5s+86gBLOF0nV1l3
|
| 4 |
+
JTMpShT+ObyGBUrscd1AOkURfrRrP6vhejfZHpaKsbn4Zd2FTczTJHNu7TNnHt5V
|
| 5 |
+
miCc/8dxckOG5/XqGIcqYKvoxhdXglj3EszETFk5MHh+kYAuiLK+fY4RkCFESGJJ
|
| 6 |
+
f7qfjHsomBryBif/R/z2ju6nUNhBLB6/6BCBGNMaWjXGuC47O16RzfJ29uEa/tov
|
| 7 |
+
tSP/Oo9xW9ecN+eKhBXuQQNzPyC6kXJXuBkqiVHUbwhAl2ZNpgeC7MVcXlDeUpVb
|
| 8 |
+
HX38JJnzAgMBAAECggEAVqm4bMa4bea3HRcXYu8fQS7JKhdm1cHhd9PBm6yXzpE5
|
| 9 |
+
CXEyjmNv7RD8n3Qm2BLsA67WLyWn2iPv35hSQTETQETAcudzKSVvFx7WZRzLB/8m
|
| 10 |
+
9XofXsG3ZZ+avONAlwALjB1KaGEMN3fPZO8y5NVvIDBPGNggr1cyqbxPGAjh1Cav
|
| 11 |
+
Laqki0rdPfr3FhxTyPBdmBFDcaMLc77Yl/7rmQJRYWb1qe+g4SEG4xXmEYpcpSUz
|
| 12 |
+
zDJZAkY5XAO5cHU5EoKgKJedVBNxqAaRtaisO9yv+CKMqD83hAWhXqeK1bSphghs
|
| 13 |
+
2qIkzNe134ZNUBbmK2FDsAbiPMHNcMKuI4ljfb78iQKBgQD5oZ/uzaYTt6ZQQzKq
|
| 14 |
+
rQFA2DxSlBt4Ewae5n6JYzw0hIjRf7LvitZF9zKXcMkHP2QcL+5RiibyJ6ohGypa
|
| 15 |
+
jpDP+m5e0B5tS6gEgFzBnrXWbjnrDxUR5Qj0lKg3uuOXw8OdwNxn+MulKkIfGyTW
|
| 16 |
+
pCu7G1nh/kltwvN87s4cJycwnwKBgQDu5XUyIcok8nxcBwtxu3zFdtdNn+P4Yq1a
|
| 17 |
+
W2sUEUEJUDwcUZqksPIxQhG/SMEEtBqii+EJj3nAlaWItBgTE37mzKGyKv16ZiM1
|
| 18 |
+
hr+Rlv5AURxER+Eo4JLFqULZKwMaDlXDrFdV2ulF+6SXWOqKrp4/6sPYxtxHmKfs
|
| 19 |
+
oBnXq/4yLQKBgCQFl5+NG2cC/EPevoP0fRbPXT0JVEFqdW0ek6ndoQVvDpM0myyH
|
| 20 |
+
202zUyCZTNj348lRfVFU3zPYV2t5kQ4KPolUePLDk3BwF2m24CusbE7qDv+FaKPx
|
| 21 |
+
ae5pOTD5jfgLbsHn36Y9N5240FvOve0fOZRBaSH8YLovBJXFnAZh+/y/AoGALZzQ
|
| 22 |
+
CJddAjruNZ/+tmNmykkLiL2riERG9waXZkh5E28nWvzVuvYx9+e2fcBFYkGFCF4O
|
| 23 |
+
xIWJaJTp+zTvl8zUIPsXMG524UTZGiI1N3YN63fRHtRekDB4tZbAtbg5qmLsSyT/
|
| 24 |
+
s9vNSFhor6EBfyMiAfAwHpaxflYOUearqHslWK0CgYEAzi/B0azCOaDqzpp6RhAL
|
| 25 |
+
rhTRFfu2HR8wN8EJLOSbBbUnlSSJHdnHJBwyyXe3shD/rETLV8dHx+6/k47e1l2d
|
| 26 |
+
MUlsad/dOKQyL2pY7UodBzPJkIkmwknDnKzioGety8Tb98oUSTQ8oHfHMuRBOie9
|
| 27 |
+
mq1MSTuZyZtsdSXnFhH3qNc=
|
| 28 |
+
-----END PRIVATE KEY-----
|
dockerfiles/dind/motd
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
###############################################################
|
| 2 |
+
# WARNING!!!! #
|
| 3 |
+
# This is a sandbox environment. Using personal credentials #
|
| 4 |
+
# is HIGHLY! discouraged. Any consequences of doing so are #
|
| 5 |
+
# completely the user's responsibilites. #
|
| 6 |
+
# #
|
| 7 |
+
# The PWD team. #
|
| 8 |
+
###############################################################
|
dockerfiles/dind/ssh_config
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Host *
|
| 2 |
+
StrictHostKeyChecking no
|
dockerfiles/dind/sudo
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
|
| 3 |
+
# This is shim to help with the case were pasted commands from a readme assume you are not root. Since this isto be run by root, it should effectively be a dummy command that allows the parameters to pass through.
|
| 4 |
+
|
| 5 |
+
exec "$@"
|
dockerfiles/dind/ucp-beta.sh
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
set -e
|
| 4 |
+
|
| 5 |
+
function wait_for_url {
|
| 6 |
+
# Wait for docker daemon to be ready
|
| 7 |
+
while ! curl -k -sS $1 > /dev/null; do
|
| 8 |
+
sleep 1;
|
| 9 |
+
done
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
function deploy_ucp {
|
| 13 |
+
wait_for_url "https://localhost:2376"
|
| 14 |
+
|
| 15 |
+
docker config create com.docker.ucp.config $HOME/ucp-config.toml
|
| 16 |
+
|
| 17 |
+
docker run --rm -i --name ucp \
|
| 18 |
+
-v /var/run/docker.sock:/var/run/docker.sock \
|
| 19 |
+
docker/ucp:3.2.3 install --debug --force-insecure-tcp --skip-cloud-provider-check \
|
| 20 |
+
--san *.direct.${PWD_HOST_FQDN} \
|
| 21 |
+
--license $(cat $HOME/workshop_beta.lic) \
|
| 22 |
+
--swarm-port 2375 \
|
| 23 |
+
--existing-config \
|
| 24 |
+
--admin-username admin \
|
| 25 |
+
--admin-password admin1234
|
| 26 |
+
|
| 27 |
+
rm $HOME/workshop_beta.lic $HOME/ucp-config.toml
|
| 28 |
+
echo "Finished deploying UCP"
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
function get_instance_ip {
|
| 32 |
+
ip -o -4 a s eth1 | awk '{print $4}' | cut -d '/' -f1
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
function get_node_routable_ip {
|
| 36 |
+
curl -sS https://${PWD_HOST_FQDN}/sessions/${SESSION_ID} | jq -r '.instances[] | select(.hostname == "'$1'") | .routable_ip'
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
function get_direct_url_from_ip {
|
| 40 |
+
local ip_dash="${1//./-}"
|
| 41 |
+
local url="https://ip${ip_dash}-${SESSION_ID}.direct.${PWD_HOST_FQDN}"
|
| 42 |
+
echo $url
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
function deploy_dtr {
|
| 46 |
+
if [ $# -lt 1 ]; then
|
| 47 |
+
echo "DTR node hostname"
|
| 48 |
+
return
|
| 49 |
+
fi
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
local dtr_ip=$(get_node_routable_ip $1)
|
| 53 |
+
local ucp_ip=$(get_instance_ip)
|
| 54 |
+
|
| 55 |
+
local dtr_url=$(get_direct_url_from_ip $dtr_ip)
|
| 56 |
+
local ucp_url=$(get_direct_url_from_ip $ucp_ip)
|
| 57 |
+
|
| 58 |
+
docker run -i --rm docker/dtr:2.7.3 install \
|
| 59 |
+
--dtr-external-url $dtr_url \
|
| 60 |
+
--ucp-node $1 \
|
| 61 |
+
--ucp-username admin \
|
| 62 |
+
--ucp-password admin1234 \
|
| 63 |
+
--ucp-insecure-tls \
|
| 64 |
+
--ucp-url $ucp_url
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
function setup_dtr_certs {
|
| 68 |
+
if [ $# -lt 1 ]; then
|
| 69 |
+
echo "DTR node hostname is missing"
|
| 70 |
+
return
|
| 71 |
+
fi
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
local dtr_ip=$(get_node_routable_ip $1)
|
| 75 |
+
local dtr_url=$(get_direct_url_from_ip $dtr_ip)
|
| 76 |
+
local dtr_hostname="${dtr_url/https:\/\/}"
|
| 77 |
+
|
| 78 |
+
wait_for_url "$dtr_url/ca"
|
| 79 |
+
|
| 80 |
+
curl -kfsSL $dtr_url/ca -o /usr/local/share/ca-certificates/$dtr_hostname.crt
|
| 81 |
+
update-ca-certificates
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
case "$1" in
|
| 86 |
+
deploy)
|
| 87 |
+
deploy_ucp
|
| 88 |
+
deploy_dtr $2
|
| 89 |
+
setup_dtr_certs $2
|
| 90 |
+
;;
|
| 91 |
+
setup-certs)
|
| 92 |
+
setup_dtr_certs $2
|
| 93 |
+
;;
|
| 94 |
+
*)
|
| 95 |
+
echo "Illegal option $1"
|
| 96 |
+
;;
|
| 97 |
+
esac
|
| 98 |
+
|
dockerfiles/dind/ucp-config.toml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[cluster_config]
|
| 2 |
+
custom_kubelet_flags = ["--http-check-frequency=20s", "--containerized=false"]
|
dockerfiles/dind/ucp.sh
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
set -e
|
| 4 |
+
|
| 5 |
+
function wait_for_url {
|
| 6 |
+
# Wait for docker daemon to be ready
|
| 7 |
+
while ! curl -k -sS $1 > /dev/null; do
|
| 8 |
+
sleep 1;
|
| 9 |
+
done
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
function deploy_ucp {
|
| 13 |
+
wait_for_url "https://localhost:2376"
|
| 14 |
+
docker run --rm -i --name ucp \
|
| 15 |
+
-v /var/run/docker.sock:/var/run/docker.sock \
|
| 16 |
+
docker/ucp:3.2.3 install --debug --force-insecure-tcp --skip-cloud-provider-check \
|
| 17 |
+
--san *.direct.${PWD_HOST_FQDN} \
|
| 18 |
+
--license $(cat $HOME/workshop_beta.lic) \
|
| 19 |
+
--swarm-port 2375 \
|
| 20 |
+
--admin-username admin \
|
| 21 |
+
--admin-password admin1234
|
| 22 |
+
|
| 23 |
+
rm $HOME/workshop_beta.lic
|
| 24 |
+
echo "Finished deploying UCP"
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
function get_instance_ip {
|
| 28 |
+
ip -o -4 a s eth1 | awk '{print $4}' | cut -d '/' -f1
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
function get_node_routable_ip {
|
| 32 |
+
curl -sS https://${PWD_HOST_FQDN}/sessions/${SESSION_ID} | jq -r '.instances[] | select(.hostname == "'$1'") | .routable_ip'
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
function get_direct_url_from_ip {
|
| 36 |
+
local ip_dash="${1//./-}"
|
| 37 |
+
local url="https://ip${ip_dash}-${SESSION_ID}.direct.${PWD_HOST_FQDN}"
|
| 38 |
+
echo $url
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
function deploy_dtr {
|
| 42 |
+
if [ $# -lt 1 ]; then
|
| 43 |
+
echo "DTR node hostname"
|
| 44 |
+
return
|
| 45 |
+
fi
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
local dtr_ip=$(get_node_routable_ip $1)
|
| 49 |
+
local ucp_ip=$(get_instance_ip)
|
| 50 |
+
|
| 51 |
+
local dtr_url=$(get_direct_url_from_ip $dtr_ip)
|
| 52 |
+
local ucp_url=$(get_direct_url_from_ip $ucp_ip)
|
| 53 |
+
|
| 54 |
+
docker run -i --rm docker/dtr:2.7.3 install \
|
| 55 |
+
--dtr-external-url $dtr_url \
|
| 56 |
+
--ucp-node $1 \
|
| 57 |
+
--ucp-username admin \
|
| 58 |
+
--ucp-password admin1234 \
|
| 59 |
+
--ucp-insecure-tls \
|
| 60 |
+
--ucp-url $ucp_url
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
function setup_dtr_certs {
|
| 64 |
+
if [ $# -lt 1 ]; then
|
| 65 |
+
echo "DTR node hostname is missing"
|
| 66 |
+
return
|
| 67 |
+
fi
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
local dtr_ip=$(get_node_routable_ip $1)
|
| 71 |
+
local dtr_url=$(get_direct_url_from_ip $dtr_ip)
|
| 72 |
+
local dtr_hostname="${dtr_url/https:\/\/}"
|
| 73 |
+
|
| 74 |
+
wait_for_url "$dtr_url/ca"
|
| 75 |
+
|
| 76 |
+
curl -kfsSL $dtr_url/ca -o /usr/local/share/ca-certificates/$dtr_hostname.crt
|
| 77 |
+
update-ca-certificates
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
case "$1" in
|
| 82 |
+
deploy)
|
| 83 |
+
deploy_ucp
|
| 84 |
+
deploy_dtr $2
|
| 85 |
+
setup_dtr_certs $2
|
| 86 |
+
;;
|
| 87 |
+
setup-certs)
|
| 88 |
+
setup_dtr_certs $2
|
| 89 |
+
;;
|
| 90 |
+
*)
|
| 91 |
+
echo "Illegal option $1"
|
| 92 |
+
;;
|
| 93 |
+
esac
|
| 94 |
+
|
dockerfiles/dind/workshop.lic
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"key_id":"B3T_Uirjs-tpcGd4Tql8HL--kDo1iTOUaVUFNMhEXM1Z","private_key":"RbtCEoNZ4OBu-yIHNM1mGCJ6R_4SxF-ThghAd-I3b6_N","authorization":"ewogICAicGF5bG9hZCI6ICJleUpsZUhCcGNtRjBhVzl1SWpvaU1qQXhPUzB3TkMweU5GUXhPRG93TkRvek5Gb2lMQ0owYjJ0bGJpSTZJbU16U1VnMllWSjFWak00WjBWSVIwWXRVV1l0ZGxGM2MwMHdlR05vYnpoWE4xSklPRzFLYVRaT1VUUTlJaXdpYldGNFJXNW5hVzVsY3lJNk1UQXNJbk5qWVc1dWFXNW5SVzVoWW14bFpDSTZkSEoxWlN3aWJHbGpaVzV6WlZSNWNHVWlPaUpQWm1ac2FXNWxJaXdpZEdsbGNpSTZJbEJ5YjJSMVkzUnBiMjRpZlEiLAogICAic2lnbmF0dXJlcyI6IFsKICAgICAgewogICAgICAgICAiaGVhZGVyIjogewogICAgICAgICAgICAiandrIjogewogICAgICAgICAgICAgICAiZSI6ICJBUUFCIiwKICAgICAgICAgICAgICAgImtleUlEIjogIko3TEQ6NjdWUjpMNUhaOlU3QkE6Mk80Rzo0QUwzOk9GMk46SkhHQjpFRlRIOjVDVlE6TUZFTzpBRUlUIiwKICAgICAgICAgICAgICAgImtpZCI6ICJKN0xEOjY3VlI6TDVIWjpVN0JBOjJPNEc6NEFMMzpPRjJOOkpIR0I6RUZUSDo1Q1ZROk1GRU86QUVJVCIsCiAgICAgICAgICAgICAgICJrdHkiOiAiUlNBIiwKICAgICAgICAgICAgICAgIm4iOiAieWRJeS1sVTdvN1BjZVktNC1zLUNRNU9FZ0N5RjhDeEljUUlXdUs4NHBJaVpjaVk2NzMweUNZbndMU0tUbHctVTZVQ19RUmVXUmlvTU5ORTVEczVUWUVYYkdHNm9sbTJxZFdiQndjQ2ctMlVVSF9PY0I5V3VQNmdSUEhwTUZNc3hEeld3dmF5OEpVdUhnWVVMVXBtMUl2LW1xN2xwNW5RX1J4clQwS1pSQVFUWUxFTUVmR3dtM2hNT19nZUxQUy1oZ0tQdElIbGtnNl9XY294VEdvS1A3OWRfd2FIWXhHTmw3V2hTbmVpQlN4YnBiUUFLazIxbGc3OThYYjd2WnlFQVRETXJSUjlNZUU2QWRqNUhKcFkzQ295UkFQQ21hS0dSQ0s0dW9aU29JdTBoRlZsS1VQeWJidzAwMEdPLXdhMktOOFV3Z0lJbTBpNUkxdVc5R2txNHpqQnk1emhncXVVWGJHOWJXUEFPWXJxNVFhODFEeEdjQmxKeUhZQXAtRERQRTlUR2c0elltWGpKbnhacUhFZHVHcWRldlo4WE1JMHVrZmtHSUkxNHdVT2lNSUlJclhsRWNCZl80Nkk4Z1FXRHp4eWNaZV9KR1gtTEF1YXlYcnlyVUZlaFZOVWRaVWw5d1hOYUpCLWthQ3F6NVF3YVI5M3NHdy1RU2Z0RDBOdkxlN0N5T0gtRTZ2ZzZTdF9OZVR2Z3Y4WW5oQ2lYSWxaOEhPZkl3TmU3dEVGX1VjejVPYlB5a20zdHlsck5VanQwVnlBbXR0YWNWSTJpR2loY1VQcm1rNGxWSVo3VkRfTFNXLWk3eW9TdXJ0cHNQWGNlMnBLRElvMzBsSkdoT18zS1VtbDJTVVpDcXpKMXlFbUtweXNINUhEVzljc0lGQ0EzZGVBamZaVXZON1UiCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJhbGciOiAiUlMyNTYiCiAgICAgICAgIH0sCiAgICAgICAgICJzaWduYXR1cmUiOiAid2xrQUhLd0l1TUs5Y0N3YUdINVB1MW50dGNkLVk0SkNsRnpLeTZtcmJlTzR3eXFOenpwUi16TG4tMlhsYnJGZTdlczYtSklSREhmNzBGR3JRZl9MZEc3QVQ4bC1HRXVoUk1SaF8xVTlXd1BkOGdsWnNFem44VFUyeGtzU3lkWEw2WER3TUlqMHJUMFdpQm43T29YcEc0ZGJrUGgwLWxfY1VKQnphQzlwbEZ3ZXdmdF9Ocl80a0FpcUlNa3FJZHdQaU5XOVc4NERPUFdpZ2FrcTZTTnRtMVpqT2E1UG1ldHUydk1iUGpnTzFZM19tUVFsUldpakRwRUR1Rzl1dl9yNDFsN1I2LTdKQTB6SGpvdVVqdkxDREdIMUQ3eUxnR1RFMTlXN2FMRHI4ZE5FeXBjdi1vQzVmb3pqM19ISjUyWXVDS0RnazJzb3Y5YVFYOHhNTW5DWGU4Y3JIYjlEVG05eVcyd09FN0kxYVZLYXRKbjZrSGprM1FSWGVNbnRNQnJ6TGlzanBjZnlBYzdGNlc1YnBTSUtXaUQtd2o5QTRlY0FPbFNxc0NBS3lkaWxnR2lqQTNPY1dOZHhvV0NhV1MzaXFvakFBTE1JNHlsOFlpdG50ckVMVFNuUDFFS08wTGFaaTJxVURfU0lBSmFOUlRPTVIzblRqQUNwd1ZwYXAyU3lkOEZwc1pFVllTZFJVLWJVZDJybmN1ZHZfcC1XdFZpYWVsQ3BvTWstdURzWGhud2JyWFB6Y3dkVHVobmg0V2kxMmRTcjRUQ3ZMRktSMklCaklwam1VZWt4MFBTazlKUkNXc2R2bjY0dElCZnV6dVZSRkVkSVBidnBZd2pWOUZZc19VQWJvVE85a2E1OWZmNm1zOThHYXVTbE9sYnkwSWE0TlBxTTRKY2ZvSFUiLAogICAgICAgICAicHJvdGVjdGVkIjogImV5Sm1iM0p0WVhSTVpXNW5kR2dpT2pFM05Dd2labTl5YldGMFZHRnBiQ0k2SW1aUklpd2lkR2x0WlNJNklqSXdNVGd0TURVdE1UWlVNREU2TURNNk1qTmFJbjAiCiAgICAgIH0KICAgXQp9"}
|
dockerfiles/k8s/.bashrc
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export PS1="[\h \W]$ "
|
| 2 |
+
cat /etc/motd
|
| 3 |
+
echo $BASHPID > /var/run/cwd
|
dockerfiles/k8s/Dockerfile
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM centos:7
|
| 2 |
+
|
| 3 |
+
COPY ./systemctl /usr/bin/systemctl
|
| 4 |
+
COPY ./kubernetes.repo /etc/yum.repos.d/
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
RUN yum install -y kubectl-1.27.2 kubeadm-1.27.2 kubelet-1.27.2 \
|
| 9 |
+
#&& mv -f /etc/systemd/system/kubelet.service.d/10-kubeadm.conf /etc/systemd/system/kubelet.service \
|
| 10 |
+
&& yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo \
|
| 11 |
+
&& yum install -y docker-ce git bash-completion \
|
| 12 |
+
&& sed -i -e '4d;5d;8d' /lib/systemd/system/docker.service \
|
| 13 |
+
&& yum clean all
|
| 14 |
+
|
| 15 |
+
RUN curl -Lf -o /usr/bin/jq https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 \
|
| 16 |
+
&& curl -Lf -o /usr/bin/docker-compose https://github.com/docker/compose/releases/download/1.21.0/docker-compose-$(uname -s)-$(uname -m) \
|
| 17 |
+
&& chmod +x /usr/bin/jq /usr/bin/docker-compose
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
VOLUME ["/var/lib/kubelet"]
|
| 21 |
+
|
| 22 |
+
COPY ./kube* /etc/systemd/system/
|
| 23 |
+
COPY ./wrapkubeadm.sh /usr/local/bin/kubeadm
|
| 24 |
+
COPY ./tokens.csv /etc/pki/tokens.csv
|
| 25 |
+
COPY ./daemon.json /etc/docker/
|
| 26 |
+
COPY ./resolv.conf.override /etc/
|
| 27 |
+
COPY ./docker.service /usr/lib/systemd/system/
|
| 28 |
+
COPY ./.bashrc /root/
|
| 29 |
+
|
| 30 |
+
COPY motd /etc/motd
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
RUN echo 'source <(kubectl completion bash)' >>~/.bashrc \
|
| 34 |
+
&& kubectl completion bash >> /etc/bash_completion.d/kubectl
|
| 35 |
+
|
| 36 |
+
RUN mkdir -p /root/.kube && ln -s /etc/kubernetes/admin.conf /root/.kube/config \
|
| 37 |
+
&& rm -f /etc/machine-id
|
| 38 |
+
|
| 39 |
+
WORKDIR /root
|
| 40 |
+
|
| 41 |
+
CMD mount --make-shared / \
|
| 42 |
+
&& systemctl start docker \
|
| 43 |
+
&& systemctl start kubelet \
|
| 44 |
+
&& while true; do script -q -c "/bin/bash -l" /dev/null; done
|
dockerfiles/k8s/daemon.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"experimental": true,
|
| 3 |
+
"debug": true,
|
| 4 |
+
"cri-containerd": true,
|
| 5 |
+
"log-level": "info",
|
| 6 |
+
"tls": false,
|
| 7 |
+
"insecure-registries": [
|
| 8 |
+
"127.0.0.1"
|
| 9 |
+
],
|
| 10 |
+
"hosts": [
|
| 11 |
+
"unix:///var/run/docker.sock",
|
| 12 |
+
"tcp://0.0.0.0:2375"
|
| 13 |
+
]
|
| 14 |
+
}
|
dockerfiles/k8s/docker.service
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[Unit]
|
| 2 |
+
Description=Docker Application Container Engine
|
| 3 |
+
Documentation=https://docs.docker.com
|
| 4 |
+
|
| 5 |
+
[Service]
|
| 6 |
+
# the default is not to use systemd for cgroups because the delegate issues still
|
| 7 |
+
# exists and systemd currently does not support the cgroup feature set required
|
| 8 |
+
# for containers run by docker
|
| 9 |
+
ExecStart=/usr/bin/dockerd
|
| 10 |
+
ExecReload=/bin/kill -s HUP $MAINPID
|
| 11 |
+
# Having non-zero Limit*s causes performance problems due to accounting overhead
|
| 12 |
+
# in the kernel. We recommend using cgroups to do container-local accounting.
|
| 13 |
+
LimitNOFILE=infinity
|
| 14 |
+
LimitNPROC=infinity
|
| 15 |
+
LimitCORE=infinity
|
| 16 |
+
# Uncomment TasksMax if your systemd version supports it.
|
| 17 |
+
# Only systemd 226 and above support this version.
|
| 18 |
+
#TasksMax=infinity
|
| 19 |
+
TimeoutStartSec=0
|
| 20 |
+
# set delegate yes so that systemd does not reset the cgroups of docker containers
|
| 21 |
+
Delegate=yes
|
| 22 |
+
# kill only the docker process, not all processes in the cgroup
|
| 23 |
+
KillMode=process
|
| 24 |
+
# restart the docker process if it exits prematurely
|
| 25 |
+
Restart=on-failure
|
| 26 |
+
StartLimitBurst=3
|
| 27 |
+
StartLimitInterval=60s
|
| 28 |
+
|
| 29 |
+
[Install]
|
| 30 |
+
WantedBy=multi-user.target
|
dockerfiles/k8s/kubelet.env
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
KUBELET_KUBECONFIG_ARGS="--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
|
| 2 |
+
KUBELET_SYSTEM_PODS_ARGS="--pod-manifest-path=/etc/kubernetes/manifests"
|
| 3 |
+
KUBELET_DNS_ARGS="--cluster-dns=10.96.0.10 --cluster-domain=cluster.local"
|
| 4 |
+
KUBELET_AUTHZ_ARGS="--authorization-mode=Webhook --client-ca-file=/etc/kubernetes/pki/ca.crt"
|
| 5 |
+
KUBELET_CGROUP_ARGS="--cgroup-driver=cgroupfs"
|
| 6 |
+
KUBELET_EXTRA_ARGS="--fail-swap-on=false --resolv-conf=/etc/resolv.conf.override --container-runtime-endpoint /run/docker/containerd/containerd.sock "
|
dockerfiles/k8s/kubelet.service
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[Service]
|
| 2 |
+
Restart=always
|
| 3 |
+
EnvironmentFile=/etc/systemd/system/kubelet.env
|
| 4 |
+
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CGROUP_ARGS $KUBELET_EXTRA_ARGS
|
dockerfiles/k8s/kubernetes.repo
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[kubernetes]
|
| 2 |
+
name=Kubernetes
|
| 3 |
+
baseurl=https://pkgs.k8s.io/core:/stable:/v1.28/rpm/
|
| 4 |
+
enabled=1
|
| 5 |
+
gpgcheck=1
|
| 6 |
+
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.28/rpm/repodata/repomd.xml.key
|
| 7 |
+
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
|
dockerfiles/k8s/motd
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
WARNING!!!!
|
| 3 |
+
|
| 4 |
+
This is a sandbox environment. Using personal credentials
|
| 5 |
+
is HIGHLY! discouraged. Any consequences of doing so, are
|
| 6 |
+
completely the user's responsibilites.
|
| 7 |
+
|
| 8 |
+
You can bootstrap a cluster as follows:
|
| 9 |
+
|
| 10 |
+
1. Initializes cluster master node:
|
| 11 |
+
|
| 12 |
+
kubeadm init --apiserver-advertise-address $(hostname -i) --pod-network-cidr 10.5.0.0/16
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
2. Initialize cluster networking:
|
| 16 |
+
|
| 17 |
+
kubectl apply -f https://raw.githubusercontent.com/cloudnativelabs/kube-router/master/daemonset/kubeadm-kuberouter.yaml
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
3. (Optional) Create an nginx deployment:
|
| 21 |
+
|
| 22 |
+
kubectl apply -f https://raw.githubusercontent.com/kubernetes/website/master/content/en/examples/application/nginx-app.yaml
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
The PWK team.
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
|
dockerfiles/k8s/resolv.conf.override
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
nameserver 8.8.8.8
|
dockerfiles/k8s/systemctl
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
function get_unit_file(){
|
| 4 |
+
|
| 5 |
+
local UNIT=$1
|
| 6 |
+
|
| 7 |
+
for DIR in ${UNIT_PATHS[@]} ; do
|
| 8 |
+
if [ -f "${DIR}${UNIT}" ] ; then
|
| 9 |
+
echo "${DIR}${UNIT}"
|
| 10 |
+
break
|
| 11 |
+
fi
|
| 12 |
+
done
|
| 13 |
+
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
function read_option(){
|
| 17 |
+
local OPTION="$1"
|
| 18 |
+
local UNIT_FILE="$2"
|
| 19 |
+
local UNIT_INSTANCE="$3"
|
| 20 |
+
|
| 21 |
+
local UNIT=`basename $UNIT_FILE`
|
| 22 |
+
local UNIT_FULL=`echo $UNIT | sed "s/@/@$UNIT_INSTANCE/"`
|
| 23 |
+
|
| 24 |
+
VALUE="$(grep '^'$OPTION'[= ]' "$UNIT_FILE" | cut -d '=' -f2- | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
|
| 25 |
+
|
| 26 |
+
VALUE="`
|
| 27 |
+
echo $VALUE |
|
| 28 |
+
sed -e "s/%[i]/$UNIT_INSTANCE/g" \
|
| 29 |
+
-e "s/%[I]/\"$UNIT_INSTANCE\"/g" \
|
| 30 |
+
-e "s/%[n]/$UNIT_FULL/g" \
|
| 31 |
+
-e "s/%[N]/\"$UNIT_FULL\"/g"
|
| 32 |
+
`"
|
| 33 |
+
# TODO: Add more options from:
|
| 34 |
+
# https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Specifiers
|
| 35 |
+
|
| 36 |
+
echo $VALUE
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
function get_unit_wants() {
|
| 40 |
+
|
| 41 |
+
local UNIT_FILE=$1
|
| 42 |
+
local UNIT=`basename $UNIT_FILE`
|
| 43 |
+
|
| 44 |
+
sort -u <<< `(
|
| 45 |
+
# Print wants from UNIT_PATHS
|
| 46 |
+
for DIR in ${UNIT_PATHS[@]} ; do
|
| 47 |
+
if [ -d "${DIR}${UNIT}.wants" ] ; then
|
| 48 |
+
ls -1 "${DIR}${UNIT}.wants/" | tr '\n' ' '
|
| 49 |
+
fi
|
| 50 |
+
done
|
| 51 |
+
|
| 52 |
+
# Print wants from unit-file
|
| 53 |
+
read_option Wants $UNIT_FILE
|
| 54 |
+
)`
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
function action_start(){
|
| 58 |
+
|
| 59 |
+
# Find depended services
|
| 60 |
+
local UNIT_FILE=$1
|
| 61 |
+
local UNIT_WANTS=(`get_unit_wants $1`)
|
| 62 |
+
local UNIT_INSTANCE=$2
|
| 63 |
+
|
| 64 |
+
# Start depended services
|
| 65 |
+
for UNIT in ${UNIT_WANTS[@]}; do
|
| 66 |
+
exec_action start $UNIT
|
| 67 |
+
done
|
| 68 |
+
|
| 69 |
+
# Load options
|
| 70 |
+
local User=`read_option User $UNIT_FILE $UNIT_INSTANCE`
|
| 71 |
+
local Type=`read_option Type $UNIT_FILE $UNIT_INSTANCE`
|
| 72 |
+
local EnvironmentFile=`read_option EnvironmentFile $UNIT_FILE $UNIT_INSTANCE`
|
| 73 |
+
local ExecStartPre=(`read_option ExecStartPre $UNIT_FILE $UNIT_INSTANCE`)
|
| 74 |
+
local ExecStart=`read_option ExecStart $UNIT_FILE $UNIT_INSTANCE`
|
| 75 |
+
local ExecStartPost=(`read_option ExecStartPost $UNIT_FILE $UNIT_INSTANCE`)
|
| 76 |
+
local Restart=(`read_option Restart $UNIT_FILE $UNIT_INSTANCE`)
|
| 77 |
+
local RestartSec=(`read_option RestartSec $UNIT_FILE $UNIT_INSTANCE`)
|
| 78 |
+
RestartSec=${RestartSec:=5}
|
| 79 |
+
|
| 80 |
+
[ -f "$EnvironmentFile" ] && source "$EnvironmentFile"
|
| 81 |
+
|
| 82 |
+
# Start service
|
| 83 |
+
if [ -z $Type ] || [[ "${Type,,}" == *"simple"* ]] ; then
|
| 84 |
+
if [ "$Restart" == "always" ]; then
|
| 85 |
+
COMMAND='nohup bash -c "while true ; do '"$ExecStart"'; sleep $RestartSec; done" &>/dev/null &'
|
| 86 |
+
else
|
| 87 |
+
COMMAND='nohup '"$ExecStart"' >>/dev/null 2>&1 &'
|
| 88 |
+
fi
|
| 89 |
+
elif [[ "${Type,,}" == *"forking"* ]] || [[ "${Type,,}" == *"oneshot"* ]] ; then
|
| 90 |
+
COMMAND="$ExecStart"
|
| 91 |
+
else
|
| 92 |
+
>&2 echo "Unknown service type $Type"
|
| 93 |
+
fi
|
| 94 |
+
|
| 95 |
+
#[ -z $User ] || COMMAND="su $User -c \"$COMMAND\""
|
| 96 |
+
|
| 97 |
+
while IFS=$'\n' read -a i; do
|
| 98 |
+
eval $i
|
| 99 |
+
done <<< "${ExecStartPre[@]}"
|
| 100 |
+
|
| 101 |
+
eval "$COMMAND"
|
| 102 |
+
|
| 103 |
+
while IFS=$'\n' read -a i; do
|
| 104 |
+
eval $i
|
| 105 |
+
done <<< "${ExecStartPost[@]}"
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
function action_stop(){
|
| 109 |
+
|
| 110 |
+
# Find depended services
|
| 111 |
+
local UNIT_FILE=$1
|
| 112 |
+
local UNIT_WANTS=(`get_unit_wants $1`)
|
| 113 |
+
local UNIT_INSTANCE=$2
|
| 114 |
+
|
| 115 |
+
# Load options
|
| 116 |
+
local User=`read_option User $UNIT_FILE $UNIT_INSTANCE`
|
| 117 |
+
local Type=`read_option Type $UNIT_FILE $UNIT_INSTANCE`
|
| 118 |
+
local EnvironmentFile=`read_option EnvironmentFile $UNIT_FILE $UNIT_INSTANCE`
|
| 119 |
+
local ExecStopPre=(`read_option ExecStartPre $UNIT_FILE $UNIT_INSTANCE`)
|
| 120 |
+
local ExecStop=`read_option ExecStop $UNIT_FILE $UNIT_INSTANCE`
|
| 121 |
+
local ExecStopPost=(`read_option ExecStartPost $UNIT_FILE $UNIT_INSTANCE`)
|
| 122 |
+
local ExecStart=`read_option ExecStart $UNIT_FILE $UNIT_INSTANCE`
|
| 123 |
+
|
| 124 |
+
[ -f "$EnvironmentFile" ] && source "$EnvironmentFile"
|
| 125 |
+
|
| 126 |
+
# Stop service
|
| 127 |
+
if [ -z $ExecStop ] ; then
|
| 128 |
+
COMMAND="kill -TERM \$(pgrep -f \"$ExecStart\")"
|
| 129 |
+
else
|
| 130 |
+
COMMAND="$ExecStop"
|
| 131 |
+
fi
|
| 132 |
+
|
| 133 |
+
#[ -z $User ] || COMMAND="su $User -c \"$COMMAND\""
|
| 134 |
+
|
| 135 |
+
while IFS=$'\n' read -a i; do
|
| 136 |
+
eval $i
|
| 137 |
+
done <<< "${ExecStopPre[@]}"
|
| 138 |
+
|
| 139 |
+
eval "$COMMAND"
|
| 140 |
+
|
| 141 |
+
while IFS=$'\n' read -a i; do
|
| 142 |
+
eval $i
|
| 143 |
+
done <<< "${ExecStopPost[@]}"
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
function action_restart(){
|
| 147 |
+
local UNIT_FILE=$1
|
| 148 |
+
local UNIT_INSTANCE=$2
|
| 149 |
+
|
| 150 |
+
action_stop $UNIT_FILE $UNIT_INSTANCE
|
| 151 |
+
action_start $UNIT_FILE $UNIT_INSTANCE
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
function action_enable(){
|
| 156 |
+
|
| 157 |
+
local UNIT_FILE=$1
|
| 158 |
+
local UNIT=`basename $UNIT_FILE`
|
| 159 |
+
local UNIT_INSTANCE=$2
|
| 160 |
+
local UNIT_FULL=`echo $UNIT | sed "s/@/@$UNIT_INSTANCE/"`
|
| 161 |
+
|
| 162 |
+
local WantedBy=`read_option WantedBy $UNIT_FILE`
|
| 163 |
+
|
| 164 |
+
if [ -z $WantedBy ] ; then
|
| 165 |
+
>&2 echo "Unit $UNIT have no WantedBy option."
|
| 166 |
+
exit 1
|
| 167 |
+
fi
|
| 168 |
+
|
| 169 |
+
local WANTEDBY_DIR="/etc/systemd/system/$WantedBy.wants"
|
| 170 |
+
|
| 171 |
+
if [ ! -f "$WANTEDBY_DIR/$UNIT_FULL" ] ; then
|
| 172 |
+
mkdir -p $WANTEDBY_DIR
|
| 173 |
+
echo Created symlink from $WANTEDBY_DIR/$UNIT_FULL to $UNIT_FILE.
|
| 174 |
+
ln -s $WANTEDBY_DIR/$UNIT_FULL $UNIT_FILE
|
| 175 |
+
fi
|
| 176 |
+
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
function action_disable(){
|
| 180 |
+
|
| 181 |
+
local UNIT_FILE=$1
|
| 182 |
+
local UNIT=`basename $UNIT_FILE`
|
| 183 |
+
local UNIT_INSTANCE=$2
|
| 184 |
+
local UNIT_FULL=`echo $UNIT | sed "s/@/@$UNIT_INSTANCE/"`
|
| 185 |
+
|
| 186 |
+
local WantedBy=`read_option WantedBy $UNIT_FILE`
|
| 187 |
+
|
| 188 |
+
if [ -z $WantedBy ] ; then
|
| 189 |
+
>&2 echo "Unit $UNIT have no WantedBy option."
|
| 190 |
+
exit 1
|
| 191 |
+
fi
|
| 192 |
+
|
| 193 |
+
local WANTEDBY_DIR="/etc/systemd/system/$WantedBy.wants"
|
| 194 |
+
|
| 195 |
+
if [ -f "$WANTEDBY_DIR/$UNIT_FULL" ] ; then
|
| 196 |
+
echo Removed $WANTEDBY_DIR/$UNIT_FULL.
|
| 197 |
+
rm -f $WANTEDBY_DIR/$UNIT_FULL.
|
| 198 |
+
rmdir --ignore-fail-on-non-empty $WANTEDBY_DIR
|
| 199 |
+
fi
|
| 200 |
+
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
function action_status(){
|
| 204 |
+
|
| 205 |
+
# Find depended services
|
| 206 |
+
local UNIT_FILE=$1
|
| 207 |
+
local UNIT_WANTS=(`get_unit_wants $1`)
|
| 208 |
+
local UNIT_INSTANCE=$2
|
| 209 |
+
|
| 210 |
+
local ExecStart=`read_option ExecStart $UNIT_FILE $UNIT_INSTANCE`
|
| 211 |
+
|
| 212 |
+
|
| 213 |
+
COMMAND="pgrep -f \"$ExecStart\" &>/dev/null"
|
| 214 |
+
|
| 215 |
+
|
| 216 |
+
if eval "$COMMAND"; then
|
| 217 |
+
exit 0
|
| 218 |
+
fi
|
| 219 |
+
|
| 220 |
+
>&2 echo "Loaded: not-found"
|
| 221 |
+
exit 1
|
| 222 |
+
}
|
| 223 |
+
|
| 224 |
+
function action_is_enabled(){
|
| 225 |
+
exit 0
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
function action_is_active(){
|
| 229 |
+
local UNIT=`basename $1`
|
| 230 |
+
if systemctl status $UNIT ; then
|
| 231 |
+
>&2 echo "active"
|
| 232 |
+
exit 0
|
| 233 |
+
fi
|
| 234 |
+
|
| 235 |
+
exit 1
|
| 236 |
+
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
function exec_action(){
|
| 240 |
+
|
| 241 |
+
local ACTION=$1
|
| 242 |
+
local UNIT=$2
|
| 243 |
+
|
| 244 |
+
[[ $UNIT =~ '.' ]] || UNIT="$UNIT.service"
|
| 245 |
+
|
| 246 |
+
if [[ $UNIT =~ '@' ]] ; then
|
| 247 |
+
local UNIT_INSTANCE=`echo $UNIT | cut -d'@' -f2- | cut -d. -f1`
|
| 248 |
+
local UNIT=`echo $UNIT | sed "s/$UNIT_INSTANCE//"`
|
| 249 |
+
fi
|
| 250 |
+
|
| 251 |
+
UNIT_FILE=`get_unit_file $UNIT`
|
| 252 |
+
|
| 253 |
+
if [ -z $UNIT_FILE ] ; then
|
| 254 |
+
>&2 echo "Failed to $ACTION $UNIT: Unit $UNIT not found."
|
| 255 |
+
exit 1
|
| 256 |
+
else
|
| 257 |
+
case "$ACTION" in
|
| 258 |
+
start ) action_start $UNIT_FILE $UNIT_INSTANCE ;;
|
| 259 |
+
stop ) action_stop $UNIT_FILE $UNIT_INSTANCE ;;
|
| 260 |
+
restart ) action_restart $UNIT_FILE $UNIT_INSTANCE ;;
|
| 261 |
+
enable ) action_enable $UNIT_FILE $UNIT_INSTANCE ;;
|
| 262 |
+
disable ) action_disable $UNIT_FILE $UNIT_INSTANCE ;;
|
| 263 |
+
status ) action_status $UNIT_FILE $UNIT_INSTANCE ;;
|
| 264 |
+
is-enabled ) action_is_enabled $UNIT_FILE $UNIT_INSTANCE ;;
|
| 265 |
+
is-active ) action_is_active $UNIT_FILE $UNIT_INSTANCE ;;
|
| 266 |
+
* ) >&2 echo "Unknown operation $ACTION." ; exit 1 ;;
|
| 267 |
+
esac
|
| 268 |
+
fi
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
ACTION="$1"
|
| 272 |
+
UNITS="${@:2}"
|
| 273 |
+
UNIT_PATHS=(
|
| 274 |
+
/etc/systemd/system/
|
| 275 |
+
/usr/lib/systemd/system/
|
| 276 |
+
)
|
| 277 |
+
|
| 278 |
+
|
| 279 |
+
for UNIT in ${UNITS[@]}; do
|
| 280 |
+
exec_action $ACTION $UNIT
|
| 281 |
+
done
|
dockerfiles/k8s/tokens.csv
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
31ada4fd-adec-460c-809a-9e56ceb75269,pwd,pwd,"system:admin,system:masters"
|
dockerfiles/k8s/wrapkubeadm.sh
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# Copyright 2017 Mirantis
|
| 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 |
+
set -o pipefail
|
| 17 |
+
set -o errtrace
|
| 18 |
+
|
| 19 |
+
apiserver_static_pod="/etc/kubernetes/manifests/kube-apiserver"
|
| 20 |
+
|
| 21 |
+
# jq filters follow.
|
| 22 |
+
|
| 23 |
+
# TODO: think about more secure possibilities
|
| 24 |
+
apiserver_anonymous_auth='.spec.containers[0].command|=map(select(startswith("--token-auth-file")|not))+["--token-auth-file=/etc/pki/tokens.csv"]'
|
| 25 |
+
|
| 26 |
+
# Sets etcd2 as backend
|
| 27 |
+
apiserver_etcd2_backend='.spec.containers[0].command|=map(select(startswith("--storage-backend")|not))+["--storage-backend=etcd2"]'
|
| 28 |
+
|
| 29 |
+
# Make apiserver accept insecure connections on port 8080
|
| 30 |
+
# TODO: don't use insecure port
|
| 31 |
+
#apiserver_insecure_bind_port='.spec.containers[0].command|=map(select(startswith("--insecure-port=")|not))+["--insecure-port=2375"]'
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
# Update kube-proxy CIDR, enable --masquerade-all and disable conntrack (see dind::frob-proxy below)
|
| 35 |
+
function dind::proxy-cidr-and-no-conntrack {
|
| 36 |
+
cluster_cidr="$(ip addr show docker0 | grep -w inet | awk '{ print $2; }')"
|
| 37 |
+
echo ".items[0].spec.template.spec.containers[0].command |= .+ [\"--cluster-cidr=${cluster_cidr}\", \"--masquerade-all\", \"--conntrack-max-per-core=0\"]"
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
# Adds route to defualt eth0 interface so 10.96.x.x can go through
|
| 42 |
+
function dind::add-route {
|
| 43 |
+
ip route add 10.96.0.0/16 dev eth0
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
function dind::join-filters {
|
| 49 |
+
local IFS="|"
|
| 50 |
+
echo "$*"
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
function dind::frob-apiserver {
|
| 54 |
+
local -a filters=("${apiserver_anonymous_auth}")
|
| 55 |
+
|
| 56 |
+
dind::frob-file "${apiserver_static_pod}" "${filters[@]}"
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
function dind::frob-file {
|
| 60 |
+
local path_base="$1"
|
| 61 |
+
shift
|
| 62 |
+
local filter="$(dind::join-filters "$@")"
|
| 63 |
+
local status=0
|
| 64 |
+
if [[ -f ${path_base}.yaml ]]; then
|
| 65 |
+
dind::yq "${filter}" "${path_base}.yaml" || status=$?
|
| 66 |
+
else
|
| 67 |
+
echo "${path_base}.json or ${path_base}.yaml not found" >&2
|
| 68 |
+
return 1
|
| 69 |
+
fi
|
| 70 |
+
if [[ ${status} -ne 0 ]]; then
|
| 71 |
+
echo "Failed to frob ${path_base}.yaml" >&2
|
| 72 |
+
return 1
|
| 73 |
+
fi
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
function dind::yq {
|
| 77 |
+
local filter="$1"
|
| 78 |
+
local path="$2"
|
| 79 |
+
# We need to use a temp file here because if you feed an object to
|
| 80 |
+
# 'kubectl convert' via stdin, you'll get a List object because
|
| 81 |
+
# multiple input objects are implied
|
| 82 |
+
tmp="$(mktemp tmp-XXXXXXXXXX.json)"
|
| 83 |
+
kubectl convert -f "${path}" --local -o json 2>/dev/null |
|
| 84 |
+
jq "${filter}" > "${tmp}"
|
| 85 |
+
kubectl convert -f "${tmp}" --local -o yaml 2>/dev/null >"${path}"
|
| 86 |
+
rm -f "${tmp}"
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
function dind::frob-proxy {
|
| 90 |
+
# Trying to change conntrack settings fails even in priveleged containers,
|
| 91 |
+
# so we need to avoid it. Here's sample error message from kube-proxy:
|
| 92 |
+
# I1010 21:53:00.525940 1 conntrack.go:57] Setting conntrack hashsize to 49152
|
| 93 |
+
# Error: write /sys/module/nf_conntrack/parameters/hashsize: operation not supported
|
| 94 |
+
# write /sys/module/nf_conntrack/parameters/hashsize: operation not supported
|
| 95 |
+
#
|
| 96 |
+
# Recipe by @errordeveloper:
|
| 97 |
+
# https://github.com/kubernetes/kubernetes/pull/34522#issuecomment-253248985
|
| 98 |
+
local force_apply=--force
|
| 99 |
+
if ! kubectl version --short >&/dev/null; then
|
| 100 |
+
# kubectl 1.4 doesn't have version --short and also it doesn't support apply --force
|
| 101 |
+
force_apply=
|
| 102 |
+
fi
|
| 103 |
+
KUBECONFIG=/etc/kubernetes/admin.conf kubectl -n kube-system get ds -l k8s-app=kube-proxy -o json |
|
| 104 |
+
jq "$(dind::join-filters "$(dind::proxy-cidr-and-no-conntrack)")" | KUBECONFIG=/etc/kubernetes/admin.conf kubectl apply ${force_apply} -f -
|
| 105 |
+
|
| 106 |
+
KUBECONFIG=/etc/kubernetes/admin.conf kubectl -n kube-system delete pods --now -l "k8s-app=kube-proxy"
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
function dind::wait-for-apiserver {
|
| 111 |
+
echo -n "Waiting for api server to startup"
|
| 112 |
+
local url="https://localhost:6443/api"
|
| 113 |
+
local n=60
|
| 114 |
+
while true; do
|
| 115 |
+
if curl -k -s "${url}" >&/dev/null; then
|
| 116 |
+
break
|
| 117 |
+
fi
|
| 118 |
+
if ((--n == 0)); then
|
| 119 |
+
echo "Error: timed out waiting for apiserver to become available" >&2
|
| 120 |
+
fi
|
| 121 |
+
echo -n "."
|
| 122 |
+
sleep 0.5
|
| 123 |
+
done
|
| 124 |
+
echo ""
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
function dind::frob-cluster {
|
| 128 |
+
#dind::frob-apiserver
|
| 129 |
+
dind::wait-for-apiserver
|
| 130 |
+
dind::frob-proxy
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
# Weave depends on /etc/machine-id being unique
|
| 134 |
+
if [[ ! -f /etc/machine-id ]]; then
|
| 135 |
+
rm -f /etc/machine-id
|
| 136 |
+
systemd-machine-id-setup
|
| 137 |
+
fi
|
| 138 |
+
|
| 139 |
+
if [[ "$@" == "init"* || "$@" == "join"* ]]; then
|
| 140 |
+
# Call kubeadm with params and skip flag
|
| 141 |
+
/usr/bin/kubeadm "$@" --ignore-preflight-errors all --cri-socket /run/docker/containerd/containerd.sock
|
| 142 |
+
else
|
| 143 |
+
# Call kubeadm with params
|
| 144 |
+
/usr/bin/kubeadm "$@"
|
| 145 |
+
fi
|
| 146 |
+
|
| 147 |
+
# Frob cluster
|
| 148 |
+
if [[ "$@" == "init"* && $? -eq 0 && ! "$@" == *"--help"* ]]; then
|
| 149 |
+
dind::frob-cluster
|
| 150 |
+
else
|
| 151 |
+
dind::add-route
|
| 152 |
+
fi
|
| 153 |
+
|
dockerfiles/pwm/.gitconfig
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[url "https://"]
|
| 2 |
+
insteadOf = git://
|