1 Commits

Author SHA1 Message Date
admju
4ae5926b01 init bin 2024-09-02 07:09:46 +00:00
114 changed files with 3314 additions and 273 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
bin

View File

@@ -0,0 +1,5 @@
apiVersion: v2
name: oc-catalog
description: A Helm chart for deploying the oc-catalog application
version: 0.1.0
appVersion: "1.0"

View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-oc-catalog
spec:
selector:
app: {{ .Chart.Name }}
ports:
- protocol: TCP
port: {{ .Values.service.port }}
targetPort: {{ .Values.service.targetPort }}
type: {{ .Values.service.type }}

View File

@@ -0,0 +1,33 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ .Release.Name }}-oc-catalog
labels:
app: oc-catalog
spec:
serviceName: "{{ .Release.Name }}-oc-catalog"
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: oc-catalog
template:
metadata:
labels:
app: oc-catalog
spec:
containers:
- name: oc-catalog
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: 8080
env:
- name: MONGO_DATABASE
value: "DC_myDC"
- name: MONGO_URI
value: "mongodb://mongo:27017"
imagePullSecrets:
{{- if .Values.imagePullSecrets }}
{{- range .Values.imagePullSecrets }}
- name: {{ .name }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,19 @@
replicaCount: 1
image:
repository: registry.dev.svc.cluster.local:5000/oc-catalog
tag: latest
pullPolicy: IfNotPresent
service:
type: NodePort
port: 8087
targetPort: 8080
mongo:
database: DC_myDC
uri: mongodb://mongo:27017
imagePullSecrets:
- name: regcred

View File

@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

12
Helm/oc-deploy/Chart.lock Normal file
View File

@@ -0,0 +1,12 @@
dependencies:
- name: oc-mongo
repository: file://../oc-mongo
version: 0.1.0
- name: oc-mongo-express
repository: file://../oc-mongo-express
version: 0.1.0
- name: oc-catalog
repository: file://../oc-catalog
version: 0.1.0
digest: sha256:036af8acf7fe0a73f039776d13f63aeb7530e7a8b0febb49fd5e8415ac6672c6
generated: "2024-08-27T14:34:41.6038407+02:00"

14
Helm/oc-deploy/Chart.yaml Normal file
View File

@@ -0,0 +1,14 @@
apiVersion: v2
name: oc-deploy
description: A Helm chart to deploy oc-mongo, oc-mongo-express, and oc-catalog together
version: 0.1.0
dependencies:
- name: oc-mongo
version: 0.1.0
repository: "file://../oc-mongo"
- name: oc-mongo-express
version: 0.1.0
repository: "file://../oc-mongo-express"
- name: oc-catalog
version: 0.1.0
repository: "file://../oc-catalog"

Binary file not shown.

View File

@@ -0,0 +1,5 @@
apiVersion: v2
name: oc-catalog
description: A Helm chart for deploying the oc-catalog application
version: 0.1.0
appVersion: "1.0"

View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: oc-catalog
spec:
selector:
app: {{ .Chart.Name }}
ports:
- protocol: TCP
port: {{ .Values.service.port }}
targetPort: {{ .Values.service.targetPort }}
type: {{ .Values.service.type }}

View File

@@ -0,0 +1,33 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ .Release.Name }}-oc-catalog
labels:
app: oc-catalog
spec:
serviceName: "oc-catalog"
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: oc-catalog
template:
metadata:
labels:
app: oc-catalog
spec:
containers:
- name: oc-catalog
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: 8080
env:
- name: MONGO_DATABASE
value: "DC_myDC"
- name: MONGO_URI
value: "mongodb://{{ .Release.Name }}-mongo:27017"
imagePullSecrets:
{{- if .Values.imagePullSecrets }}
{{- range .Values.imagePullSecrets }}
- name: {{ .name }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,19 @@
replicaCount: 1
image:
repository: registry.dev.svc.cluster.local:5000/oc-catalog
tag: latest
pullPolicy: IfNotPresent
service:
type: NodePort
port: 8087
targetPort: 8080
mongo:
database: DC_myDC
uri: mongodb://oc-deploy-mongo:27017
imagePullSecrets:
- name: regcred

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,5 @@
apiVersion: v2
name: oc-mongo-express
description: A Helm chart for deploying mongo-express
version: 0.1.0
appVersion: "1.0"

View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: mongo-express
spec:
selector:
app: mongo-express
ports:
- protocol: TCP
port: {{ .Values.service.port }}
targetPort: {{ .Values.service.targetPort }}
type: {{ .Values.service.type }}

View File

@@ -0,0 +1,39 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ .Release.Name }}-mongo-express
labels:
app: mongo-express
spec:
serviceName: "mongo-express"
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: mongo-express
template:
metadata:
labels:
app: mongo-express
spec:
containers:
- name: mongo-express
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: {{ .Values.service.targetPort }}
env:
- name: ME_CONFIG_BASICAUTH_USERNAME
valueFrom:
secretKeyRef:
name: mongo-secret
key: {{ .Values.secret.usernameKey }}
- name: ME_CONFIG_BASICAUTH_PASSWORD
valueFrom:
secretKeyRef:
name: mongo-secret
key: {{ .Values.secret.passwordKey }}
imagePullSecrets:
{{- if .Values.imagePullSecrets }}
{{- range .Values.imagePullSecrets }}
- name: {{ .name }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,18 @@
replicaCount: 1
image:
repository: mongo-express
tag: latest
pullPolicy: IfNotPresent
service:
port: 8081
targetPort: 8081
type: NodePort
imagePullSecrets:
- name: my-registry-key
secret:
usernameKey: mongo-username
passwordKey: mongo-password

View File

@@ -0,0 +1,5 @@
apiVersion: v2
name: oc-mongo
description: A Helm chart for deploying the oc-mongo component
version: 0.1.0
appVersion: "1.0"

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ .Values.persistence.name }}
spec:
accessModes:
- {{ .Values.persistence.accessMode }}
resources:
requests:
storage: {{ .Values.persistence.size }}

View File

@@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ .Release.Name }}-mongo-secret
type: Opaque
data:
username: {{ .Values.secret.username }}
password: {{ .Values.secret.password }}

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: mongo
spec:
selector:
app: mongo
ports:
- protocol: TCP
port: {{ .Values.service.port }}
targetPort: {{ .Values.service.port }}

View File

@@ -0,0 +1,31 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ .Release.Name }}-mongo
labels:
app: mongo
spec:
serviceName: "mongo"
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: mongo
template:
metadata:
labels:
app: mongo
spec:
containers:
- name: mongo
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: 27017
volumeMounts:
- name: mongo-persistent-storage
mountPath: /data/db
- name: mongo-persistent-storage
mountPath: /data/configdb
volumes:
- name: mongo-persistent-storage
persistentVolumeClaim:
claimName: {{ .Values.persistence.name }}

View File

@@ -0,0 +1,19 @@
replicaCount: 1
image:
repository: mongo
tag: latest
pullPolicy: IfNotPresent
service:
port: 27017
persistence:
name: mongo-pvc-helm
enabled: true
accessMode: ReadWriteOnce
size: 1Gi
secret:
username: dGVzdA== # base64 encoding of 'test'
password: dGVzdA== # base64 encoding of 'test'

View File

@@ -0,0 +1,48 @@
oc-mongo:
replicaCount: 1
image:
repository: registry.dev.svc.cluster.local:5000/mongo
tag: latest
pullPolicy: IfNotPresent
service:
port: 27017
persistence:
name: mongo-pvc-helm
enabled: true
accessMode: ReadWriteOnce
size: 1Gi
secret:
username: dGVzdA== # base64 encoding of 'test'
password: dGVzdA== # base64 encoding of 'test'
oc-mongo-express:
replicaCount: 1
image:
repository: registry.dev.svc.cluster.local:5000/mongo-express
tag: latest
pullPolicy: IfNotPresent
service:
port: 8081
targetPort: 8081
type: NodePort
imagePullSecrets:
- name: regcred
secret:
usernameKey: mongo-username
passwordKey: mongo-password
oc-catalog:
replicaCount: 1
image:
repository: registry.dev.svc.cluster.local:5000/oc-catalog
tag: latest
pullPolicy: IfNotPresent
service:
type: NodePort
port: 8087
targetPort: 8080
mongo:
database: DC_myDC
uri: mongodb://oc-catalog-mongo:27017
imagePullSecrets:
- name: regcred

View File

@@ -0,0 +1,5 @@
apiVersion: v2
name: oc-mongo-express
description: A Helm chart for deploying mongo-express
version: 0.1.0
appVersion: "1.0"

