Skip to content
Commits on Source (3)
...@@ -27,7 +27,8 @@ run: generate fmt vet manifests ...@@ -27,7 +27,8 @@ run: generate fmt vet manifests
# Install CRDs into a cluster # Install CRDs into a cluster
install: manifests install: manifests
kustomize build config/crd | kubectl apply -f - # kustomize build config/crd | kubectl apply -f -
(kustomize build config/crd | kubectl replace -f -) || (kustomize build config/crd | kubectl create -f -)
# Uninstall CRDs from a cluster # Uninstall CRDs from a cluster
uninstall: manifests uninstall: manifests
......
...@@ -3,5 +3,5 @@ repo: git.indie.host/nextcloud-operator ...@@ -3,5 +3,5 @@ repo: git.indie.host/nextcloud-operator
resources: resources:
- group: apps - group: apps
kind: Nextcloud kind: Nextcloud
version: v1beta1 version: v1alpha1
version: "2" version: "2"
...@@ -13,43 +13,43 @@ See the License for the specific language governing permissions and ...@@ -13,43 +13,43 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package application package v1alpha1
import ( import (
"github.com/presslabs/controller-util/syncer" corev1 "k8s.io/api/core/v1"
"github.com/presslabs/controller-util/rand"
interfaces "git.indie.host/nextcloud-operator/interfaces"
) )
var ( func (app *App) SetDefaults() {
generatedSalts = map[string]int{ if &app.Backend.Port == nil || app.Backend.Port.Port == 0 {
"instanceID": 10, app.Backend.Port.Port = 9000
"adminPassword": 12,
"passwordSalt": 20,
"secret": 20,
} }
)
func (c *Component) NewSecretSyncer(r interfaces.Reconcile) syncer.Interface { if len(app.Backend.Port.Protocol) == 0 {
return syncer.NewObjectSyncer("Secret", c.Owner, &c.Secret, r.GetClient(), r.GetScheme(), c.MutateSecret) app.Backend.Port.Protocol = "TCP"
} }
if len(app.Backend.Port.Name) == 0 {
app.Backend.Port.Name = "api"
}
func (c *Component) MutateSecret() error { if len(app.Backend.Paths) == 0 {
if len(c.Secret.Data) == 0 { app.Backend.Paths = []string{"/"}
c.Secret.Data = make(map[string][]byte)
} }
for name, size := range generatedSalts { if app.SecurityContext == nil {
if len(c.Secret.Data[name]) == 0 { app.SecurityContext = &corev1.PodSecurityContext{
random, err := rand.AlphaNumericString(size) RunAsUser: &wwwDataUserID,
if err != nil { RunAsGroup: &wwwDataUserID,
return err FSGroup: &wwwDataUserID,
}
c.Secret.Data[name] = []byte(random)
} }
} }
return nil if len(app.Image) == 0 {
app.Image = "libresh/nextcloud:18.0.0"
}
if len(app.Settings) == 0 {
app.Settings = []string{"app"}
}
app.InternalWorkload.SetDefaults()
} }
...@@ -13,24 +13,33 @@ See the License for the specific language governing permissions and ...@@ -13,24 +13,33 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package web package v1alpha1
import ( import (
"github.com/presslabs/controller-util/syncer" corev1 "k8s.io/api/core/v1"
interfaces "git.indie.host/nextcloud-operator/interfaces"
) )
func (c *Component) NewServiceSyncer(r interfaces.Reconcile) syncer.Interface { func (app *CLI) SetDefaults() {
return syncer.NewObjectSyncer("Service", c.Owner, &c.Service, r.GetClient(), r.GetScheme(), c.MutateService)
} if app.SecurityContext == nil {
app.SecurityContext = &corev1.PodSecurityContext{
RunAsUser: &wwwDataUserID,
RunAsGroup: &wwwDataUserID,
FSGroup: &wwwDataUserID,
}
}
if len(app.Image) == 0 {
app.Image = "libresh/nextcloud:18.0.0"
}
func (c *Component) MutateService() error { if len(app.RestartPolicy) == 0 {
labels := c.Labels("web") app.RestartPolicy = corev1.RestartPolicyOnFailure
}
c.Runtime.MutateService(&c.Service) app.ObjectMeta.SetComponent("cli")
c.Service.Spec.Selector = labels // TODO TOFIX
// meta.SetObjectMeta(app, app.ObjectMeta)
return nil
} }
...@@ -13,28 +13,33 @@ See the License for the specific language governing permissions and ...@@ -13,28 +13,33 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package application package v1alpha1
import ( func (app *Web) SetDefaults() {
"github.com/presslabs/controller-util/syncer"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" app.ObjectMeta.SetComponent("web")
interfaces "git.indie.host/nextcloud-operator/interfaces" if len(app.Backend.Paths) == 0 {
) app.Backend.Paths = []string{"/"}
}
func (c *Component) NewDeploymentSyncer(r interfaces.Reconcile) syncer.Interface { if &app.Backend.Port == nil || app.Backend.Port.Port == 0 {
return syncer.NewObjectSyncer("Deployment", c.Owner, &c.Deployment, r.GetClient(), r.GetScheme(), c.MutateDeployment) app.Backend.Port.Port = 80
} }
if len(app.Port.Protocol) == 0 {
func (c *Component) MutateDeployment() error { app.Backend.Port.Protocol = "TCP"
c.Settings.MutateDeployment(&c.Deployment) }
c.Runtime.MutateDeployment(&c.Deployment) if len(app.Backend.Port.Name) == 0 {
app.Backend.Port.Name = "http"
}
labels := c.Labels("app") if len(app.Image) == 0 {
app.Image = "libresh/nextcloud:18.0.0"
}
c.Deployment.Spec.Template.ObjectMeta = c.Deployment.ObjectMeta if len(app.Settings) == 0 {
c.Deployment.Spec.Selector = metav1.SetAsLabelSelector(labels) app.Settings = []string{"web"}
}
return nil app.Workload.SetDefaults()
} }
...@@ -13,10 +13,10 @@ See the License for the specific language governing permissions and ...@@ -13,10 +13,10 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
// Package v1beta1 contains API Schema definitions for the apps v1beta1 API group // Package v1alpha1 contains API Schema definitions for the apps v1alpha1 API group
// +kubebuilder:object:generate=true // +kubebuilder:object:generate=true
// +groupName=apps.libre.sh // +groupName=apps.libre.sh
package v1beta1 package v1alpha1
import ( import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
...@@ -25,7 +25,7 @@ import ( ...@@ -25,7 +25,7 @@ import (
var ( var (
// GroupVersion is group version used to register these objects // GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "apps.libre.sh", Version: "v1beta1"} GroupVersion = schema.GroupVersion{Group: "apps.libre.sh", Version: "v1alpha1"}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme // SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
......
...@@ -13,111 +13,46 @@ See the License for the specific language governing permissions and ...@@ -13,111 +13,46 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package v1beta1 package v1alpha1
import ( import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.libre.sh/application/components"
"k8s.libre.sh/application/settings"
) )
// NextcloudStatus defines the observed state of Nextcloud // NextcloudStatus defines the observed state of Nextcloud
type NextcloudStatus struct { type NextcloudStatus struct {
// Version defines the installed version // Version defines the installed version
Version string `json:"version,omitempty"` Version string `json:"version,omitempty"`
Phase Phase `json:"Phase,omitempty"` Settings map[string]SettingsStatus `json:"settings,omitempty"`
Phase Phase `json:"phase,omitempty"`
} }
// NextcloudSpec defines the desired state of Nextcloud type SettingsStatus struct {
type NextcloudSpec struct { Sources []settings.Source `json:"sources,omitempty"`
// Replicas *int32 `json:"replicas,omitempty"`
// Hosts []Host `json:"hosts,omitempty"`
// Storage storage.StorageSpec `json:"storage,omitempty"`
Version string `json:"version,omitempty"`
App Component `json:"app,omitempty"`
Web Component `json:"web,omitempty"`
CLI Component `json:"cli,omitempty"`
Cron Component `json:"cron,omitempty"`
Database Dependency `json:"database,omitempty"`
SMTP Dependency `json:"smtp,omitempty"`
ObjectStore Dependency `json:"objectStore,omitempty"`
Redis Dependency `json:"redis,omitempty"`
}
type From struct {
// The ConfigMap to select from.
corev1.LocalObjectReference `json:",inline" protobuf:"bytes,1,opt,name=localObjectReference"`
Value string `json:"value,omitempty"`
// The key to select.
Key string `json:"key,omitempty" protobuf:"bytes,2,opt,name=key"`
// An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.
// +optional
Prefix string `json:"prefix,omitempty" protobuf:"bytes,1,opt,name=prefix"`
}
//type Foo struct {
// Name string `json:"name,omitempty"`
// Keys []ParametersKey `json:"keys,omitempty"`
//}
//type ParametersKey struct {
// Value string `json:"value,omitempty"`
// Key string `json:"key" protobuf:"bytes,2,opt,name=key"`
// An optional identifier to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.
// +optional
// Prefix string `json:"prefix,omitempty" protobuf:"bytes,1,opt,name=prefix"`
//}
type Parameters struct {
From []From `json:"from,omitempty"`
EnvVar map[string]string `json:"envVar,omitempty"`
} }
type Settings struct { // NextcloudSpec defines the desired state of Nextcloud
Secrets []From `json:"secrets,omitempty"` type NextcloudSpec struct {
Parameters *Parameters `json:"parameters,omitempty"` Version string `json:"version,omitempty"`
Settings Settings `json:"settings,omitempty"`
App *App `json:"app,omitempty"`
Web *Web `json:"web,omitempty"`
CLI *CLI `json:"cli,omitempty"`
// Cron Component `json:"cron,omitempty"`
} }
type Component struct { type App struct {
Enabled bool `json:"enabled,omitempty"` *components.InternalWorkload `json:",inline"`
Name string `json:"name,omitempty"`
Runtime Runtime `json:"runtime,omitempty"`
Settings Settings `json:"settings,omitempty"`
} }
type Dependency struct { type Web struct {
Enabled bool `json:"enabled,omitempty"` *components.Workload `json:",inline"`
Name string `json:"name,omitempty"`
Settings Settings `json:"settings,omitempty"`
} }
// SecretRef represents a reference to a Secret type CLI struct {
type SecretRef string *components.CLI `json:",inline"`
// Host represents a valid hostname
type Host string
type Runtime struct {
Image string `json:"image,omitempty"`
ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
ServiceType corev1.ServiceType `json:"serviceType,omitempty"`
IngressAnnotations map[string]string `json:"ingressAnnotations,omitempty"`
Hosts []Host `json:"hosts,omitempty"`
// Number of desired pods. This is a pointer to distinguish between explicit
// zero and not specified. Defaults to 1.
// +optional
Replicas *int32 `json:"replicas,omitempty" protobuf:"varint,1,opt,name=replicas"`
TLSSecretRef SecretRef `json:"tlsSecretRef,omitempty"`
Ports []corev1.ContainerPort `json:"ports,omitempty"`
Resources corev1.ResourceRequirements `json:"resources,omitempty" protobuf:"bytes,8,opt,name=resources"`
SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"`
ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty" protobuf:"bytes,11,opt,name=readinessProbe"`
LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty" protobuf:"bytes,10,opt,name=livenessProbe"`
// The deployment strategy to use to replace existing pods with new ones.
// +optional
// +patchStrategy=retainKeys
Strategy appsv1.DeploymentStrategy `json:"strategy,omitempty" patchStrategy:"retainKeys" protobuf:"bytes,4,opt,name=strategy"`
} }
// Phase is the current status of a App as a whole. // Phase is the current status of a App as a whole.
......
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
"k8s.libre.sh/application"
"k8s.libre.sh/application/components"
"k8s.libre.sh/application/settings"
"k8s.libre.sh/interfaces"
"k8s.libre.sh/meta"
"k8s.libre.sh/objects/job"
)
var (
wwwDataUserID int64 = 33
)
func (o *Nextcloud) GetOwner() interfaces.Object { return o }
func (o *Nextcloud) GetName() string { return o.Name }
func (o *Nextcloud) GetNamespace() string { return o.Namespace }
func (o *Nextcloud) GetInstance() string { return o.Name }
func (o *Nextcloud) SetInstance(s string) {}
func (o *Nextcloud) GetVersion() string { return o.Spec.Version }
func (o *Nextcloud) SetVersion(s string) {}
func (o *Nextcloud) GetComponent() string { return "instance" }
func (o *Nextcloud) SetComponent(s string) {}
func (o *Nextcloud) GetPartOf() string { return "Nextcloud" }
func (o *Nextcloud) SetPartOf(s string) {}
func (o *Nextcloud) GetManagedBy() string { return "Nextcloud-operator" }
func (o *Nextcloud) SetManagedBy(s string) {}
func (o *Nextcloud) GetApplication() string { return "Nextcloud" }
func (o *Nextcloud) SetApplication(s string) {}
func (o *Nextcloud) GetSettings() map[string]settings.Settings {
// TODO TO FIX
setts := map[string]settings.Settings{
"app": settings.NewSettings(&o.Spec.Settings.AppSettings),
"web": settings.NewSettings(&o.Spec.Settings.Web),
}
if len(o.Status.Settings) > 0 {
for k, v := range o.Status.Settings {
setts[k].(*settings.Component).ConfigSpec.Sources = append(setts[k].(*settings.Component).ConfigSpec.Sources, v.Sources...)
}
}
return setts
}
func (app *Nextcloud) GetComponentsSyncOrder() map[int]string {
return map[int]string{
0: "settings",
1: "cli",
2: "app",
3: "web",
}
}
func (app *Nextcloud) GetComponents() map[string]application.Component {
cpts := map[string]application.Component{
"app": app.Spec.App,
"web": app.Spec.Web,
"cli": app.Spec.CLI,
}
return cpts
}
func (app *Nextcloud) Init() {
if app.Spec.App == nil {
app.Spec.App = &App{}
app.Spec.App.InternalWorkload = &components.InternalWorkload{}
}
if app.Spec.Web == nil {
app.Spec.Web = &Web{}
app.Spec.Web.Workload = &components.Workload{}
}
if app.Spec.CLI == nil {
app.Spec.CLI = &CLI{}
app.Spec.CLI.CLI = &components.CLI{}
}
for _, c := range app.GetComponents() {
c.Init()
}
if app.Spec.CLI == nil {
app.Spec.CLI = &CLI{}
app.Spec.CLI.Job = &job.Job{}
}
app.Spec.CLI.Init()
app.Spec.Settings.AppSettings.CreateOptions.Init()
app.Spec.Settings.Web.CreateOptions.Init()
}
func (app *Nextcloud) SetDefaultMeta() {
app.Spec.Web.ObjectMeta.SetComponent("web")
// TODO TO FIX create a func in application package
for _, c := range app.GetComponents() {
meta.SetObjectMetaFromInstance(app, c)
for _, o := range c.GetObjects() {
meta.SetObjectMeta(c, o)
}
}
// TODO TOFIX
meta.SetObjectMeta(app, app.Spec.CLI.ObjectMeta)
app.Spec.CLI.ObjectMeta.SetComponent("cli")
meta.SetObjectMeta(app, app.Spec.Settings.AppSettings.CreateOptions.CommonMeta)
app.Spec.Settings.AppSettings.CreateOptions.CommonMeta.Labels["app.kubernetes.io/component"] = "app"
meta.SetObjectMeta(app, app.Spec.Settings.Web.CreateOptions.CommonMeta)
app.Spec.Settings.Web.CreateOptions.CommonMeta.Labels["app.kubernetes.io/component"] = "web"
}
func (app *Nextcloud) SetDefaults() {
app.Spec.App.SetDefaults()
app.Spec.Web.SetDefaults()
app.Spec.CLI.SetDefaults()
app.Spec.Settings.SetDefaults()
app.Spec.Settings.SetDefaults()
}
package v1alpha1
import (
"k8s.libre.sh/application/settings"
)
type Settings struct {
CreateOptions settings.CreateOptions `json:"createOptions,omitempty"`
Sources []settings.Source `json:"sources,omitempty"`
AppSettings AppSettings `json:"app,omitempty"`
Web WebSettings `json:"web,omitempty"`
}
func (s *Settings) SetDefaults() {
s.AppSettings.SetDefaults()
s.Web.SetDefaults()
}
package v1alpha1
import (
"k8s.libre.sh/application/settings"
"k8s.libre.sh/meta"
"k8s.libre.sh/objects"
"sigs.k8s.io/controller-runtime/pkg/client"
)
type AppSettings struct {
CreateOptions settings.CreateOptions `json:"createOptions,omitempty"`
Sources []settings.Source `json:"sources,omitempty"`
Database Database `json:"database,omitempty"`
SMTP SMTP `json:"smtp,omitempty"`
General General `json:"general,omitempty"`
ObjectStore ObjectStore `json:"objectStore,omitempty"`
Redis Redis `json:"cache,omitempty"`
}
func (s *AppSettings) GetMeta() meta.Instance { return s.CreateOptions.CommonMeta }
func (s *AppSettings) SetDefaults() {
// s.CreateOptions.Init()
// s.CreateOptions.CommonMeta.Labels["app.kubernetes.io/component"] = "app"
s.General.SetDefaults()
s.Database.SetDefaults()
s.SMTP.SetDefaults()
s.ObjectStore.SetDefaults()
s.Redis.SetDefaults()
}
func (s *AppSettings) GetConfig() settings.Config {
params := *s.General.GetParameters()
params = append(params, *s.Database.GetParameters()...)
params = append(params, *s.SMTP.GetParameters()...)
params = append(params, *s.ObjectStore.GetParameters()...)
params = append(params, *s.Redis.GetParameters()...)
settings := &settings.ConfigSpec{
Parameters: &params,
Sources: s.Sources,
}
return settings
}
func (s *AppSettings) GetObjects() map[int]objects.Object {
return nil
}
func (s *AppSettings) Init(c client.Client) error {
return nil
}
func (s *AppSettings) GetCreateOptions() *settings.CreateOptions {
return &s.CreateOptions
}
...@@ -13,23 +13,22 @@ See the License for the specific language governing permissions and ...@@ -13,23 +13,22 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package application package v1alpha1
import ( import (
"github.com/presslabs/controller-util/syncer" "k8s.libre.sh/application/settings/parameters"
interfaces "git.indie.host/nextcloud-operator/interfaces"
) )
func (c *Component) NewServiceSyncer(r interfaces.Reconcile) syncer.Interface { type Redis struct {
return syncer.NewObjectSyncer("Service", c.Owner, &c.Service, r.GetClient(), r.GetScheme(), c.MutateService) Username parameters.Parameter `json:"username,omitempty" env:"REDIS_USERNAME"`
Password parameters.Parameter `json:"password,omitempty" env:"REDIS_PASSWORD"`
Host parameters.Parameter `json:"host,omitempty" env:"REDIS_HOST"`
Port parameters.Parameter `json:"port,omitempty" env:"REDIS_HOST_PORT"`
} }
func (c *Component) MutateService() error { func (d *Redis) SetDefaults() {
labels := c.Labels("app") }
c.Runtime.MutateService(&c.Service)
c.Service.Spec.Selector = labels
return nil func (s *Redis) GetParameters() *parameters.Parameters {
return &parameters.Parameters{}
} }
...@@ -13,54 +13,34 @@ See the License for the specific language governing permissions and ...@@ -13,54 +13,34 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package application package v1alpha1
import ( import "k8s.libre.sh/application/settings/parameters"
"fmt"
appsv1 "k8s.io/api/apps/v1" type Database struct {
corev1 "k8s.io/api/core/v1" Database parameters.Parameter `json:"database,omitempty" env:"DB_NAME"`
networking "k8s.io/api/networking/v1beta1" Host parameters.Parameter `json:"host,omitempty" env:"DB_HOST"`
Port parameters.Parameter `json:"port,omitempty" env:"DB_PORT"`
common "git.indie.host/nextcloud-operator/components/common" Type parameters.Parameter `json:"type,omitempty" env:"DB_TYPE"`
interfaces "git.indie.host/nextcloud-operator/interfaces" Username parameters.Parameter `json:"username,omitempty" env:"DB_USERNAME"`
) Password parameters.Parameter `json:"password,omitempty" env:"DB_PASSWORD"`
type Component struct {
Name string
*common.Common
Deployment appsv1.Deployment
Service corev1.Service
Ingress networking.Ingress
Secret corev1.Secret
} }
func CreateAndInit(common *common.Common) *Component { func (s *Database) SetDefaults() {
c := &Component{} if len(s.Database.Value) == 0 || len(s.Database.ValueFrom.Ref) == 0 {
c.Name = "app" s.Database.Value = "nextcloud"
c.Common = common
objects := c.GetObjects()
labels := c.Labels("app")
for _, o := range objects {
o.SetName(c.GetName())
o.SetNamespace(c.Owner.Namespace)
o.SetLabels(labels)
} }
return c if len(s.Port.Value) == 0 || len(s.Port.ValueFrom.Ref) == 0 {
} s.Port.Value = "5425"
}
func (c *Component) GetName() string { if len(s.Type.Value) == 0 || len(s.Type.ValueFrom.Ref) == 0 {
return fmt.Sprintf("%s-%s", c.Owner.Name, c.Name) s.Type.Value = "pgsql"
}
} }
func (c *Component) GetObjects() []interfaces.Object { func (s *Database) GetParameters() *parameters.Parameters {
return []interfaces.Object{ params, _ := parameters.Marshal(*s)
&c.Secret, return &params
&c.Deployment,
&c.Service,
&c.Ingress,
}
} }
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
"k8s.libre.sh/application/settings/parameters"
)
type General struct {
AppStore AppStore `json:"appStore,omitempty"`
Locales Locales `json:"locales,omitempty"`
GlobalSecrets `json:",inline"`
GlobalSettings `json:",inline"`
}
func (s *General) SetDefaults() {
s.AppStore.SetDefaults()
s.Locales.SetDefaults()
s.GlobalSecrets.SetDefaults()
s.GlobalSettings.SetDefaults()
}
func (s *General) GetParameters() *parameters.Parameters {
params := append(*s.AppStore.GetParameters(), *s.Locales.GetParameters()...)
params = append(params, *s.GlobalSecrets.GetParameters()...)
params = append(params, *s.GlobalSettings.GetParameters()...)
return &params
}
type GlobalSettings struct {
Domains parameters.Parameter `json:"domains,omitempty" env:"NEXTCLOUD_TRUSTED_DOMAINS"`
OverwriteCLI parameters.Parameter `json:"overwriteCLI,omitempty" env:"OVERWRITE_CLI_URL"`
OverwriteProtocol parameters.Parameter `json:"overwriteProtocol,omitempty" env:"OVERWRITE_PROTOCOL"`
DataDirectory parameters.Parameter `json:"dataDirectory,omitempty" env:"DATA_DIRECTORY"`
Debug parameters.Parameter `json:"debug,omitempty" env:"DEBUG"`
ReadOnly parameters.Parameter `json:"readOnly,omitempty" env:"CONFIG_READONLY"`
UpdateChecker parameters.Parameter `json:"updateChecker,omitempty" env:"UPDATE_CHECKER"`
UpdateURL parameters.Parameter `json:"udpateURL,omitempty" env:"OVERWRITECLI"`
UpdateChannel parameters.Parameter `json:"updateChannel,omitempty" env:"UPDATE_URL"`
UpdateDisable parameters.Parameter `json:"updateDisable,omitempty" env:"UPDATE_CHANNEL"`
BruteForce parameters.Parameter `json:"bruteforce,omitempty" env:"UPDATE_DISABLE_WEB"`
}
func (s *GlobalSettings) GetParameters() *parameters.Parameters {
params, _ := parameters.Marshal(*s)
return &params
}
func (s *GlobalSettings) SetDefaults() {
if len(s.ReadOnly.Value) == 0 || len(s.ReadOnly.ValueFrom.Ref) == 0 {
s.ReadOnly.Value = "true"
}
if len(s.DataDirectory.Value) == 0 || len(s.DataDirectory.ValueFrom.Ref) == 0 {
s.DataDirectory.Value = "/var/www/html/data"
}
if len(s.UpdateChecker.Value) == 0 || len(s.UpdateChecker.ValueFrom.Ref) == 0 {
s.UpdateChecker.Value = "false"
}
if len(s.UpdateDisable.Value) == 0 || len(s.UpdateDisable.ValueFrom.Ref) == 0 {
s.UpdateDisable.Value = "true"
}
if len(s.Domains.Value) == 0 || len(s.Domains.ValueFrom.Ref) == 0 {
s.Domains.Value = "{{ .settings.app.INSTANCE_ID }}"
s.Domains.Generate = parameters.GenerateTemplate
s.Domains.Type = parameters.SecretParameter
}
}
type GlobalSecrets struct {
InstanceID parameters.Parameter `json:"instanceID,omitempty" env:"INSTANCE_ID"`
PasswordSalt parameters.Parameter `json:"passwordSalt,omitempty" env:"PASSWORD_SALT"`
Secret parameters.Parameter `json:"secret,omitempty" env:"SECRET"`
AdminPassword parameters.Parameter `json:"adminPassword,omitempty" env:"ADMIN_PASSWORD"`
AdminUsername parameters.Parameter `json:"adminUsername,omitempty" env:"ADMIN_USERNAME"`
}
func (s *GlobalSecrets) SetDefaults() {
// TODO return warning if value is defined and ignore it. Or use secretParameter type to enforce no values
if len(s.InstanceID.Value) > 0 || len(s.InstanceID.ValueFrom.Ref) == 0 {
s.InstanceID.Generate = parameters.GenerateRand12
}
if len(s.PasswordSalt.Value) == 0 || len(s.PasswordSalt.ValueFrom.Ref) == 0 {
s.PasswordSalt.Generate = parameters.GenerateRand12
}
if len(s.Secret.Value) == 0 || len(s.Secret.ValueFrom.Ref) == 0 {
s.Secret.Generate = parameters.GenerateRand12
}
if len(s.AdminPassword.Value) == 0 || len(s.AdminPassword.ValueFrom.Ref) == 0 {
s.AdminPassword.Generate = parameters.GenerateRand12
}
if len(s.AdminUsername.Value) == 0 || len(s.AdminUsername.ValueFrom.Ref) == 0 {
s.AdminUsername.Value = "admin"
}
}
func (s *GlobalSecrets) GetParameters() *parameters.Parameters {
params, _ := parameters.Marshal(*s)
return &params
}
type AppStore struct {
// StoreEnabled defines if the app store is enabled
StoreEnabled parameters.Parameter `json:"storeEnabled,omitempty" env:"APPS_STORE_ENABLE"`
// Default defines the default app
Default parameters.Parameter `json:"default,omitempty" env:"APPS_DEFAULT"`
// StoreUrl defines the URL for the app store
StoreURL parameters.Parameter `json:"storeURL,omitempty" env:"APPS_STORE_URL"`
}
func (s *AppStore) SetDefaults() {
if len(s.StoreEnabled.Value) == 0 || len(s.StoreEnabled.ValueFrom.Ref) == 0 {
s.StoreEnabled.Value = "false"
}
}
func (s *AppStore) GetParameters() *parameters.Parameters {
params, _ := parameters.Marshal(*s)
return &params
}
type Locales struct {
// Default defines the default language
Default parameters.Parameter `json:"default,omitempty" env:"DEFAULT_LANGUAGE"`
Locale parameters.Parameter `json:"locale,omitempty" env:"DEFAULT_LOCALE"`
ForceLanguage parameters.Parameter `json:"forceLanguage,omitempty" env:"FORCE_LANGUAGE"`
ForceLocale parameters.Parameter `json:"forceLocale,omitempty" env:"DEFAULT_LOCALE"`
}
func (s *Locales) SetDefaults() {}
func (s *Locales) GetParameters() *parameters.Parameters {
params, _ := parameters.Marshal(*s)
return &params
}
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
"k8s.libre.sh/application/settings/parameters"
)
type SMTP struct {
Username parameters.Parameter `json:"username,omitempty" env:"SMTP_USERNAME"`
Password parameters.Parameter `json:"password,omitempty" env:"SMTP_PASSWORD"`
FromAdress parameters.Parameter `json:"fromAddress,omitempty" env:"MAIL_FROM_ADDRESS"`
Domain parameters.Parameter `json:"domain,omitempty" env:"MAIL_DOMAIN"`
Secure parameters.Parameter `json:"secure,omitempty" env:"SMTP_SECURE"`
AuthType parameters.Parameter `json:"authType,omitempty" env:"SMTP_AUTHTYPE"`
Debug parameters.Parameter `json:"debug,omitempty" env:"SMTP_DEBUG"`
Host parameters.Parameter `json:"host,omitempty" env:"SMTP_HOST"`
Port parameters.Parameter `json:"port,omitempty" env:"SMTP_PORT"`
TemplateClass parameters.Parameter `json:"templateClass,omitempty" env:"SMTP_TEMPLATE_CLASS"`
PlainTextOnly parameters.Parameter `json:"plainTextOnly,omitempty" env:"SMTP_SEND_PLAINTEXT_ONLY"`
}
func (d *SMTP) SetDefaults() {
}
func (s *SMTP) GetParameters() *parameters.Parameters {
params, _ := parameters.Marshal(*s)
return &params
}
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import "k8s.libre.sh/application/settings/parameters"
type ObjectStore struct {
Bucket parameters.Parameter `json:"bucket,omitempty" env:"OBJECTSTORE_S3_BUCKET"`
Host parameters.Parameter `json:"host,omitempty" env:"OBJECTSTORE_S3_HOST"`
Port parameters.Parameter `json:"port,omitempty" env:"OBJECTSTORE_S3_PORT"`
AutoCreate parameters.Parameter `json:"autocreate,omitempty" env:"OBJECTSTORE_S3_AUTOCREATE"`
SSL parameters.Parameter `json:"ssl,omitempty" env:"OBJECTSTORE_S3_SSL"`
Region parameters.Parameter `json:"region,omitempty" env:"OBJECTSTORE_S3_REGION"`
PathStyle parameters.Parameter `json:"pathStyle,omitempty" env:"OBJECTSTORE_S3_USEPATH_STYLE"`
AccessKeyID parameters.Parameter `json:"accessKeyID,omitempty" env:"OBJECTSTORE_S3_KEY"`
SecretAccessKey parameters.Parameter `json:"secretAccessKey,omitempty" env:"OBJECTSTORE_S3_SECRET"`
}
func (s *ObjectStore) SetDefaults() {
/* if len(d.Bucket) == 0 {
d.Bucket = "nextcloud"
}
if len(d.Port) == 0 {
d.Port = "443"
}
if len(d.Region) == 0 {
d.Region = "default"
} */
}
func (s *ObjectStore) GetParameters() *parameters.Parameters {
params, _ := parameters.Marshal(*s)
return &params
}
/* /*
Licensed under the GNU AFFERO GENERAL PUBLIC LICENSE, Version 3 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
https://www.gnu.org/licenses/agpl-3.0.html http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
...@@ -13,18 +13,17 @@ See the License for the specific language governing permissions and ...@@ -13,18 +13,17 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package web package v1alpha1
import ( import (
"bytes" "k8s.libre.sh/application/settings"
"html/template" "k8s.libre.sh/application/settings/parameters"
"k8s.libre.sh/meta"
"github.com/presslabs/controller-util/syncer" "k8s.libre.sh/objects"
"sigs.k8s.io/controller-runtime/pkg/client"
interfaces "git.indie.host/nextcloud-operator/interfaces"
) )
const conf = ` const nginxConf = `
user www-data; user www-data;
events { events {
worker_connections 768; worker_connections 768;
...@@ -32,9 +31,9 @@ const conf = ` ...@@ -32,9 +31,9 @@ const conf = `
http { http {
upstream backend { upstream backend {
server {{ .Name }}-app:9000; server {{ .components.app.service.meta.name }}:{{ .components.app.service.port.port }};
} }
include /etc/nginx/mime.types; include /etc/nginx/mime.types
default_type application/octet-stream; default_type application/octet-stream;
server { server {
...@@ -132,36 +131,50 @@ const conf = ` ...@@ -132,36 +131,50 @@ const conf = `
} }
` `
func (c *Component) NewConfigMapSyncer(r interfaces.Reconcile) syncer.Interface { type WebSettings struct {
return syncer.NewObjectSyncer("ConfigMap", c.Owner, &c.ConfigMap, r.GetClient(), r.GetScheme(), c.MutateConfigMap) CreateOptions settings.CreateOptions `json:"createOptions,omitempty"`
Sources []settings.Source `json:"sources,omitempty"`
ConfTemplate parameters.Parameter `json:"conf,omitempty" env:"nginx-conf"`
} }
func (c *Component) MutateConfigMap() error { func (s *WebSettings) SetDefaults() {
data, err := c.GenConfigMapData()
if err != nil {
return err
}
c.ConfigMap.Data = data
return nil // s.CreateOptions.Init()
} // s.CreateOptions.CommonMeta.Labels["app.kubernetes.io/component"] = "web"
// GenAppConfigMapData func generates data for the web configmap that contains the nginx.conf if len(s.ConfTemplate.Value) > 0 || len(s.ConfTemplate.ValueFrom.Ref) == 0 {
func (c *Component) GenConfigMapData() (map[string]string, error) { s.ConfTemplate.Value = nginxConf
var cm map[string]string s.ConfTemplate.Generate = parameters.GenerateTemplate
tmpl, err := template.New("test").Parse(conf) s.ConfTemplate.MountType = parameters.MountEnvFile
if err != nil { s.ConfTemplate.Type = parameters.ConfigParameter
return nil, err s.ConfTemplate.MountType = parameters.MountFile
} s.ConfTemplate.MountPath.Path = "/etc/nginx/nginx.conf"
var tpl bytes.Buffer s.ConfTemplate.MountPath.SubPath = "nginx.conf"
err = tmpl.Execute(&tpl, c.Owner)
if err != nil {
return nil, err
} }
}
func (s *WebSettings) GetConfig() settings.Config {
params, _ := parameters.Marshal(*s)
cm = map[string]string{ settings := &settings.ConfigSpec{
"nginx.conf": tpl.String(), Parameters: &params,
Sources: s.Sources,
} }
return cm, nil return settings
}
func (s *WebSettings) GetMeta() meta.Instance { return s.CreateOptions.CommonMeta }
func (s *WebSettings) GetObjects() map[int]objects.Object {
return nil
}
func (s *WebSettings) Init(c client.Client) error {
return nil
}
func (s *WebSettings) GetCreateOptions() *settings.CreateOptions {
return &s.CreateOptions
} }
...@@ -17,58 +17,199 @@ limitations under the License. ...@@ -17,58 +17,199 @@ limitations under the License.
// Code generated by controller-gen. DO NOT EDIT. // Code generated by controller-gen. DO NOT EDIT.
package v1beta1 package v1alpha1
import ( import (
"k8s.io/api/core/v1"
runtime "k8s.io/apimachinery/pkg/runtime" runtime "k8s.io/apimachinery/pkg/runtime"
"k8s.libre.sh/application/components"
"k8s.libre.sh/application/settings"
) )
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Component) DeepCopyInto(out *Component) { func (in *App) DeepCopyInto(out *App) {
*out = *in *out = *in
in.Runtime.DeepCopyInto(&out.Runtime) if in.InternalWorkload != nil {
in.Settings.DeepCopyInto(&out.Settings) in, out := &in.InternalWorkload, &out.InternalWorkload
*out = new(components.InternalWorkload)
(*in).DeepCopyInto(*out)
}
} }
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Component. // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new App.
func (in *Component) DeepCopy() *Component { func (in *App) DeepCopy() *App {
if in == nil { if in == nil {
return nil return nil
} }
out := new(Component) out := new(App)
in.DeepCopyInto(out) in.DeepCopyInto(out)
return out return out
} }
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Dependency) DeepCopyInto(out *Dependency) { func (in *AppSettings) DeepCopyInto(out *AppSettings) {
*out = *in *out = *in
in.Settings.DeepCopyInto(&out.Settings) in.CreateOptions.DeepCopyInto(&out.CreateOptions)
if in.Sources != nil {
in, out := &in.Sources, &out.Sources
*out = make([]settings.Source, len(*in))
copy(*out, *in)
}
out.Database = in.Database
out.SMTP = in.SMTP
out.General = in.General
out.ObjectStore = in.ObjectStore
out.Redis = in.Redis
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppSettings.
func (in *AppSettings) DeepCopy() *AppSettings {
if in == nil {
return nil
}
out := new(AppSettings)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AppStore) DeepCopyInto(out *AppStore) {
*out = *in
out.StoreEnabled = in.StoreEnabled
out.Default = in.Default
out.StoreURL = in.StoreURL
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppStore.
func (in *AppStore) DeepCopy() *AppStore {
if in == nil {
return nil
}
out := new(AppStore)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CLI) DeepCopyInto(out *CLI) {
*out = *in
if in.CLI != nil {
in, out := &in.CLI, &out.CLI
*out = new(components.CLI)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CLI.
func (in *CLI) DeepCopy() *CLI {
if in == nil {
return nil
}
out := new(CLI)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Database) DeepCopyInto(out *Database) {
*out = *in
out.Database = in.Database
out.Host = in.Host
out.Port = in.Port
out.Type = in.Type
out.Username = in.Username
out.Password = in.Password
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Database.
func (in *Database) DeepCopy() *Database {
if in == nil {
return nil
}
out := new(Database)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *General) DeepCopyInto(out *General) {
*out = *in
out.AppStore = in.AppStore
out.Locales = in.Locales
out.GlobalSecrets = in.GlobalSecrets
out.GlobalSettings = in.GlobalSettings
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new General.
func (in *General) DeepCopy() *General {
if in == nil {
return nil
}
out := new(General)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GlobalSecrets) DeepCopyInto(out *GlobalSecrets) {
*out = *in
out.InstanceID = in.InstanceID
out.PasswordSalt = in.PasswordSalt
out.Secret = in.Secret
out.AdminPassword = in.AdminPassword
out.AdminUsername = in.AdminUsername
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlobalSecrets.
func (in *GlobalSecrets) DeepCopy() *GlobalSecrets {
if in == nil {
return nil
}
out := new(GlobalSecrets)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GlobalSettings) DeepCopyInto(out *GlobalSettings) {
*out = *in
out.Domains = in.Domains
out.OverwriteCLI = in.OverwriteCLI
out.OverwriteProtocol = in.OverwriteProtocol
out.DataDirectory = in.DataDirectory
out.Debug = in.Debug
out.ReadOnly = in.ReadOnly
out.UpdateChecker = in.UpdateChecker
out.UpdateURL = in.UpdateURL
out.UpdateChannel = in.UpdateChannel
out.UpdateDisable = in.UpdateDisable
out.BruteForce = in.BruteForce
} }
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Dependency. // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlobalSettings.
func (in *Dependency) DeepCopy() *Dependency { func (in *GlobalSettings) DeepCopy() *GlobalSettings {
if in == nil { if in == nil {
return nil return nil
} }
out := new(Dependency) out := new(GlobalSettings)
in.DeepCopyInto(out) in.DeepCopyInto(out)
return out return out
} }
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *From) DeepCopyInto(out *From) { func (in *Locales) DeepCopyInto(out *Locales) {
*out = *in *out = *in
out.LocalObjectReference = in.LocalObjectReference out.Default = in.Default
out.Locale = in.Locale
out.ForceLanguage = in.ForceLanguage
out.ForceLocale = in.ForceLocale
} }
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new From. // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Locales.
func (in *From) DeepCopy() *From { func (in *Locales) DeepCopy() *Locales {
if in == nil { if in == nil {
return nil return nil
} }
out := new(From) out := new(Locales)
in.DeepCopyInto(out) in.DeepCopyInto(out)
return out return out
} }
...@@ -79,7 +220,7 @@ func (in *Nextcloud) DeepCopyInto(out *Nextcloud) { ...@@ -79,7 +220,7 @@ func (in *Nextcloud) DeepCopyInto(out *Nextcloud) {
out.TypeMeta = in.TypeMeta out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec) in.Spec.DeepCopyInto(&out.Spec)
out.Status = in.Status in.Status.DeepCopyInto(&out.Status)
} }
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Nextcloud. // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Nextcloud.
...@@ -135,14 +276,22 @@ func (in *NextcloudList) DeepCopyObject() runtime.Object { ...@@ -135,14 +276,22 @@ func (in *NextcloudList) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NextcloudSpec) DeepCopyInto(out *NextcloudSpec) { func (in *NextcloudSpec) DeepCopyInto(out *NextcloudSpec) {
*out = *in *out = *in
in.App.DeepCopyInto(&out.App) in.Settings.DeepCopyInto(&out.Settings)
in.Web.DeepCopyInto(&out.Web) if in.App != nil {
in.CLI.DeepCopyInto(&out.CLI) in, out := &in.App, &out.App
in.Cron.DeepCopyInto(&out.Cron) *out = new(App)
in.Database.DeepCopyInto(&out.Database) (*in).DeepCopyInto(*out)
in.SMTP.DeepCopyInto(&out.SMTP) }
in.ObjectStore.DeepCopyInto(&out.ObjectStore) if in.Web != nil {
in.Redis.DeepCopyInto(&out.Redis) in, out := &in.Web, &out.Web
*out = new(Web)
(*in).DeepCopyInto(*out)
}
if in.CLI != nil {
in, out := &in.CLI, &out.CLI
*out = new(CLI)
(*in).DeepCopyInto(*out)
}
} }
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NextcloudSpec. // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NextcloudSpec.
...@@ -158,6 +307,13 @@ func (in *NextcloudSpec) DeepCopy() *NextcloudSpec { ...@@ -158,6 +307,13 @@ func (in *NextcloudSpec) DeepCopy() *NextcloudSpec {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NextcloudStatus) DeepCopyInto(out *NextcloudStatus) { func (in *NextcloudStatus) DeepCopyInto(out *NextcloudStatus) {
*out = *in *out = *in
if in.Settings != nil {
in, out := &in.Settings, &out.Settings
*out = make(map[string]SettingsStatus, len(*in))
for key, val := range *in {
(*out)[key] = *val.DeepCopy()
}
}
} }
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NextcloudStatus. // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NextcloudStatus.
...@@ -171,112 +327,155 @@ func (in *NextcloudStatus) DeepCopy() *NextcloudStatus { ...@@ -171,112 +327,155 @@ func (in *NextcloudStatus) DeepCopy() *NextcloudStatus {
} }
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Parameters) DeepCopyInto(out *Parameters) { func (in *ObjectStore) DeepCopyInto(out *ObjectStore) {
*out = *in *out = *in
if in.From != nil { out.Bucket = in.Bucket
in, out := &in.From, &out.From out.Host = in.Host
*out = make([]From, len(*in)) out.Port = in.Port
copy(*out, *in) out.AutoCreate = in.AutoCreate
} out.SSL = in.SSL
if in.EnvVar != nil { out.Region = in.Region
in, out := &in.EnvVar, &out.EnvVar out.PathStyle = in.PathStyle
*out = make(map[string]string, len(*in)) out.AccessKeyID = in.AccessKeyID
for key, val := range *in { out.SecretAccessKey = in.SecretAccessKey
(*out)[key] = val
}
}
} }
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Parameters. // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectStore.
func (in *Parameters) DeepCopy() *Parameters { func (in *ObjectStore) DeepCopy() *ObjectStore {
if in == nil { if in == nil {
return nil return nil
} }
out := new(Parameters) out := new(ObjectStore)
in.DeepCopyInto(out) in.DeepCopyInto(out)
return out return out
} }
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Runtime) DeepCopyInto(out *Runtime) { func (in *Redis) DeepCopyInto(out *Redis) {
*out = *in *out = *in
if in.ImagePullSecrets != nil { out.Username = in.Username
in, out := &in.ImagePullSecrets, &out.ImagePullSecrets out.Password = in.Password
*out = make([]v1.LocalObjectReference, len(*in)) out.Host = in.Host
copy(*out, *in) out.Port = in.Port
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Redis.
func (in *Redis) DeepCopy() *Redis {
if in == nil {
return nil
} }
if in.IngressAnnotations != nil { out := new(Redis)
in, out := &in.IngressAnnotations, &out.IngressAnnotations in.DeepCopyInto(out)
*out = make(map[string]string, len(*in)) return out
for key, val := range *in { }
(*out)[key] = val
} // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SMTP) DeepCopyInto(out *SMTP) {
*out = *in
out.Username = in.Username
out.Password = in.Password
out.FromAdress = in.FromAdress
out.Domain = in.Domain
out.Secure = in.Secure
out.AuthType = in.AuthType
out.Debug = in.Debug
out.Host = in.Host
out.Port = in.Port
out.TemplateClass = in.TemplateClass
out.PlainTextOnly = in.PlainTextOnly
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SMTP.
func (in *SMTP) DeepCopy() *SMTP {
if in == nil {
return nil
} }
if in.Hosts != nil { out := new(SMTP)
in, out := &in.Hosts, &out.Hosts in.DeepCopyInto(out)
*out = make([]Host, len(*in)) return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Settings) DeepCopyInto(out *Settings) {
*out = *in
in.CreateOptions.DeepCopyInto(&out.CreateOptions)
if in.Sources != nil {
in, out := &in.Sources, &out.Sources
*out = make([]settings.Source, len(*in))
copy(*out, *in) copy(*out, *in)
} }
if in.Replicas != nil { in.AppSettings.DeepCopyInto(&out.AppSettings)
in, out := &in.Replicas, &out.Replicas in.Web.DeepCopyInto(&out.Web)
*out = new(int32) }
**out = **in
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Settings.
func (in *Settings) DeepCopy() *Settings {
if in == nil {
return nil
} }
if in.Ports != nil { out := new(Settings)
in, out := &in.Ports, &out.Ports in.DeepCopyInto(out)
*out = make([]v1.ContainerPort, len(*in)) return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SettingsStatus) DeepCopyInto(out *SettingsStatus) {
*out = *in
if in.Sources != nil {
in, out := &in.Sources, &out.Sources
*out = make([]settings.Source, len(*in))
copy(*out, *in) copy(*out, *in)
} }
in.Resources.DeepCopyInto(&out.Resources) }
if in.SecurityContext != nil {
in, out := &in.SecurityContext, &out.SecurityContext // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SettingsStatus.
*out = new(v1.PodSecurityContext) func (in *SettingsStatus) DeepCopy() *SettingsStatus {
(*in).DeepCopyInto(*out) if in == nil {
} return nil
if in.ReadinessProbe != nil {
in, out := &in.ReadinessProbe, &out.ReadinessProbe
*out = new(v1.Probe)
(*in).DeepCopyInto(*out)
} }
if in.LivenessProbe != nil { out := new(SettingsStatus)
in, out := &in.LivenessProbe, &out.LivenessProbe in.DeepCopyInto(out)
*out = new(v1.Probe) return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Web) DeepCopyInto(out *Web) {
*out = *in
if in.Workload != nil {
in, out := &in.Workload, &out.Workload
*out = new(components.Workload)
(*in).DeepCopyInto(*out) (*in).DeepCopyInto(*out)
} }
in.Strategy.DeepCopyInto(&out.Strategy)
} }
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Runtime. // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Web.
func (in *Runtime) DeepCopy() *Runtime { func (in *Web) DeepCopy() *Web {
if in == nil { if in == nil {
return nil return nil
} }
out := new(Runtime) out := new(Web)
in.DeepCopyInto(out) in.DeepCopyInto(out)
return out return out
} }
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Settings) DeepCopyInto(out *Settings) { func (in *WebSettings) DeepCopyInto(out *WebSettings) {
*out = *in *out = *in
if in.Secrets != nil { in.CreateOptions.DeepCopyInto(&out.CreateOptions)
in, out := &in.Secrets, &out.Secrets if in.Sources != nil {
*out = make([]From, len(*in)) in, out := &in.Sources, &out.Sources
*out = make([]settings.Source, len(*in))
copy(*out, *in) copy(*out, *in)
} }
if in.Parameters != nil { out.ConfTemplate = in.ConfTemplate
in, out := &in.Parameters, &out.Parameters
*out = new(Parameters)
(*in).DeepCopyInto(*out)
}
} }
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Settings. // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebSettings.
func (in *Settings) DeepCopy() *Settings { func (in *WebSettings) DeepCopy() *WebSettings {
if in == nil { if in == nil {
return nil return nil
} }
out := new(Settings) out := new(WebSettings)
in.DeepCopyInto(out) in.DeepCopyInto(out)
return out return out
} }
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
"sort"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
networking "k8s.io/api/networking/v1beta1"
interfaces "git.indie.host/nextcloud-operator/interfaces"
)
const (
// InternalHTTPPort represents the internal port used by the runtime container
HTTPPort = 8080
)
var (
wwwDataUserID int64 = 33
)
func (r *Runtime) MutateContainer(obj *corev1.Container) error {
r.SetDefaults()
obj.Name = "test"
obj.Image = r.Image
obj.ImagePullPolicy = r.ImagePullPolicy
obj.Ports = r.Ports
obj.LivenessProbe = r.LivenessProbe
obj.ReadinessProbe = r.ReadinessProbe
return nil
}
func (s *Settings) MutateDeployment(obj *appsv1.Deployment) error {
s.MutatePod(&obj.Spec.Template)
return nil
}
func (r *Runtime) MutateDeployment(obj *appsv1.Deployment) error {
obj.Spec.Replicas = r.Replicas
r.MutatePod(&obj.Spec.Template)
return nil
}
func (s *Settings) MutatePod(obj *corev1.PodTemplateSpec) error {
container := &corev1.Container{}
containers := []corev1.Container{}
container.Name = "test"
s.MutateContainerEnvFrom(container)
containers = append(containers, *container)
if len(obj.Spec.Containers) == 0 {
obj.Spec.Containers = containers
} else {
s.MutateContainerEnvFrom(&obj.Spec.Containers[0])
}
return nil
}
func (r *Runtime) MutatePod(obj *corev1.PodTemplateSpec) error {
container := &corev1.Container{}
containers := []corev1.Container{}
obj.Spec.SecurityContext = r.SecurityContext
r.MutateContainer(container)
containers = append(containers, *container)
if len(obj.Spec.Containers) == 0 {
obj.Spec.Containers = containers
} else {
r.MutateContainer(&obj.Spec.Containers[0])
}
return nil
}
func (f *From) GetLocalObjectReference() corev1.LocalObjectReference {
return f.LocalObjectReference
}
func (f *From) GetValue() string {
return f.Value
}
func (f *From) GetKey() string {
return f.Key
}
func GenEnv(e interfaces.EnvSource, object string) (corev1.EnvFromSource, corev1.EnvVar) {
envFrom := corev1.EnvFromSource{}
envVar := corev1.EnvVar{}
if len(e.GetKey()) == 0 && len(e.GetLocalObjectReference().Name) > 0 && len(e.GetValue()) == 0 {
if object == "configmap" {
ref := &corev1.ConfigMapEnvSource{
LocalObjectReference: e.GetLocalObjectReference(),
}
envFrom.ConfigMapRef = ref
} else {
ref := &corev1.SecretEnvSource{
LocalObjectReference: e.GetLocalObjectReference(),
}
envFrom.SecretRef = ref
}
} else if len(e.GetLocalObjectReference().Name) > 0 && len(e.GetValue()) > 0 {
envVar.Name = e.GetValue()
if object == "configmap" {
valueFrom := &corev1.EnvVarSource{
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
LocalObjectReference: e.GetLocalObjectReference(),
Key: e.GetKey(),
},
}
envVar.ValueFrom = valueFrom
} else {
valueFrom := &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: e.GetLocalObjectReference(),
Key: e.GetKey(),
},
}
envVar.ValueFrom = valueFrom
}
}
return envFrom, envVar
}
func (s *Settings) MutateContainerEnvFrom(obj *corev1.Container) error {
configMapSources := s.Parameters.From
secretSources := s.Secrets
envVars := []corev1.EnvVar{}
envFroms := []corev1.EnvFromSource{}
for _, source := range configMapSources {
envFrom, envVar := GenEnv(&source, "configmap")
if len(envVar.Name) > 0 {
envVars = append(envVars, envVar)
}
if envFrom.ConfigMapRef != nil {
envFroms = append(envFroms, envFrom)
}
}
if &secretSources != nil {
for _, source := range secretSources {
if &source != nil {
envFrom, envVar := GenEnv(&source, "secret")
if len(envVar.Name) > 0 {
envVars = append(envVars, envVar)
}
if envFrom.SecretRef != nil {
envFroms = append(envFroms, envFrom)
}
}
}
}
for k, v := range s.Parameters.EnvVar {
envVar := corev1.EnvVar{
Name: k,
Value: v,
}
envVars = append(envVars, envVar)
}
// Sort var to avoid update of the object if var are not in the same order?
sort.SliceStable(envVars, func(i, j int) bool {
return envVars[i].Name < envVars[j].Name
})
obj.EnvFrom = envFroms
obj.Env = envVars
return nil
}
func (r *Runtime) MutateService(obj *corev1.Service) error {
ports := []corev1.ServicePort{
{
Port: 9000,
Name: "http",
},
}
obj.Spec.Type = r.ServiceType
obj.Spec.Ports = ports
return nil
}
func (r *Runtime) MutateIngress(obj *networking.Ingress) error {
obj.ObjectMeta.Annotations = r.IngressAnnotations
if len(r.TLSSecretRef) > 0 {
tls := networking.IngressTLS{
SecretName: string(r.TLSSecretRef),
}
for _, d := range r.Hosts {
tls.Hosts = append(tls.Hosts, string(d))
}
obj.Spec.TLS = []networking.IngressTLS{tls}
} else {
obj.Spec.TLS = nil
}
return nil
}
func (r *Runtime) SetDefaults() {
if len(r.Image) == 0 {
r.Image = "indiehosters/nextcloud"
}
if len(r.ServiceType) == 0 {
r.ServiceType = "ClusterIP"
}
if r.Ports == nil {
ports := []corev1.ContainerPort{
{
Name: "http",
ContainerPort: int32(HTTPPort),
Protocol: "TCP",
},
}
r.Ports = ports
}
// if r.Strategy == nil {
// r.Strategy = "recreate"
// }
if r.SecurityContext == nil {
r.SecurityContext = &corev1.PodSecurityContext{
RunAsUser: &wwwDataUserID,
RunAsGroup: &wwwDataUserID,
FSGroup: &wwwDataUserID,
}
}
}
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cli
import (
"fmt"
"github.com/presslabs/controller-util/syncer"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
common "git.indie.host/nextcloud-operator/components/common"
interfaces "git.indie.host/nextcloud-operator/interfaces"
)
type Component struct {
Name string
*common.Common
Job batchv1.Job
}
func CreateAndInit(common *common.Common) *Component {
c := &Component{}
c.Name = "cli"
c.Common = common
labels := c.Labels("cli")
objects := c.GetObjects()
for _, o := range objects {
o.SetName(c.GetName())
o.SetNamespace(c.Owner.Namespace)
o.SetLabels(labels)
}
return c
}
func (c *Component) NewJobSyncer(r interfaces.Reconcile) syncer.Interface {
return syncer.NewObjectSyncer("Job", c.Owner, &c.Job, r.GetClient(), r.GetScheme(), c.MutateJob)
}
func (c *Component) MutateJob() error {
c.Settings.MutatePod(&c.Job.Spec.Template)
c.Runtime.MutatePod(&c.Job.Spec.Template)
// _ = mergo.Merge(&component.Job.Spec.Template.ObjectMeta, &component.Job.ObjectMeta)
// component.Job.Spec.Template.ObjectMeta = component.Job.ObjectMeta
c.Job.Spec.Template.Spec.RestartPolicy = corev1.RestartPolicyNever
// args := []string{"/usr/local/bin/php", "/var/www/html/cron.php"}
// component.Job.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Args = args
return nil
}
func (c *Component) GetName() string {
return fmt.Sprintf("%s-%s", c.Owner.Name, c.Name)
}
func (c *Component) GetObjects() []interfaces.Object {
return []interfaces.Object{
&c.Job,
}
}
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package common
import (
"github.com/imdario/mergo"
"k8s.io/apimachinery/pkg/labels"
appsv1beta1 "git.indie.host/nextcloud-operator/api/v1beta1"
)
type Common struct {
Owner *appsv1beta1.Nextcloud
Settings *appsv1beta1.Settings
Runtime *appsv1beta1.Runtime
}
func CreateAndInit(app *appsv1beta1.Nextcloud) *Common {
// app.SetDefaults()
runtime := &app.Spec.App.Runtime
settings := &app.Spec.App.Settings
if app.Spec.Database.Enabled {
settings.Secrets = append(settings.Secrets, app.Spec.Database.Settings.Secrets...)
err := mergo.Merge(settings.Parameters, app.Spec.Database.Settings.Parameters)
if err != nil {
// do something
}
}
if app.Spec.Redis.Enabled {
settings.Secrets = append(settings.Secrets, app.Spec.Redis.Settings.Secrets...)
err := mergo.Merge(settings.Parameters, app.Spec.Redis.Settings.Parameters)
if err != nil {
// do something
}
}
if app.Spec.ObjectStore.Enabled {
settings.Secrets = append(settings.Secrets, app.Spec.ObjectStore.Settings.Secrets...)
err := mergo.Merge(settings.Parameters, app.Spec.ObjectStore.Settings.Parameters)
if err != nil {
// do something
}
}
if app.Spec.SMTP.Enabled {
err := mergo.Merge(settings, app.Spec.SMTP.Settings)
if err != nil {
// do something
}
}
return &Common{
Owner: app,
Settings: settings,
Runtime: runtime,
}
}
func (c *Common) Labels(component string) labels.Set {
partOf := "nextcloud"
// if o.ObjectMeta.Labels != nil && len(o.ObjectMeta.Labels["app.kubernetes.io/part-of"]) > 0 {
// partOf = o.ObjectMeta.Labels["app.kubernetes.io/part-of"]
// }
labels := labels.Set{
"app.kubernetes.io/name": "nextcloud",
"app.kubernetes.io/part-of": partOf,
"app.kubernetes.io/instance": c.Owner.ObjectMeta.Name,
// "app.kubernetes.io/version": c.Owner.Spec.AppVersion,
"app.kubernetes.io/component": component,
"app.kubernetes.io/managed-by": "nextcloud-operator.libre.sh",
}
return labels
}
//func (c *Common) SetDefaults() {
//}
//func (c *Common) GetDeployment() obj *appsv1.deployment {
// c.Settings.MutateDeployment(obj)
// return obj
//}
//func (c *Common) GetService() obj *corev1.service {
// return obj
//}
//func (c *Common) GetConfigMap() obj *corev1.ConfigMap {
// return obj
//}
//func (c *Common) GetSecret() obj *corev1.Secret {
//return obj
//}