Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 54b6631fd0 | |||
| 04ad3616c9 | |||
| 7158764d2c | |||
| 1f611efed0 | |||
| 935861a107 | |||
| 926828a2dc | |||
| 9ec3ed0f1c | |||
| e075ff13fa |
@@ -55,7 +55,7 @@ spec:
|
|||||||
containers:
|
containers:
|
||||||
- command:
|
- command:
|
||||||
- /manager
|
- /manager
|
||||||
image: git.acooldomain.co/server-manager/kubernetes-operator:v0.0.8
|
image: git.acooldomain.co/server-manager/kubernetes-operator:v0.0.9
|
||||||
env:
|
env:
|
||||||
- name: CONFIG_PATH
|
- name: CONFIG_PATH
|
||||||
value: /etc/server-manager/config.yaml
|
value: /etc/server-manager/config.yaml
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
apiVersion: server-manager.acooldomain.co/v1alpha1
|
||||||
|
kind: Image
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: kubernetes-operator
|
||||||
|
app.kubernetes.io/managed-by: kustomize
|
||||||
|
name: minecraft-paper-1-21-5
|
||||||
|
spec:
|
||||||
|
location: git.acooldomain.co/server-manager/minecraft:paper-1.21.5
|
||||||
|
name: minecraft
|
||||||
|
tag: paper-1.21.5
|
||||||
|
working_dir: /opt/server
|
||||||
|
ports:
|
||||||
|
- port: 25565
|
||||||
|
protocol: TCP
|
||||||
|
|
||||||
|
init_script:
|
||||||
|
image: alpine:latest
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
args:
|
||||||
|
- /bin/sh
|
||||||
|
- "-c"
|
||||||
|
- "echo eula=true >> /data/eula.txt"
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
type SourceRule struct {
|
||||||
|
FolderPath string `yaml:"folderPath"`
|
||||||
|
Viewable bool `yaml:"viewable"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SourceConfig struct {
|
||||||
|
DefaultEnabled bool `yaml:"defaultEnabled"`
|
||||||
|
Rules []SourceRule `yaml:"rules"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SourceDefinition struct {
|
||||||
|
Path string `yaml:"path"`
|
||||||
|
Config SourceConfig `yaml:"config"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerConfig struct {
|
||||||
|
Port int `yaml:"port"`
|
||||||
|
BaseUrl string `yaml:"baseURL"`
|
||||||
|
Sources []SourceDefinition `yaml:"sources"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserDefaultPermissionConfig struct {
|
||||||
|
Modify bool `yaml:"modify"`
|
||||||
|
Share bool `yaml:"share"`
|
||||||
|
Realtime bool `yaml:"realtime"`
|
||||||
|
Create bool `yaml:"create"`
|
||||||
|
Delete bool `yaml:"delete"`
|
||||||
|
Api bool `yaml:"api"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserDefaultsConfig struct {
|
||||||
|
Permissions UserDefaultPermissionConfig `yaml:"permissions"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthPasswordMethodConfig struct {
|
||||||
|
Enabled bool `yaml:"enabled"`
|
||||||
|
MinLength int `yaml:"minLength"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthProxyMethodConfig struct {
|
||||||
|
Enabled bool `yaml:"enabled"`
|
||||||
|
Header string `yaml:"header"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthMethodsConfig struct {
|
||||||
|
Password AuthPasswordMethodConfig `yaml:"password"`
|
||||||
|
Proxy AuthProxyMethodConfig `yaml:"proxy"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthConfig struct {
|
||||||
|
AdminUsername string `yaml:"adminUsername"`
|
||||||
|
Methods AuthMethodsConfig `yaml:"methods"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FrontendConfig struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileBrowserConfig struct {
|
||||||
|
Server ServerConfig `yaml:"server"`
|
||||||
|
Auth AuthConfig `yaml:"auth"`
|
||||||
|
Frontend FrontendConfig `yaml:"frontend"`
|
||||||
|
UserDefaults UserDefaultsConfig `yaml:"userDefaults"`
|
||||||
|
}
|
||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
traefikv3 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
|
traefikv3 "github.com/traefik/traefik/v3/pkg/provider/kubernetes/crd/traefikio/v1alpha1"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
@@ -297,7 +298,22 @@ func (r *ServerManagerReconciler) Reconcile(ctx context.Context, req ctrl.Reques
|
|||||||
}
|
}
|
||||||
logging.Info("verified server service")
|
logging.Info("verified server service")
|
||||||
|
|
||||||
browserPod := r.BrowserPod(s, pvc, browserPvc)
|
browserConfigMap, err := r.BrowserConfigMap(s)
|
||||||
|
if err != nil {
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
logging.Info("created browser configmap")
|
||||||
|
var foundBrowserConfigMap corev1.ConfigMap
|
||||||
|
|
||||||
|
err = r.Get(ctx, client.ObjectKeyFromObject(browserConfigMap), &foundBrowserConfigMap)
|
||||||
|
if err != nil {
|
||||||
|
logging.Info("Failed getting browser configmap", "err", err)
|
||||||
|
err = r.Create(ctx, browserConfigMap)
|
||||||
|
return ctrl.Result{Requeue: true}, err
|
||||||
|
}
|
||||||
|
logging.Info("verified browser config map")
|
||||||
|
|
||||||
|
browserPod := r.BrowserPod(s, pvc, browserPvc, browserConfigMap)
|
||||||
foundBrowser := &corev1.Pod{}
|
foundBrowser := &corev1.Pod{}
|
||||||
err = r.Get(ctx, client.ObjectKeyFromObject(browserPod), foundBrowser)
|
err = r.Get(ctx, client.ObjectKeyFromObject(browserPod), foundBrowser)
|
||||||
if err == nil && !s.Spec.Browser.On {
|
if err == nil && !s.Spec.Browser.On {
|
||||||
@@ -519,16 +535,72 @@ func (r *ServerManagerReconciler) BrowserService(s *servermanagerv1alpha1.Server
|
|||||||
return service
|
return service
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ServerManagerReconciler) BrowserPod(s *servermanagerv1alpha1.ServerManager, pvc *corev1.PersistentVolumeClaim, browserPvc *corev1.PersistentVolumeClaim) *corev1.Pod {
|
func (r *ServerManagerReconciler) BrowserConfigMap(s *servermanagerv1alpha1.ServerManager) (*corev1.ConfigMap, error) {
|
||||||
ports := make([]corev1.ContainerPort, len(s.Spec.Server.Ports))
|
serializedConfig, err := yaml.Marshal(FileBrowserConfig{
|
||||||
|
Server: ServerConfig{
|
||||||
|
Port: 80,
|
||||||
|
BaseUrl: r.GenerateBrowserSubPath(s),
|
||||||
|
Sources: []SourceDefinition{
|
||||||
|
{
|
||||||
|
Path: "/tmp/data",
|
||||||
|
Config: SourceConfig{
|
||||||
|
DefaultEnabled: true,
|
||||||
|
Rules: []SourceRule{
|
||||||
|
{
|
||||||
|
FolderPath: "lost+found",
|
||||||
|
Viewable: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Auth: AuthConfig{
|
||||||
|
AdminUsername: "admin",
|
||||||
|
Methods: AuthMethodsConfig{
|
||||||
|
Password: AuthPasswordMethodConfig{
|
||||||
|
Enabled: false,
|
||||||
|
},
|
||||||
|
Proxy: AuthProxyMethodConfig{
|
||||||
|
Enabled: true,
|
||||||
|
Header: r.Config.Browser.AuthHeader,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Frontend: FrontendConfig{
|
||||||
|
Name: "ACoolFileBrowser",
|
||||||
|
},
|
||||||
|
UserDefaults: UserDefaultsConfig{
|
||||||
|
Permissions: UserDefaultPermissionConfig{
|
||||||
|
Modify: true,
|
||||||
|
Create: true,
|
||||||
|
Delete: true,
|
||||||
|
Api: true,
|
||||||
|
Share: true,
|
||||||
|
Realtime: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
for i, port := range s.Spec.Server.Ports {
|
if err != nil {
|
||||||
ports[i] = corev1.ContainerPort{
|
return nil, err
|
||||||
ContainerPort: port.Port,
|
|
||||||
Protocol: port.Protocol,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return &corev1.ConfigMap{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: fmt.Sprintf("%s-browser-config", s.Name),
|
||||||
|
Namespace: s.Namespace,
|
||||||
|
Labels: map[string]string{"browser": s.Name},
|
||||||
|
},
|
||||||
|
Data: map[string]string{"config.yaml": string(serializedConfig)},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ServerManagerReconciler) BrowserPod(s *servermanagerv1alpha1.ServerManager, pvc *corev1.PersistentVolumeClaim, browserPvc *corev1.PersistentVolumeClaim, browserConfigMap *corev1.ConfigMap) *corev1.Pod {
|
||||||
|
var fsGroupValue int64 = 2000
|
||||||
|
var runAsUserValue int64 = 1000
|
||||||
|
policy := corev1.FSGroupChangeOnRootMismatch // Optimizes startup speed
|
||||||
|
|
||||||
pod := &corev1.Pod{
|
pod := &corev1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: fmt.Sprintf("%s-browser", s.Name),
|
Name: fmt.Sprintf("%s-browser", s.Name),
|
||||||
@@ -536,6 +608,12 @@ func (r *ServerManagerReconciler) BrowserPod(s *servermanagerv1alpha1.ServerMana
|
|||||||
Labels: map[string]string{"browser": s.Name},
|
Labels: map[string]string{"browser": s.Name},
|
||||||
},
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
|
SecurityContext: &corev1.PodSecurityContext{
|
||||||
|
FSGroup: &fsGroupValue,
|
||||||
|
RunAsUser: &runAsUserValue,
|
||||||
|
RunAsGroup: &fsGroupValue,
|
||||||
|
FSGroupChangePolicy: &policy,
|
||||||
|
},
|
||||||
Volumes: []corev1.Volume{
|
Volumes: []corev1.Volume{
|
||||||
{
|
{
|
||||||
Name: "volume",
|
Name: "volume",
|
||||||
@@ -553,19 +631,12 @@ func (r *ServerManagerReconciler) BrowserPod(s *servermanagerv1alpha1.ServerMana
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
{Name: "config-volume",
|
||||||
InitContainers: []corev1.Container{
|
VolumeSource: corev1.VolumeSource{
|
||||||
{
|
ConfigMap: &corev1.ConfigMapVolumeSource{
|
||||||
Name: "proxy-setter",
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
Image: "filebrowser/filebrowser",
|
Name: browserConfigMap.Name,
|
||||||
ImagePullPolicy: corev1.PullIfNotPresent,
|
},
|
||||||
Ports: ports,
|
|
||||||
Command: []string{"/bin/sh"},
|
|
||||||
Args: []string{"-c", fmt.Sprintf("rm /tmp/database/filebrowser.db; /filebrowser config init -d /tmp/database/filebrowser.db && /filebrowser config set --auth.method=proxy --auth.header=%s -d /tmp/database/filebrowser.db", r.Config.Browser.AuthHeader)},
|
|
||||||
VolumeMounts: []corev1.VolumeMount{
|
|
||||||
{
|
|
||||||
Name: "browser-volume",
|
|
||||||
MountPath: "/tmp/database",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -573,10 +644,9 @@ func (r *ServerManagerReconciler) BrowserPod(s *servermanagerv1alpha1.ServerMana
|
|||||||
Containers: []corev1.Container{
|
Containers: []corev1.Container{
|
||||||
{
|
{
|
||||||
Name: "browser",
|
Name: "browser",
|
||||||
Image: "filebrowser/filebrowser",
|
Image: "ghcr.io/gtsteffaniak/filebrowser",
|
||||||
ImagePullPolicy: corev1.PullIfNotPresent,
|
ImagePullPolicy: corev1.PullIfNotPresent,
|
||||||
Ports: ports,
|
Args: []string{"-c", "/tmp/config/config.yaml"},
|
||||||
Args: []string{"-d", "/tmp/database/filebrowser.db", "-r", "/tmp/data", "-b", r.GenerateBrowserSubPath(s)},
|
|
||||||
VolumeMounts: []corev1.VolumeMount{
|
VolumeMounts: []corev1.VolumeMount{
|
||||||
{
|
{
|
||||||
Name: "volume",
|
Name: "volume",
|
||||||
@@ -586,6 +656,10 @@ func (r *ServerManagerReconciler) BrowserPod(s *servermanagerv1alpha1.ServerMana
|
|||||||
Name: "browser-volume",
|
Name: "browser-volume",
|
||||||
MountPath: "/tmp/database",
|
MountPath: "/tmp/database",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "config-volume",
|
||||||
|
MountPath: "/tmp/config",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -599,7 +673,7 @@ func (r *ServerManagerReconciler) BrowserPod(s *servermanagerv1alpha1.ServerMana
|
|||||||
func (r *ServerManagerReconciler) ServerService(s *servermanagerv1alpha1.ServerManager) *corev1.Service {
|
func (r *ServerManagerReconciler) ServerService(s *servermanagerv1alpha1.ServerManager) *corev1.Service {
|
||||||
ports := make([]corev1.ServicePort, len(s.Spec.Server.Ports))
|
ports := make([]corev1.ServicePort, len(s.Spec.Server.Ports))
|
||||||
for i, port := range s.Spec.Server.Ports {
|
for i, port := range s.Spec.Server.Ports {
|
||||||
ports[i] = corev1.ServicePort{NodePort: 0, Port: port.Port, TargetPort: intstr.FromInt32(port.Port), Name: fmt.Sprintf("%s-%d", strings.ToLower(string(port.Protocol)), port.Port)}
|
ports[i] = corev1.ServicePort{NodePort: 0, Port: port.Port, TargetPort: intstr.FromInt32(port.Port), Name: fmt.Sprintf("%s-%d", strings.ToLower(string(port.Protocol)), port.Port), Protocol: port.Protocol}
|
||||||
}
|
}
|
||||||
service := &corev1.Service{
|
service := &corev1.Service{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
|||||||
Reference in New Issue
Block a user