View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-mongo-express
spec:
selector:
app: mongo-express
ports:
- protocol: TCP
port: {{ .Values.service.port }}
targetPort: {{ .Values.service.targetPort }}
type: {{ .Values.service.type }}

View File

@@ -0,0 +1,39 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ .Release.Name }}-mongo-express
labels:
app: mongo-express
spec:
serviceName: "{{ .Release.Name }}-mongo-express"
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: mongo-express
template:
metadata:
labels:
app: mongo-express
spec:
containers:
- name: mongo-express
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: {{ .Values.service.targetPort }}
env:
- name: ME_CONFIG_BASICAUTH_USERNAME
valueFrom:
secretKeyRef:
name: mongo-secret
key: {{ .Values.secret.usernameKey }}
- name: ME_CONFIG_BASICAUTH_PASSWORD
valueFrom:
secretKeyRef:
name: mongo-secret
key: {{ .Values.secret.passwordKey }}
imagePullSecrets:
{{- if .Values.imagePullSecrets }}
{{- range .Values.imagePullSecrets }}
- name: {{ .name }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,18 @@
replicaCount: 1
image:
repository: mongo-express
tag: latest
pullPolicy: IfNotPresent
service:
port: 8081
targetPort: 8081
type: NodePort
imagePullSecrets:
- name: my-registry-key
secret:
usernameKey: mongo-username
passwordKey: mongo-password

5
Helm/oc-mongo/Chart.yaml Normal file
View File

@@ -0,0 +1,5 @@
apiVersion: v2
name: oc-mongo
description: A Helm chart for deploying the oc-mongo component
version: 0.1.0
appVersion: "1.0"

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ .Values.persistence.name }}
spec:
accessModes:
- {{ .Values.persistence.accessMode }}
resources:
requests:
storage: {{ .Values.persistence.size }}

View File

@@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ .Release.Name }}-mongo-secret
type: Opaque
data:
username: {{ .Values.secret.username }}
password: {{ .Values.secret.password }}

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: mongo
spec:
selector:
app: mongo
ports:
- protocol: TCP
port: {{ .Values.service.port }}
targetPort: {{ .Values.service.port }}

View File

@@ -0,0 +1,31 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ .Release.Name }}-mongo
labels:
app: mongo
spec:
serviceName: "{{ .Release.Name }}-mongo"
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: mongo
template:
metadata:
labels:
app: mongo
spec:
containers:
- name: mongo
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: 27017
volumeMounts:
- name: mongo-persistent-storage
mountPath: /data/db
- name: mongo-persistent-storage
mountPath: /data/configdb
volumes:
- name: mongo-persistent-storage
persistentVolumeClaim:
claimName: {{ .Values.persistence.name }}

19
Helm/oc-mongo/values.yaml Normal file
View File

@@ -0,0 +1,19 @@
replicaCount: 1
image:
repository: mongo
tag: latest
pullPolicy: IfNotPresent
service:
port: 27017
persistence:
name: mongo-pvc-helm
enabled: true
accessMode: ReadWriteOnce
size: 1Gi
secret:
username: dGVzdA== # base64 encoding of 'test'
password: dGVzdA== # base64 encoding of 'test'

View File

