working with images

This commit is contained in:
ACoolName 2025-04-03 23:46:25 +03:00
parent f464e8966d
commit b021c161ca
7 changed files with 184 additions and 15 deletions

View File

@ -23,11 +23,23 @@ import (
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
type InitScript struct {
Image string `json:"image"`
Command []string `json:"command"`
Args []string `json:"args"`
}
// ImageSpec defines the desired state of Image
type ImageSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
Location string `json:"location"`
Name string `json:"name"`
Location string `json:"location"`
WorkingDir string `json:"working_dir"`
Command []string `json:"command,omitempty"`
Ports []Port `json:"ports"`
Args []string `json:"args,omitempty"`
InitScript *InitScript `json:"init_script,omitempty"`
}
// +kubebuilder:object:root=true

View File

@ -59,7 +59,7 @@ func (in *Image) DeepCopyInto(out *Image) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
in.Spec.DeepCopyInto(&out.Spec)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Image.
@ -115,6 +115,26 @@ func (in *ImageList) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImageSpec) DeepCopyInto(out *ImageSpec) {
*out = *in
if in.Command != nil {
in, out := &in.Command, &out.Command
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Ports != nil {
in, out := &in.Ports, &out.Ports
*out = make([]Port, len(*in))
copy(*out, *in)
}
if in.Args != nil {
in, out := &in.Args, &out.Args
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.InitScript != nil {
in, out := &in.InitScript, &out.InitScript
*out = new(InitScript)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageSpec.
@ -127,6 +147,31 @@ func (in *ImageSpec) DeepCopy() *ImageSpec {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InitScript) DeepCopyInto(out *InitScript) {
*out = *in
if in.Command != nil {
in, out := &in.Command, &out.Command
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Args != nil {
in, out := &in.Args, &out.Args
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InitScript.
func (in *InitScript) DeepCopy() *InitScript {
if in == nil {
return nil
}
out := new(InitScript)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Port) DeepCopyInto(out *Port) {
*out = *in

View File

@ -39,13 +39,57 @@ spec:
spec:
description: ImageSpec defines the desired state of Image
properties:
args:
items:
type: string
type: array
command:
items:
type: string
type: array
init_script:
properties:
args:
items:
type: string
type: array
command:
items:
type: string
type: array
image:
type: string
required:
- args
- command
- image
type: object
location:
type: string
name:
description: |-
INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
Important: Run "make" to regenerate code after modifying this file
type: string
ports:
items:
properties:
port:
format: int32
type: integer
protocol:
description: Protocol defines network protocols supported for
things like container ports.
type: string
type: object
type: array
working_dir:
type: string
required:
- location
- name
- ports
- working_dir
type: object
type: object
served: true

View File

@ -19,6 +19,7 @@ rules:
- pods
verbs:
- create
- delete
- get
- list
- watch

View File

@ -4,6 +4,20 @@ metadata:
labels:
app.kubernetes.io/name: kubernetes-operator
app.kubernetes.io/managed-by: kustomize
name: image-sample
name: minecraft-paper-1-21-4
spec:
# TODO(user): Add fields here
location: git.acooldomain.co/server-manager/minecraft:paper-1.21.4
name: minecraft:paper-1.21.4
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"

View File

@ -11,8 +11,7 @@ spec:
"on": true
server:
"on": true
image: git.acooldomain.co/server-manager/minecraft:paper-1.21.4
working_dir: /opt/server
image: minecraft-paper-1-21-4
ports:
- protocol: TCP
port: 25565

View File

@ -33,6 +33,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
servermanagerv1alpha1 "git.acooldomain.co/server-manager/kubernetes-operator/api/v1alpha1"
)
@ -95,7 +96,7 @@ type ServerManagerReconciler struct {
// +kubebuilder:rbac:groups=,resources=persistentvolumeclaims,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=server-manager.acooldomain.co,resources=servermanagers/finalizers,verbs=update
// +kubebuilder:rbac:groups=,resources=services,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=,resources=pods,verbs=get;list;watch;create
// +kubebuilder:rbac:groups=,resources=pods,verbs=get;list;watch;create;delete
// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
@ -151,7 +152,13 @@ func (r *ServerManagerReconciler) Reconcile(ctx context.Context, req ctrl.Reques
}
logging.Info("verified browserPvc")
serverPod := r.ServerPod(s, pvc)
image, err := r.GetImage(ctx, s)
if err != nil {
logging.Error(err, "Failed to get image")
return reconcile.Result{}, err
}
serverPod := r.ServerPod(s, pvc, image)
found := &corev1.Pod{}
err = r.Get(ctx, client.ObjectKey{Namespace: pvc.Namespace, Name: pvc.Name}, found)
if err == nil && !s.Spec.Server.On {
@ -602,8 +609,13 @@ func (r *ServerManagerReconciler) ServerPvc(s *servermanagerv1alpha1.ServerManag
return pvc
}
func (r *ServerManagerReconciler) ServerPod(s *servermanagerv1alpha1.ServerManager, pvc *corev1.PersistentVolumeClaim) *corev1.Pod {
ports := make([]corev1.ContainerPort, len(s.Spec.Server.Ports))
func (r *ServerManagerReconciler) ServerPod(s *servermanagerv1alpha1.ServerManager, pvc *corev1.PersistentVolumeClaim, image *servermanagerv1alpha1.Image) *corev1.Pod {
serverPorts := image.Spec.Ports
if len(s.Spec.Server.Ports) > 0 {
serverPorts = s.Spec.Server.Ports
}
ports := make([]corev1.ContainerPort, len(serverPorts))
for i, port := range s.Spec.Server.Ports {
ports[i] = corev1.ContainerPort{
@ -612,6 +624,36 @@ func (r *ServerManagerReconciler) ServerPod(s *servermanagerv1alpha1.ServerManag
}
}
command := image.Spec.Command
if len(s.Spec.Server.Command) > 0 {
command = s.Spec.Server.Command
}
args := image.Spec.Args
if len(s.Spec.Server.Args) > 0 {
args = s.Spec.Server.Args
}
var initContainers []corev1.Container = nil
if image.Spec.InitScript != nil {
initContainers = []corev1.Container{
{
Name: "init",
Image: image.Spec.InitScript.Image,
ImagePullPolicy: corev1.PullIfNotPresent,
Command: image.Spec.Command,
Args: image.Spec.InitScript.Args,
VolumeMounts: []corev1.VolumeMount{
{
Name: "volume",
MountPath: "/data",
},
},
},
}
}
pod := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: s.Name,
@ -629,18 +671,19 @@ func (r *ServerManagerReconciler) ServerPod(s *servermanagerv1alpha1.ServerManag
},
},
},
InitContainers: initContainers,
Containers: []corev1.Container{
{
Name: "server",
Image: s.Spec.Server.Image,
Image: image.Spec.Location,
ImagePullPolicy: corev1.PullAlways,
Command: s.Spec.Server.Command,
Args: s.Spec.Server.Args,
WorkingDir: s.Spec.Server.WorkingDir,
Command: command,
Args: args,
WorkingDir: image.Spec.WorkingDir,
Ports: ports,
VolumeMounts: []corev1.VolumeMount{{
Name: "volume",
MountPath: s.Spec.Server.WorkingDir,
MountPath: image.Spec.WorkingDir,
}},
Stdin: true,
TTY: true,
@ -648,10 +691,21 @@ func (r *ServerManagerReconciler) ServerPod(s *servermanagerv1alpha1.ServerManag
},
},
}
controllerutil.SetControllerReference(s, pod, r.Scheme)
return pod
}
func (r *ServerManagerReconciler) GetImage(ctx context.Context, s *servermanagerv1alpha1.ServerManager) (*servermanagerv1alpha1.Image, error) {
image := &servermanagerv1alpha1.Image{}
err := r.Get(ctx, client.ObjectKey{Name: s.Spec.Server.Image, Namespace: s.Namespace}, image)
if err != nil {
return nil, err
}
return image, nil
}
// SetupWithManager sets up the controller with the Manager.
func (r *ServerManagerReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).