@@ -35,69 +35,5 @@ Install Talos
chmod 700 get_helm.sh chmod 700 get_helm.sh
./get_helm.sh ./get_helm.sh
--------------------------
# Create OpenCloud Chart # Create OpenCloud Chart
helm create occhart
# `oc-deploy` Component
The `oc-deploy` component aims to simplify and automate the deployment of OpenCloud components on a Kubernetes cluster through the creation of Helm Charts.
## Prerequisites:
- Access to the OpenCloud forge and the associated Harbor registry: [https://registry.o-forge.io/](https://registry.o-forge.io/), which will allow pulling OpenCloud release images from the "stable" project.
- To test the connection to this registry from the Docker client:
```bash
docker login registry.o-forge.io
```
- A Kubernetes cluster: Minikube, K3s, RKE2, etc. See `KubernetesCluster`.
- Helm installed locally
## **To Be Defined:**
### Configuring a Docker Secret for Kubernetes
Kubernetes needs to know your credentials to pull images from the "registry.o-forge.io" registry. Create a Docker secret in Kubernetes:
```bash
kubectl create secret docker-registry regcred \
--docker-server=registry.o-forge.io \
--docker-username=<your_username> \
--docker-password=<your_password> \
--docker-email=<your_email>
```
## Checking if Helm Recognizes Your Local Kubernetes Cluster:
### 1. Verify Connection to Kubernetes:
Before checking Helm, ensure that your `kubectl` is properly configured to connect to your local Kubernetes cluster.
Run the following command to see if you can communicate with the cluster:
```bash
kubectl get nodes
```
If this command returns the list of nodes in your cluster, it means `kubectl` is properly connected.
### 2. Verify Helm Configuration:
Now, you can check if Helm can access the cluster by using the following command:
```bash
helm version
```
This command displays the Helm version and the Kubernetes version it is connected to.
## Deploying with Helm:
You can deploy the `oc-deploy` Chart with Helm:
```bash
helm install oc-deploy path/to/your/Helm/oc-deploy
```
## Checking Helm Releases:
You can also list the existing releases to see if Helm is properly connected to the cluster:
```bash
helm list
```
If all these commands execute without errors and give the expected results, your Helm installation is correctly configured to recognize and interact with your local Kubernetes cluster

View File

@@ -1,4 +1,4 @@
@startuml Arch Diagram @startuml
top to bottom direction top to bottom direction

88
docker/docker-compose.yml Normal file
View File

@@ -0,0 +1,88 @@
version: '3.8'
services:
traefik:
image: traefik:latest
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
mongo:
image: mongo:latest
ports:
- "27017:27017"
volumes:
- mongo-data:/data/db
labels:
- "traefik.enable=true"
- "traefik.http.routers.mongo.rule=PathPrefix(`/mongo`)"
- "traefik.http.services.mongo.loadbalancer.server.port=27017"
nats:
image: nats:latest
ports:
- "4222:4222"
labels:
- "traefik.enable=true"
- "traefik.http.routers.nats.rule=PathPrefix(`/nats`)"
- "traefik.http.services.nats.loadbalancer.server.port=4222"
zinc:
image: public.ecr.aws/zinclabs/zincsearch:latest
ports:
- "4080:4080"
labels:
- "traefik.enable=true"
- "traefik.http.routers.zinc.rule=PathPrefix(`/zinc`)"
- "traefik.http.services.zinc.loadbalancer.server.port=4080"
dex:
image: quay.io/dexidp/dex:latest
ports:
- "5556:5556"
volumes:
- ./dex/config.yaml:/etc/dex/cfg/config.yaml
command: ["dex", "serve", "/etc/dex/cfg/config.yaml"]
labels:
- "traefik.enable=true"
- "traefik.http.routers.dex.rule=PathPrefix(`/dex`)"
- "traefik.http.services.dex.loadbalancer.server.port=5556"
ldap:
image: bitnami/openldap
ports:
- "389:389"
environment:
- LDAP_ADMIN_USERNAME=admin
- LDAP_ADMIN_PASSWORD=adminpassword
- LDAP_USERS=user01,user02
- LDAP_PASSWORDS=password1,password2
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
GF_SECURITY_ADMIN_PASSWORD: "admin"
labels:
- "traefik.enable=true"
- "traefik.http.routers.grafana.rule=PathPrefix(`/grafana`)"
- "traefik.http.services.grafana.loadbalancer.server.port=3000"
loki:
image: grafana/loki:latest
ports:
- "3100:3100"
labels:
- "traefik.enable=true"
- "traefik.http.routers.loki.rule=PathPrefix(`/loki`)"
- "traefik.http.services.loki.loadbalancer.server.port=3100"
volumes:
mongo-data:

View File

@@ -1,207 +0,0 @@
@startuml
skinparam componentStyle rectangle
node "Kubernetes Cluster" {
cloud "Service: oc-catalog" as oc_catalog_service {
oc_catalog_service : Type: NodePort
oc_catalog_service : External NodePort: 8087 # Exposed NodePort for external access
oc_catalog_service : Internal TargetPort: 8080
}
' Deployment for oc-catalog managing the pods
node "Deployment: oc-catalog" as oc_catalog_deployment {
oc_catalog_deployment : Replicas: {{ .Values.replicaCount }}
oc_catalog_deployment : Image: registry.dev.svc.cluster.local:5000/oc-catalog:latest
oc_catalog_deployment : PullPolicy: IfNotPresent
oc_catalog_deployment : TargetPort: 8080
node "Pod: oc-catalog-1" as catalog_1 {
component "Container: oc-catalog" as oc_catalog_container1 {
oc_catalog_container1 : Internal Port: 8080
oc_catalog_container1 : MONGO_DATABASE=DC_myDC
oc_catalog_container1 : MONGO_URI=mongodb://mongo:27017
}
}
}
oc_catalog_service --> oc_catalog_deployment : Routes traffic to Deployment
oc_catalog_deployment --> catalog_1 : Manages Pods
' MongoDB service and statefulset
cloud "Service: mongo" as mongo_service {
mongo_service : Type: ClusterIP
mongo_service : Internal Port: 27017
}
catalog_1 --> mongo_service : Connects to MongoDB
cloud "Service: oc-shared" as oc_shared_service {
oc_shared_service : Type: NodePort
oc_shared_service : External NodePort: 8091 # Exposed NodePort for external access
oc_shared_service : Internal TargetPort: 8080
}
' Deployment for oc-shared managing the pods
node "Deployment: oc-shared" as oc_shared_deployment {
oc_shared_deployment : Replicas: {{ .Values.replicaCount }}
oc_shared_deployment : Image: registry.dev.svc.cluster.local:5000/oc-shared:latest
oc_shared_deployment : PullPolicy: IfNotPresent
oc_shared_deployment : TargetPort: 8080
node "Pod: oc-shared-1" as shared_1 {
component "Container: oc-shared" as oc_shared_container1 {
oc_shared_container1 : Internal Port: 8080
oc_shared_container1 : MONGO_DATABASE=DC_myDC
oc_shared_container1 : MONGO_URI=mongodb://mongo:27017
}
}
}
oc_shared_service --> oc_shared_deployment : Routes traffic to Deployment
oc_shared_deployment --> shared_1 : Manages Pods
' MongoDB service and statefulset
cloud "Service: mongo" as mongo_service {
mongo_service : Type: ClusterIP
mongo_service : Internal Port: 27017
}
shared_1 --> mongo_service : Connects to MongoDB
cloud "Service: oc-workflow" as oc_workflow_service {
oc_workflow_service : Type: NodePort
oc_workflow_service : External NodePort: 8088 # Exposed NodePort for external access
oc_workflow_service : Internal TargetPort: 8080
}
' Deployment for oc-workflow managing the pods
node "Deployment: oc-workflow" as oc_workflow_deployment {
oc_workflow_deployment : Replicas: {{ .Values.replicaCount }}
oc_workflow_deployment : Image: registry.dev.svc.cluster.local:5000/oc-workflow:latest
oc_workflow_deployment : PullPolicy: IfNotPresent
oc_workflow_deployment : TargetPort: 8080
node "Pod: oc-workflow-1" as workflow_1 {
component "Container: oc-workflow" as oc_workflow_container1 {
oc_workflow_container1 : Internal Port: 8080
oc_workflow_container1 : MONGO_DATABASE=DC_myDC
oc_workflow_container1 : MONGO_URI=mongodb://mongo:27017
}
}
}
oc_workflow_service --> oc_workflow_deployment : Routes traffic to Deployment
oc_workflow_deployment --> workflow_1 : Manages Pods
' MongoDB service and statefulset
cloud "Service: mongo" as mongo_service {
mongo_service : Type: ClusterIP
mongo_service : Internal Port: 27017
}
workflow_1 --> mongo_service : Connects to MongoDB
cloud "Service: oc-workspace" as oc_workspace_service {
oc_workspace_service : Type: NodePort
oc_workspace_service : External NodePort: 8089 # Exposed NodePort for external access
oc_workspace_service : Internal TargetPort: 8080
}
' Deployment for oc-workspace managing the pods
node "Deployment: oc-workspace" as oc_workspace_deployment {
oc_workspace_deployment : Replicas: {{ .Values.replicaCount }}
oc_workspace_deployment : Image: registry.dev.svc.cluster.local:5000/oc-workspace:latest
oc_workspace_deployment : PullPolicy: IfNotPresent
oc_workspace_deployment : TargetPort: 8080
node "Pod: oc-workspace-1" as workspace_1 {
component "Container: oc-workspace" as oc_workspace_container1 {
oc_workspace_container1 : Internal Port: 8080
oc_workspace_container1 : MONGO_DATABASE=DC_myDC
oc_workspace_container1 : MONGO_URI=mongodb://mongo:27017
}
}
}
oc_workspace_service --> oc_workspace_deployment : Routes traffic to Deployment
oc_workspace_deployment --> workspace_1 : Manages Pods
cloud "Service: oc-scheduler" as oc_scheduler_service {
oc_scheduler_service : Type: NodePort
oc_scheduler_service : External NodePort: 8090 # Exposed NodePort for external access
oc_scheduler_service : Internal TargetPort: 8080
}
' Deployment for oc-scheduler managing the pods
node "Deployment: oc-scheduler" as oc_scheduler_deployment {
oc_scheduler_deployment : Replicas: {{ .Values.replicaCount }}
oc_scheduler_deployment : Image: registry.dev.svc.cluster.local:5000/oc-scheduler:latest
oc_scheduler_deployment : PullPolicy: IfNotPresent
oc_scheduler_deployment : TargetPort: 8080
node "Pod: oc-scheduler-1" as scheduler_1 {
component "Container: oc-scheduler" as oc_scheduler_container1 {
oc_scheduler_container1 : Internal Port: 8080
oc_scheduler_container1 : MONGO_DATABASE=DC_myDC
oc_scheduler_container1 : MONGO_URI=mongodb://mongo:27017
}
}
}
oc_scheduler_service --> oc_scheduler_deployment : Routes traffic to Deployment
oc_scheduler_deployment --> scheduler_1 : Manages Pods
' MongoDB service and statefulset
cloud "Service: mongo" as mongo_service {
mongo_service : Type: ClusterIP
mongo_service : Internal Port: 27017
}
scheduler_1 --> mongo_service : Connects to MongoDB
' MongoDB service and statefulset
cloud "Service: mongo" as mongo_service {
mongo_service : Type: ClusterIP
mongo_service : Internal Port: 27017
}
' MongoDB StatefulSet with PVC and PV
node "StatefulSet: MongoDB" as mongo_statefulset {
component " Pod: MongoDB" as mongo_pod{
component "Container: MongoDB" as mongo_container {
mongo_container : Image: mongo:latest
mongo_container : PullPolicy: IfNotPresent
mongo_container : Exposed Port: 27017
mongo_container : Volume Mount: /data/db
mongo_container : Volume Mount: /data/configdb
mongo_container : Secret: username, password (base64)
}
}
storage "PersistentVolumeClaim: mongo-pvc" as mongo_PVC {
mongo_pvc : Access Mode: ReadWriteOnce
mongo_pvc : Size: 1Gi
mongo_pvc : Storage Class: {{ .Values.persistence.storageClass }}
}
}
storage "PersistentVolume: PV" as mongo_PV {
mongo_pv : Bound to PVC: mongo-pvc
}
mongo_service --> mongo_statefulset : Routes traffic to MongoDB StatefulSet
mongo_pod --> mongo_PVC : Mounted Persistent Volume Claim
mongo_pvc --> mongo_PV : Bound Persistent Volume
workspace_1 --> mongo_service : Connects to MongoDB
}
@enduml

23
kube/occhart/.helmignore Normal file
View File

@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

24
kube/occhart/Chart.yaml Normal file
View File

@@ -0,0 +1,24 @@
apiVersion: v2
name: occhart
description: A Helm chart for Kubernetes
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "1.16.0"

View File

@@ -0,0 +1,32 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: dex
labels:
app: dex
spec:
replicas: 1
selector:
matchLabels:
app: dex
template:
metadata:
labels:
app: dex
spec:
containers:
- name: dex
image: quay.io/dexidp/dex:v2.27.0
ports:
- containerPort: 5556
args:
- serve
- /etc/dex/cfg/config.yaml
volumeMounts:
- mountPath: /etc/dex/cfg
name: config
volumes:
- name: config
configMap:
name: dex-config

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: dex
labels:
app: dex
spec:
ports:
- port: 5556
selector:
app: dex

View File

@@ -0,0 +1,21 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
labels:
app: grafana
spec:
replicas: 1
selector:
matchLabels:
app: grafana
template:
metadata:
labels:
app: grafana
spec:
containers:
- name: grafana
image: grafana/grafana:7.5.0
ports:
- containerPort: 3000

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: grafana
labels:
app: grafana
spec:
ports:
- port: 3000
selector:
app: grafana

View File

@@ -0,0 +1,21 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ldap
labels:
app: ldap
spec:
replicas: 1
selector:
matchLabels:
app: ldap
template:
metadata:
labels:
app: ldap
spec:
containers:
- name: ldap
image: osixia/openldap:1.5.0
ports:
- containerPort: 389

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: ldap
labels:
app: ldap
spec:
ports:
- port: 389
selector:
app: ldap

View File

@@ -0,0 +1,21 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: loki
labels:
app: loki
spec:
replicas: 1
selector:
matchLabels:
app: loki
template:
metadata:
labels:
app: loki
spec:
containers:
- name: loki
image: grafana/loki:2.2.0
ports:
- containerPort: 3100

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: loki
labels:
app: loki
spec:
ports:
- port: 3100
selector:
app: loki

View File

@@ -0,0 +1,21 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongo
labels:
app: mongo
spec:
replicas: 1
selector:
matchLabels:
app: mongo
template:
metadata:
labels:
app: mongo
spec:
containers:
- name: mongo
image: mongo:4.4
ports:
- containerPort: 27017

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: mongo
labels:
app: mongo
spec:
ports:
- port: 27017
selector:
app: mongo

View File

@@ -0,0 +1,21 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: nats
labels:
app: nats
spec:
replicas: 1
selector:
matchLabels:
app: nats
template:
metadata:
labels:
app: nats
spec:
containers:
- name: nats
image: nats:2.1.9
ports:
- containerPort: 4222

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: nats
labels:
app: nats
spec:
ports:
- port: 4222
selector:
app: nats

View File

@@ -0,0 +1,37 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: traefik
labels:
app: traefik
spec:
replicas: 1
selector:
matchLabels:
app: traefik
template:
metadata:
labels:
app: traefik
spec:
containers:
- name: traefik
image: traefik:v2.4
ports:
- name: web
containerPort: 80
- name: admin
containerPort: 8080
args:
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --providers.kubernetescrd
- --api
volumeMounts:
- mountPath: /etc/traefik
name: traefik-config
volumes:
- name: traefik-config
configMap:
name: traefik-config

View File

@@ -0,0 +1,81 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: traefik-ingress
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web
spec:
rules:
- host: <your-domain>
http:
paths:
- path: /front
pathType: Prefix
backend:
service:
name: front-service
port:
number: 80
- path: /back1
pathType: Prefix
backend:
service:
name: back1-service
port:
number: 80
- path: /back2
pathType: Prefix
backend:
service:
name: back2-service
port:
number: 80
- path: /mongo
pathType: Prefix
backend:
service:
name: mongo
port:
number: 27017
- path: /nats
pathType: Prefix
backend:
service:
name: nats
port:
number: 4222
- path: /zinc
pathType: Prefix
backend:
service:
name: zinc
port:
number: 4080
- path: /dex
pathType: Prefix
backend:
service:
name: dex
port:
number: 5556
- path: /ldap
pathType: Prefix
backend:
service:
name: ldap
port:
number: 389
- path: /grafana
pathType: Prefix
backend:
service:
name: grafana
port:
number: 3000
- path: /loki
pathType: Prefix
backend:
service:
name: loki
port:
number: 3100

View File

@@ -0,0 +1,17 @@
apiVersion: v1
kind: Service
metadata:
name: traefik
labels:
app: traefik
spec:
type: LoadBalancer
ports:
- port: 80
name: web
targetPort: 80
- port: 8080
name: admin
targetPort: 8080
selector:
app: traefik

View File

@@ -0,0 +1,21 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: zinc
labels:
app: zinc
spec:
replicas: 1
selector:
matchLabels:
app: zinc
template:
metadata:
labels:
app: zinc
spec:
containers:
- name: zinc
image: public.ecr.aws/zinclabs/zinc:latest
ports:
- containerPort: 4080

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Service
metadata:
name: zinc
labels:
app: zinc
spec:
ports:
- port: 4080
selector:
app: zinc

View File

@@ -0,0 +1,22 @@
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "occhart.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch its status by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "occhart.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "occhart.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "occhart.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
{{- end }}

View File

@@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "occhart.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "occhart.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "occhart.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "occhart.labels" -}}
helm.sh/chart: {{ include "occhart.chart" . }}
{{ include "occhart.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "occhart.selectorLabels" -}}
app.kubernetes.io/name: {{ include "occhart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "occhart.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "occhart.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,68 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "occhart.fullname" . }}
labels:
{{- include "occhart.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "occhart.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "occhart.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "occhart.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
livenessProbe:
{{- toYaml .Values.livenessProbe | nindent 12 }}
readinessProbe:
{{- toYaml .Values.readinessProbe | nindent 12 }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.volumeMounts }}
volumeMounts:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.volumes }}
volumes:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}

View File

@@ -0,0 +1,32 @@
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "occhart.fullname" . }}
labels:
{{- include "occhart.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "occhart.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,61 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "occhart.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
{{- end }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{- include "occhart.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
pathType: {{ .pathType }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- else }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "occhart.fullname" . }}
labels:
{{- include "occhart.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "occhart.selectorLabels" . | nindent 4 }}

View File

@@ -0,0 +1,13 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "occhart.serviceAccountName" . }}
labels:
{{- include "occhart.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
{{- end }}

View File

@@ -0,0 +1,15 @@
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "occhart.fullname" . }}-test-connection"
labels:
{{- include "occhart.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "occhart.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never

107
kube/occhart/values.yaml Normal file
View File

@@ -0,0 +1,107 @@
# Default values for occhart.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: nginx
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
# Automatically mount a ServiceAccount's API credentials?
automount: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
podAnnotations: {}
podLabels: {}
podSecurityContext: {}
# fsGroup: 2000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
service:
type: ClusterIP
port: 80
ingress:
enabled: false
className: ""
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: chart-example.local
paths:
- path: /
pathType: ImplementationSpecific
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80
# Additional volumes on the output Deployment definition.
volumes: []
# - name: foo
# secret:
# secretName: mysecret
# optional: false
# Additional volumeMounts on the output Deployment definition.
volumeMounts: []
# - name: foo
# mountPath: "/etc/foo"
# readOnly: true
nodeSelector: {}
tolerations: []
affinity: {}

View File

@@ -0,0 +1,29 @@
# oc-catalog-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: oc-catalog
labels:
app: oc-catalog
spec:
replicas: 1
selector:
matchLabels:
app: oc-catalog
template:
metadata:
labels:
app: oc-catalog
spec:
containers:
- name: oc-catalog
image: registry.dev.svc.cluster.local:5000/oc-catalog:latest
ports:
- containerPort: 8080
env:
- name: MONGO_DATABASE
value: "DC_myDC"
- name: MONGO_URI
value: "mongodb://mongo:27017"
imagePullSecrets:
- name: regcred

View File

@@ -0,0 +1,13 @@
# oc-catalog-service.yml
apiVersion: v1
kind: Service
metadata:
name: oc-catalog
spec:
selector:
app: oc-catalog
ports:
- protocol: TCP
port: 8087
targetPort: 8080
type: NodePort # Optional, useful for accessing via Minikube IP and NodePort

View File

@@ -0,0 +1,32 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongo-express
spec:
replicas: 1
selector:
matchLabels:
app: mongo-express
template:
metadata:
labels:
app: mongo-express
spec:
containers:
- name: mongo-express
image: mongo-express:latest
ports:
- containerPort: 8081
env:
- name: ME_CONFIG_BASICAUTH_USERNAME
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-username
- name: ME_CONFIG_BASICAUTH_PASSWORD
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-password
imagePullSecrets:
- name: my-registry-key

View File

@@ -0,0 +1,13 @@
# mongo-express-service.yml
apiVersion: v1
kind: Service
metadata:
name: mongo-express
spec:
selector:
app: mongo-express
ports:
- protocol: TCP
port: 8081
targetPort: 8081
type: NodePort # Optional, useful for accessing via Minikube IP and NodePort

View File

@@ -0,0 +1,42 @@
# mongo-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongo
labels:
app: mongo
spec:
replicas: 1
selector:
matchLabels:
app: mongo
template:
metadata:
labels:
app: mongo
spec:
containers:
- name: mongo
image: mongo:latest
ports:
- containerPort: 27017
volumeMounts:
- name: mongo-persistent-storage
mountPath: /data/db
- name: mongo-persistent-storage
mountPath: /data/configdb
volumes:
- name: mongo-persistent-storage
persistentVolumeClaim:
claimName: mongo-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongo-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi

View File

@@ -0,0 +1,9 @@
# mongo-secret.yml
apiVersion: v1
kind: Secret
metadata:
name: mongo-secret
type: Opaque
data:
username: dGVzdA== # base64 encoding of 'test'
password: dGVzdA== # base64 encoding of 'test'

View File

@@ -0,0 +1,12 @@
# mongo-service.yml
apiVersion: v1
kind: Service
metadata:
name: mongo
spec:
selector:
app: mongo
ports:
- protocol: TCP
port: 27017
targetPort: 27017

5
src/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
go.sum
*_
.coverage.*
.*.log
workspace_*

73
src/Makefile Normal file
View File

@@ -0,0 +1,73 @@
BIN_NAME := oc-deploy
BIN_OPTS :=
##################
SOURCES := $(wildcard *.go) $(wildcard */*.go)
BIN_DIR = ../bin/
PLUGINS := $(wildcard ../plugins/*/*.go)
OBJS := ${PLUGINS:.go=.so}
%.so: %.go
go build -buildmode=plugin -o $@ $<
help:
@echo
@echo 'Usage:'
@echo ' make build Génère les exécutables.'
@echo ' make get-deps runs dep ensure, mostly used for ci.'
@echo ' make run BIN_OPTS=... Go run'
@echo ' make run_install BIN_OPTS=... Go run'
@echo ' make run_uninstall BIN_OPTS=... Go run'
@echo ' make exec BIN_OPTS=... exécutable'
@echo ' make exec_install BIN_OPTS=... exécutable'
@echo ' make exec_uninstall BIN_OPTS=... exécutable'
@echo ' make test Test.'
@echo ' make test Test'
@echo ' make clean Clean the directory tree.'
@echo
${BIN_DIR}/${BIN_NAME}: ${SOURCES} $(OBJS)
go build -o ${BIN_DIR}/${BIN_NAME}
build: ${BIN_DIR}/${BIN_NAME}
run: $(OBJS)
@go run main.go ${BIN_OPTS}
run_generate: $(OBJS)
@go run main.go generate ${BIN_OPTS}
run_install: $(OBJS)
@go run main.go install ${BIN_OPTS}
run_uninstall: $(OBJS)
@go run main.go uninstall ${BIN_OPTS}
exec: ${BIN_DIR}/${BIN_NAME} $(OBJS)
@${BIN_DIR}/${BIN_NAME} ${BIN_OPTS}
exec_install: ${BIN_DIR}/${BIN_NAME} $(OBJS)
@${BIN_DIR}/${BIN_NAME} install ${BIN_OPTS}
exec_uninstall: ${BIN_DIR}/${BIN_NAME} $(OBJS)
@${BIN_DIR}/${BIN_NAME} uninstall ${BIN_OPTS}
clean:
@test ! -e ${BIN_DIR}/${BIN_NAME} || rm ${BIN_DIR}/${BIN_NAME}
@test ! -e .coverage.out || rm .coverage.out
@test ! -e .coverage.html || rm .coverage.html
@test ! -e go.sum || rm go.sum
@test ! -e .oc-deploy.log || rm .oc-deploy.log
@rm -rf workspace_*
@go mod tidy
.PHONY: test
test:
@go test ./... -coverprofile=.coverage.out -v
go tool cover -html=.coverage.out -o .coverage.html

75
src/README.md Normal file
View File

@@ -0,0 +1,75 @@
# Helm
[![Build Status](https://github.com/helm/helm/workflows/release/badge.svg)](https://github.com/helm/helm/actions?workflow=release)
[![Go Report Card](https://goreportcard.com/badge/github.com/helm/helm)](https://goreportcard.com/report/github.com/helm/helm)
[![GoDoc](https://img.shields.io/static/v1?label=godoc&message=reference&color=blue)](https://pkg.go.dev/helm.sh/helm/v3)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/3131/badge)](https://bestpractices.coreinfrastructure.org/projects/3131)
Helm is a tool for managing Charts. Charts are packages of pre-configured Kubernetes resources.
Use Helm to:
- Find and use [popular software packaged as Helm Charts](https://artifacthub.io/packages/search?kind=0) to run in Kubernetes
- Share your own applications as Helm Charts
- Create reproducible builds of your Kubernetes applications
- Intelligently manage your Kubernetes manifest files
- Manage releases of Helm packages
## Helm in a Handbasket
Helm is a tool that streamlines installing and managing Kubernetes applications.
Think of it like apt/yum/homebrew for Kubernetes.
- Helm renders your templates and communicates with the Kubernetes API
- Helm runs on your laptop, CI/CD, or wherever you want it to run.
- Charts are Helm packages that contain at least two things:
- A description of the package (`Chart.yaml`)
- One or more templates, which contain Kubernetes manifest files
- Charts can be stored on disk, or fetched from remote chart repositories
(like Debian or RedHat packages)
## Install
Binary downloads of the Helm client can be found on [the Releases page](https://github.com/helm/helm/releases/latest).
Unpack the `helm` binary and add it to your PATH and you are good to go!
If you want to use a package manager:
- [Homebrew](https://brew.sh/) users can use `brew install helm`.
- [Chocolatey](https://chocolatey.org/) users can use `choco install kubernetes-helm`.
- [Scoop](https://scoop.sh/) users can use `scoop install helm`.
- [Snapcraft](https://snapcraft.io/) users can use `snap install helm --classic`
To rapidly get Helm up and running, start with the [Quick Start Guide](https://helm.sh/docs/intro/quickstart/).
See the [installation guide](https://helm.sh/docs/intro/install/) for more options,
including installing pre-releases.
## Docs
Get started with the [Quick Start guide](https://helm.sh/docs/intro/quickstart/) or plunge into the [complete documentation](https://helm.sh/docs)
## Roadmap
The [Helm roadmap uses GitHub milestones](https://github.com/helm/helm/milestones) to track the progress of the project.
## Community, discussion, contribution, and support
You can reach the Helm community and developers via the following channels:
- [Kubernetes Slack](https://kubernetes.slack.com):
- [#helm-users](https://kubernetes.slack.com/messages/helm-users)
- [#helm-dev](https://kubernetes.slack.com/messages/helm-dev)
- [#charts](https://kubernetes.slack.com/messages/charts)
- Mailing List:
- [Helm Mailing List](https://lists.cncf.io/g/cncf-helm)
- Developer Call: Thursdays at 9:30-10:00 Pacific ([meeting details](https://github.com/helm/community/blob/master/communication.md#meetings))
### Contribution
If you're interested in contributing, please refer to the [Contributing Guide](CONTRIBUTING.md) **before submitting a pull request**.
### Code of conduct
Participation in the Helm community is governed by the [Code of Conduct](code-of-conduct.md).

34
src/chart/conf.go Normal file
View File

@@ -0,0 +1,34 @@
package chart
import (
"os"
"gopkg.in/yaml.v2"
)
type ChartData struct {
Name string `yaml:"name"`
Chart string `yaml:"chart"`
Version string `yaml:"version"`
Opts string `yaml:"helm_opts"`
Values string `yaml:"helm_values"`
FileValues string `yaml:"helm_filevalues"`
}
type ChartRepoData struct {
Name string `yaml:"name"`
Repository string `yaml:"repository"`
Charts []ChartData `yaml:"charts"`
}
type chartsRepoData struct {
Charts []ChartRepoData `yaml:"opencloud"`
}
func FromConfigFile(filename string) ([]ChartRepoData) {
yamlFile, _ := os.ReadFile(filename)
var data chartsRepoData
yaml.Unmarshal(yamlFile, &data)
return data.Charts
}

30
src/chart/conf_test.go Normal file
View File

@@ -0,0 +1,30 @@
package chart
// https://pkg.go.dev/github.com/stretchr/testify/assert
import (
"testing"
"path/filepath"
"github.com/stretchr/testify/assert"
)
func TestReadConfChart(t *testing.T){
src := filepath.Join(TEST_SRC_DIR, "oc.yml")
assert.FileExists(t, src, "FromConfigFile error")
data := FromConfigFile(src)
assert.Equal(t, data[0].Name, "bitnami", "FromConfigFile error")
assert.Equal(t, data[0].Repository, "https://charts.bitnami.com/bitnami", "FromConfigFile error")
wordpress := data[0].Charts[0]
assert.Equal(t, wordpress.Name, "wordpress", "FromConfigFile error")
assert.Equal(t, wordpress.Chart, "bitnami/wordpress", "FromConfigFile error")
assert.Equal(t, wordpress.Version, "23.1.0", "FromConfigFile error")
phpmyadmin := data[0].Charts[1]
assert.Equal(t, phpmyadmin.Name, "phpmyadmin", "FromConfigFile error")
assert.Equal(t, phpmyadmin.Chart, "bitnami/phpmyadmin", "FromConfigFile error")
assert.Equal(t, phpmyadmin.Version, "17.0.4", "FromConfigFile error")
}

23
src/chart/main_test.go Normal file
View File

@@ -0,0 +1,23 @@
package chart
import (
"os"
"testing"
"path/filepath"
)
var TEST_DEST_DIR = "../wrk_chart"
var TEST_SRC_DIR = filepath.Join("../../test", "chart")
func TestMain(m *testing.M) {
folderPath := TEST_DEST_DIR
os.RemoveAll(folderPath)
os.MkdirAll(folderPath, os.ModePerm)
// call flag.Parse() here if TestMain uses flags
exitCode := m.Run()
os.RemoveAll(folderPath)
os.Exit(exitCode)
}

71
src/cmd/args.go Normal file
View File

@@ -0,0 +1,71 @@
// Package cmd : Parse les arguments
// Arguments : version ==> version d'OpenCloud
// Argument : projet ==> nom du projet
package cmd
import (
"github.com/spf13/cobra"
log "oc-deploy/log_wrapper"
)
var (
context string
version string
)
func Execute() {
log.Log().Debug().Msg("Execute")
var rootCmd = &cobra.Command{Use: "oc-deploy"}
var cmdInstall = &cobra.Command{
Use: "install",
Short: "deploy",
Long: `deploy Charts`,
Args: cobra.MaximumNArgs(0),
Run: func(cmd *cobra.Command, args []string) {
InstallCmd(context, version)
},
Example: "oc-deploy install --version 1.0 --context ex1",
}
var cmdUninstall = &cobra.Command{
Use: "uninstall",
Short: "undeploy",
Long: `Undeploy`,
Args: cobra.MaximumNArgs(0),
Run: func(cmd *cobra.Command, args []string) {
UninstallCmd(context, version)
},
Example: "oc-deploy uninstall --context ex1",
}
var cmdGenerate = &cobra.Command{
Use: "generate",
Short: "generate",
Long: "Value",
Args: cobra.MaximumNArgs(0),
Run: func(cmd *cobra.Command, args []string) {
GenerateCmd(context, version)
},
Example: "oc-deploy generate --version 1.0 --context ex1",
}
cmdInstall.Flags().StringVarP(&context, "context", "p", "opencloud", "Nom du projet")
cmdInstall.Flags().StringVarP(&version, "version", "v", "latest", "Version")
cmdUninstall.Flags().StringVarP(&context, "context", "p", "opencloud", "Nom du projet")
cmdGenerate.Flags().StringVarP(&context, "context", "p", "opencloud", "Nom du projet")
cmdGenerate.Flags().StringVarP(&version, "version", "v", "latest", "Version")
rootCmd.AddCommand(cmdInstall)
rootCmd.AddCommand(cmdUninstall)
rootCmd.AddCommand(cmdGenerate)
cobra.CheckErr(rootCmd.Execute())
}

27
src/cmd/generateCmd.go Normal file
View File

@@ -0,0 +1,27 @@
package cmd
import (
log "oc-deploy/log_wrapper"
"oc-deploy/versionOc"
"oc-deploy/generate"
)
func GenerateCmd(project string, version string) {
log.Log().Info().Msg("Generate >> ")
version, err := versionOc.Get(version)
if err != nil {
log.Log().Fatal().Msg("OpenCloud >> " + err.Error())
}
log.Log().Info().Msg(" >> Version : " + version)
obj := generate.GenerateClass{Workspace: "workspace_" + project, Version: version}
fic, err := obj.New()
if err != nil {
log.Log().Fatal().Msg(" >> " + err.Error())
}
log.Log().Info().Msg(" >> Value : " + fic)
}

51
src/cmd/installCmd.go Normal file
View File

@@ -0,0 +1,51 @@
package cmd
import (
"fmt"
log "oc-deploy/log_wrapper"
"oc-deploy/versionOc"
"oc-deploy/install"
)
func InstallCmd(context string, version string) {
log.Log().Info().Msg("Install >> ")
log.Log().Info().Msg(" << Contexte : " + context)
version, err := versionOc.Get(version)
log.Log().Info().Msg(" << Version : " + version)
if err != nil {
log.Log().Fatal().Msg(" >> " + err.Error())
}
workspace := fmt.Sprintf("workspace_%s", context)
obj := install.InstallClass{Workspace: workspace, Version: version}
file, err := obj.New()
if err != nil {
log.Log().Fatal().Msg(" >> " + err.Error())
}
log.Log().Info().Msg(" >> Config : " + file )
err = obj.Tools()
if err != nil {
log.Log().Fatal().Msg(" >> " + err.Error())
}
err = obj.ChartRepo()
if err != nil {
log.Log().Fatal().Msg(" >> " + err.Error())
}
err = obj.K8s(context)
if err != nil {
log.Log().Fatal().Msg(" >> " + err.Error())
}
err = obj.Charts()
if err != nil {
log.Log().Fatal().Msg(" >> " + err.Error())
}
}

34
src/cmd/uninstallCmd.go Normal file
View File

@@ -0,0 +1,34 @@
package cmd
import (
// "fmt"
// "strings"
// "github.com/spf13/cobra"
log "oc-deploy/log_wrapper"
"oc-deploy/versionOc"
"oc-deploy/install"
)
func UninstallCmd(context string, version string) {
log.Log().Info().Msg("Install >> ")
log.Log().Info().Msg(" << Contexte : " + context)
version, err := versionOc.Get(version)
log.Log().Info().Msg(" << Version : " + version)
if err != nil {
log.Log().Fatal().Msg(" >> " + err.Error())
}
obj := install.UninstallClass{Workspace: "workspace_" + context, Version: version}
obj.New()
// fic, err := obj.New()
// if err != nil {
// log.Log().Fatal().Msg(" >> " + err.Error())
// }
// log.Log().Info().Msg(" >> Value : " + fic)
}

23
src/generate/generate.go Normal file
View File

@@ -0,0 +1,23 @@
package generate
import (
"fmt"
"oc-deploy/utils"
)
type GenerateClass struct {
Version string
Workspace string
url string
}
func (this GenerateClass) New() (string, error) {
src := fmt.Sprintf("../offline/default_value_%s.yml", this.Version)
dst := fmt.Sprintf("%s/default_value.yml", this.Workspace)
err := utils.CopyFile(src, dst)
if err != nil {
return "", err
}
return src, nil
}

25
src/go.mod Normal file
View File

@@ -0,0 +1,25 @@
module oc-deploy
go 1.22.0
require (
github.com/jarcoal/httpmock v1.3.1
github.com/rs/zerolog v1.33.0
github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.9.0
gopkg.in/yaml.v2 v2.4.0
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/sys v0.22.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

121
src/helm/chart.go Normal file
View File

@@ -0,0 +1,121 @@
package helm
import (
"fmt"
"os"
"os/exec"
"strings"
"errors"
"path/filepath"
"encoding/json"
log "oc-deploy/log_wrapper"
)
type HelmChart struct {
Bin string
Name string
Chart string
Version string
Workspace string
Opts string
Values string
FileValues string
}
type installInfoOutput struct {
Description string `json:"description"`
Notes string `json:"notes"`
Status string `json:"status"`
}
type installOutput struct {
Info installInfoOutput `json:"info"`
}
func (this HelmChart) Install() (string, error) {
bin := this.Bin
existe, err := this.exists()
if err != nil {
return "", err
}
if existe {
return "Existe déjà", nil
}
msg := fmt.Sprintf("%s install %s %s %s --output json", bin, this.Name, this.Chart, this.Opts)
if this.Version != "" {
msg = fmt.Sprintf("%s --version %s", msg, this.Version)
}
if this.FileValues != "" {
fic := filepath.Join(this.Workspace, this.FileValues)
if _, err := os.Stat(fic); err != nil {
log.Log().Warn().Msg(fic)
} else {
msg = fmt.Sprintf("%s --values %s", msg, fic)
}
}
msg = strings.Replace(msg, " ", " ", -1)
log.Log().Debug().Msg(msg)
cmd_args := strings.Split(msg, " ")
cmd := exec.Command(cmd_args[0], cmd_args[1:]...)
stdout, err := cmd.CombinedOutput()
if err != nil {
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
return "", errors.New(res)
}
var objmap installOutput
json.Unmarshal(stdout, &objmap)
res := objmap.Info.Status
return res, nil
}
func (this HelmChart) Uninstall() (string, error) {
bin := this.Bin
log.Log().Info().Msg(" >> Chart : " + this.Name)
msg := fmt.Sprintf("%s uninstall %s", bin, this.Name)
log.Log().Debug().Msg(msg)
cmd := exec.Command(bin, "uninstall", this.Name)
stdout, err := cmd.CombinedOutput()
return string(stdout), err
}
// ../bin/helm list --filter phpmyadminm --short
func (this HelmChart) exists() (bool, error) {
bin := this.Bin
msg := fmt.Sprintf("%s list --filter %s --no-headers", bin, this.Name)
log.Log().Debug().Msg(msg)
cmd_args := strings.Split(msg, " ")
cmd := exec.Command(cmd_args[0], cmd_args[1:]...)
stdout, err := cmd.CombinedOutput()
if err != nil {
return false, errors.New(string(stdout))
}
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
log.Log().Debug().Msg(string(stdout))
return res != "", nil
}

24
src/helm/main_test.go Normal file
View File

@@ -0,0 +1,24 @@
package helm
import (
"os"
"testing"
"path/filepath"
)
var TEST_DEST_DIR = "../wrk_helm"
var TEST_SRC_DIR = filepath.Join("../../test", "helm")
var TEST_BIN_DIR = filepath.Join("../../test", "bin")
func TestMain(m *testing.M) {
folderPath := TEST_DEST_DIR
os.RemoveAll(folderPath)
os.MkdirAll(folderPath, os.ModePerm)
// call flag.Parse() here if TestMain uses flags
exitCode := m.Run()
os.RemoveAll(folderPath)
os.Exit(exitCode)
}

53
src/helm/repo.go Normal file
View File

@@ -0,0 +1,53 @@
package helm
import (
"fmt"
"strings"
"os/exec"
log "oc-deploy/log_wrapper"
)
type HelmRepo struct {
Bin string // Chemin vers le binaire
Name string
Repository string // Url du dépôt
ForceUpdate bool
Opts string
}
func (this HelmRepo) AddRepository() (string, error) {
helm_bin := this.Bin
force_update := "--force-update=false"
if this.ForceUpdate {
force_update = "--force-update=true"
}
msg := fmt.Sprintf("%s repo add %s %s %s %s", helm_bin, this.Name, this.Repository, force_update, this.Opts)
log.Log().Debug().Msg(msg)
cmd := exec.Command(helm_bin, "repo", "add", this.Name, this.Repository, force_update)
stdout, err := cmd.CombinedOutput()
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
return res, err
}
// helm repo remove [NAME]
func (this HelmRepo) RemoveRepository() (string, error) {
helm_bin := this.Bin
msg := fmt.Sprintf("%s repo remove %s", helm_bin, this.Name)
log.Log().Debug().Msg(msg)
cmd := exec.Command(helm_bin, "repo", "remove", this.Name)
stdout, err := cmd.CombinedOutput()
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
return res, err
}

23
src/helm/repo_test.go Normal file
View File

@@ -0,0 +1,23 @@
package helm
import (
// "os"
// "path/filepath"
"testing"
// "github.com/stretchr/testify/assert"
)
func TestHelmRepoAdd(t *testing.T){
// fmt.Println(" TestVersion ", TEST_BIN_DIR)
// bin := filepath.Join(TEST_BIN_DIR, "helm")
// os.Chmod(bin, 0700)
// assert.FileExists(t, bin, "TestHelmVersion error")
// version, err := Version(bin)
// assert.Nilf(t, err, "error message %s", bin)
// assert.Equal(t, version, "v3.15.4+gfa9efb0", "TestHelmVersion error")
}

20
src/helm/version.go Normal file
View File

@@ -0,0 +1,20 @@
package helm
import (
"strings"
"os/exec"
)
func Version(path string) (string, error) {
cmd := exec.Command(path, "version", "--short")
stdout, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
return res, nil
}

22
src/helm/version_test.go Normal file
View File

@@ -0,0 +1,22 @@
package helm
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
func TestHelmVersion(t *testing.T){
bin := filepath.Join(TEST_BIN_DIR, "helm")
os.Chmod(bin, 0700)
assert.FileExists(t, bin, "TestHelmVersion error")
version, err := Version(bin)
assert.Nilf(t, err, "error message %s", bin)
assert.Equal(t, version, "v3.15.4+gfa9efb0", "TestHelmVersion error")
}

200
src/install/install.go Normal file
View File

@@ -0,0 +1,200 @@
package install
import (
"fmt"
"errors"
"sync"
// "time"
log "oc-deploy/log_wrapper"
"oc-deploy/utils"
"oc-deploy/tool"
"oc-deploy/helm"
"oc-deploy/chart"
"oc-deploy/kubectl"
)
type InstallClass struct {
Version string
Workspace string
versionFile string
tools []tool.ToolData
toolsBin map[string]string
charts []chart.ChartRepoData
}
func (this *InstallClass) New() (string, error) {
// Extraction du fichier de version
log.Log().Debug().Msg("Téléchargement du fichier de version")
src := fmt.Sprintf("../offline/oc_%s.yml", this.Version)
dst := fmt.Sprintf("%s/oc.yml", this.Workspace)
err := utils.CopyFile(src, dst)
if err != nil {
return "", err
}
// Lecture du fichier de conf
this.versionFile = dst
this.tools = tool.FromConfigFile(this.versionFile)
this.charts = chart.FromConfigFile(this.versionFile)
return dst, nil
}
func (this *InstallClass) Tools() (error) {
var mem []tool.ToolClass
for _, v := range this.tools {
tool2 := tool.ToolClass{}
v.Bin = this.Workspace
err := tool2.New(v)
if err != nil {
return err
}
mem = append(mem,tool2)
}
this.toolsBin = make(map[string]string)
for _, p := range mem {
data := p.Obj.Get()
log.Log().Info().Msg(fmt.Sprintf(" >> Outils : %s", data.Name))
err := p.Locate()
if err != nil {
log.Log().Info().Msg(fmt.Sprintf(" << %s ", err))
return err
}
log.Log().Info().Msg(fmt.Sprintf(" << %s ", p.Path))
version, err1 := p.Version()
if err1 != nil {
log.Log().Info().Msg(fmt.Sprintf(" << %s ", err1))
return err1
}
log.Log().Info().Msg(fmt.Sprintf(" << %s ", version))
this.toolsBin[data.Name] = p.Path
}
return nil
}
func (this *InstallClass) getToolBin(name string) (string, error) {
for key, value := range this.toolsBin {
if key == name {
return value, nil
}
}
return "", errors.New("Error")
}
func (this *InstallClass) ChartRepo() (error) {
bin_path, _ := this.getToolBin("helm")
for _, v := range this.charts {
log.Log().Info().Msg(fmt.Sprintf(" >> Helm Repo : %s", v.Name))
repo := helm.HelmRepo{Bin: bin_path,
Name: v.Name,
Repository: v.Repository,
ForceUpdate: true}
res, err := repo.AddRepository()
if err != nil {
log.Log().Info().Msg(fmt.Sprintf(" << %s ", err))
return err
}
log.Log().Info().Msg(fmt.Sprintf(" << %s ", res))
}
return nil
}
func (this *InstallClass) K8s(context string) (error) {
bin_path, _ := this.getToolBin("kubectl")
kube := kubectl.KubeContext{Bin: bin_path}
err := kube.UseContext(context)
if err != nil {
log.Log().Info().Msg(fmt.Sprintf(" << Kube : %s ", err))
return err
}
currentcontext, namespace, server, err := kube.GetContext()
if err != nil {
log.Log().Info().Msg(fmt.Sprintf(" << Kube : %s ", err))
return err
}
log.Log().Info().Msg(fmt.Sprintf(" << Kube : %s ", currentcontext))
log.Log().Info().Msg(fmt.Sprintf(" << : %s ", namespace))
log.Log().Info().Msg(fmt.Sprintf(" << : %s ", server))
err = kube.Check()
if err != nil {
log.Log().Info().Msg(fmt.Sprintf(" << : %s ", err))
return err
}
log.Log().Info().Msg(fmt.Sprintf(" << : %s ", "OK"))
return nil
}
func (this *InstallClass) Charts() (error) {
helm_bin, _ := this.getToolBin("helm")
kubectl_bin, _ := this.getToolBin("kubectl")
var wg sync.WaitGroup
for _, v := range this.charts {
for _, v1 := range v.Charts {
wg.Add(1)
go func() {
defer wg.Done()
this.worker(helm_bin, kubectl_bin, v1)
} ()
}
}
wg.Wait()
return nil
}
func (this *InstallClass) worker(helm_bin string, kubectl_bin string, chart chart.ChartData) {
log.Log().Info().Msg(fmt.Sprintf(" << Chart : %s ", chart.Name))
helmchart := helm.HelmChart{Bin: helm_bin,
Name: chart.Name,
Chart: chart.Chart,
Version: chart.Version,
Workspace: this.Workspace,
Opts: chart.Opts,
Values: chart.Values,
FileValues: chart.FileValues}
obj := kubectl.KubeObject{Bin: kubectl_bin,
Name: chart.Name}
res, err := helmchart.Install()
if err != nil {
log.Log().Error().Msg(fmt.Sprintf(" >> %s %s (%s)", helmchart.Name, "KO", err))
return
}
log.Log().Info().Msg(fmt.Sprintf(" >> %s (%s)", helmchart.Name, res))
err = obj.Wait()
if err != nil {
log.Log().Error().Msg(fmt.Sprintf(" >> %s %s (%s)", chart.Name, "KO", err))
} else {
log.Log().Info().Msg(fmt.Sprintf(" >> %s %s", chart.Name, "OK"))
}
}

18
src/install/uninstall.go Normal file
View File

@@ -0,0 +1,18 @@
package install
import (
// "fmt"
// "os"
// "io"
// "path/filepath"
// log "oc-deploy/log_wrapper"
)
type UninstallClass struct {
Version string
Workspace string
}
func (this UninstallClass) New() {
}

108
src/kubectl/context.go Normal file
View File

@@ -0,0 +1,108 @@
package kubectl
import (
// "fmt"
"strings"
"errors"
"os/exec"
"encoding/json"
log "oc-deploy/log_wrapper"
)
type KubeContext struct {
Bin string // Chemin vers le binaire
}
type kubeConfig struct {
CurrentContext string `json:"current-context"`
Contexts [] kubeConfigContexts `json:"contexts"`
Clusters [] kubeConfigClusters `json:"clusters"`
}
type kubeConfigContexts struct {
Name string `json:"name"`
Context kubeConfigContext `json:"context"`
}
type kubeConfigContext struct {
Cluster string `json:"cluster"`
User string `json:"user"`
Namespace string `json:"namespace"`
}
type kubeConfigCluster struct {
Server string `json:"server"`
}
type kubeConfigClusters struct {
Name string `json:"name"`
Cluster kubeConfigCluster `json:"cluster"`
}
func (this KubeContext) GetCurrentContext() (string, error) {
cmd := exec.Command(this.Bin, "config", "current-context")
stdout, err := cmd.CombinedOutput()
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
return res, err
}
// Current Context
// namespace, server
func (this KubeContext) GetContext() (string, string, string, error) {
cmd := exec.Command(this.Bin, "config", "view", "-o", "json")
stdout, _ := cmd.CombinedOutput()
var objmap kubeConfig
json.Unmarshal(stdout, &objmap)
currentContext := objmap.CurrentContext
currentCluster := ""
currentNamespace := ""
for _, v := range objmap.Contexts {
if v.Name == currentContext {
currentNamespace = v.Context.Namespace
currentCluster = v.Context.Cluster
}
}
currentServer := ""
for _, v := range objmap.Clusters {
if v.Name == currentCluster {
currentServer = v.Cluster.Server
}
}
return currentContext, currentNamespace, currentServer, nil
}
func (this KubeContext) UseContext(newContext string) (error) {
cmd := exec.Command(this.Bin, "config", "use-context", newContext)
stdout, err := cmd.CombinedOutput()
if err != nil {
log.Log().Debug().Msg(string(stdout))
return errors.New(string(stdout))
}
return nil
}
func (this KubeContext) Check() (error) {
cmd := exec.Command(this.Bin, "cluster-info")
stdout, err := cmd.CombinedOutput()
if err != nil {
log.Log().Debug().Msg(string(stdout))
return errors.New("Kube non disponible")
}
return nil
}

82
src/kubectl/object.go Normal file
View File

@@ -0,0 +1,82 @@
package kubectl
import (
"fmt"
"strings"
"errors"
"time"
"os/exec"
"encoding/json"
log "oc-deploy/log_wrapper"
)
type KubeObject struct {
Bin string // Chemin vers le binaire
Name string
}
type getOutput struct {
Kind string `json:"kind"`
Status getStatusOutput `json:"status"`
}
type getStatusOutput struct {
Replicas int `json:"replicas"`
UnavailableReplicas int `json:"unavailableReplicas"`
}
func (this KubeObject) Get() (map[string]any, error) {
bin := this.Bin
name := this.Name
msg := fmt.Sprintf("%s get deployment %s -o json", bin, name)
log.Log().Debug().Msg(msg)
m := make(map[string]any)
cmd_args := strings.Split(msg, " ")
cmd := exec.Command(cmd_args[0], cmd_args[1:]...)
stdout, err := cmd.CombinedOutput()
if err != nil {
return m, errors.New(string(stdout))
}
var objmap getOutput
json.Unmarshal(stdout, &objmap)
kind := objmap.Kind
status := objmap.Status
m["name"] = name
m["kind"] = kind
m["replicas"] = status.Replicas
m["UnavailableReplicas"] = status.UnavailableReplicas
return m, nil
}
func (this KubeObject) Wait() (error) {
boucle := 10
sleep := 10000 * time.Millisecond
for _ = range boucle {
log.Log().Debug().Msg(fmt.Sprintf("Check Deployement %s", this.Name))
m, err := this.Get()
if err != nil {
return err
}
ko := m["UnavailableReplicas"].(int)
if ko == 0 {
return nil
}
time.Sleep(sleep)
}
return errors.New("Temps d'attente dépassé")
}

31
src/kubectl/version.go Normal file
View File

@@ -0,0 +1,31 @@
package kubectl
import (
"os/exec"
"encoding/json"
)
type toolClientVersion struct {
GitVersion string `json:"gitVersion"`
}
type toolVersion struct {
ClientVersion toolClientVersion `json:"clientVersion"`
}
func Version(path string) (string, error) {
cmd := exec.Command(path, "version", "-o", "json", "--client=true")
stdout, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
var objmap toolVersion
json.Unmarshal(stdout, &objmap)
res := objmap.ClientVersion.GitVersion
return res, nil
}

View File

@@ -0,0 +1,48 @@
package log_wrapper
// https://github.com/rs/zerolog/issues/150
import (
"os"
"github.com/rs/zerolog"
)
var mainLogVar zerolog.Logger
type FilteredWriter struct {
w zerolog.LevelWriter
level zerolog.Level
}
func (w *FilteredWriter) Write(p []byte) (n int, err error) {
return w.w.Write(p)
}
func (w *FilteredWriter) WriteLevel(level zerolog.Level, p []byte) (n int, err error) {
if level == w.level {
return w.w.WriteLevel(level, p)
}
return len(p), nil
}
func Log() *zerolog.Logger {
return &mainLogVar
}
func InitLog(serverName string) bool {
fAll, _ := os.OpenFile("./" + serverName + ".log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
output := zerolog.ConsoleWriter{Out: os.Stdout}
writerInfo := zerolog.MultiLevelWriter(output)
writerError := zerolog.MultiLevelWriter(output)
writerFatal := zerolog.MultiLevelWriter(output)
filteredWriteInfo := &FilteredWriter{writerInfo, zerolog.InfoLevel}
filteredWriterError := &FilteredWriter{writerError, zerolog.ErrorLevel}
filteredWriterFatal := &FilteredWriter{writerFatal, zerolog.FatalLevel}
w := zerolog.MultiLevelWriter(fAll, filteredWriteInfo, filteredWriterError, filteredWriterFatal)
mainLogVar = zerolog.New(w).With().Timestamp().Logger()
return true
}

19
src/main.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import (
"oc-deploy/cmd"
log "oc-deploy/log_wrapper"
)
func main() {
log.InitLog(".oc-deploy")
log.Log().Debug().Msg("Start")
log.Log().Info().Msg("oc-deploy :")
cmd.Execute()
log.Log().Debug().Msg("End")
}

Some files were not shown because too many files have changed in this diff Show More