blob: 66ecde0b5a8130afb7cbc3de185d7c85358f4d67 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 (
"fmt"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"strings"
)
// 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.
const (
DefaultAWSCliImageRepo = "infrastructureascode/aws-cli"
DefaultAWSCliImageVersion = "1.16.204"
DefaultS3Retries = 5
)
// SolrBackupSpec defines the desired state of SolrBackup
type SolrBackupSpec struct {
// A reference to the SolrCloud to create a backup for
SolrCloud string `json:"solrCloud"`
// The list of collections to backup. If empty, all collections in the cloud will be backed up.
// +optional
Collections []string `json:"collections,omitempty"`
// Persistence is the specification on how to persist the backup data.
Persistence PersistenceSource `json:"persistence"`
}
func (spec *SolrBackupSpec) withDefaults(backupName string) (changed bool) {
changed = spec.Persistence.withDefaults(backupName) || changed
return changed
}
// PersistenceSource defines the location and method of persisting the backup data.
// Exactly one member must be specified.
type PersistenceSource struct {
// Persist to an s3 compatible endpoint
// +optional
S3 *S3PersistenceSource `json:"S3,omitempty"`
// Persist to a volume
// +optional
Volume *VolumePersistenceSource `json:"volume,omitempty"`
}
func (spec *PersistenceSource) withDefaults(backupName string) (changed bool) {
if spec.Volume != nil {
changed = spec.Volume.withDefaults(backupName) || changed
}
if spec.S3 != nil {
changed = spec.S3.withDefaults(backupName) || changed
}
return changed
}
// S3PersistenceSource defines the specs for connecting to s3 for persistence
type S3PersistenceSource struct {
// The S3 compatible endpoint URL
// +optional
EndpointUrl string `json:"endpointUrl,omitempty"`
// The Default region to use with AWS.
// Can also be provided through a configFile in the secrets.
// Overridden by any endpointUrl value provided.
// +optional
Region string `json:"region,omitempty"`
// The S3 bucket to store/find the backup data
Bucket string `json:"bucket"`
// The key for the referenced tarred & zipped backup file
// Defaults to the name of the backup/restore + '.tgz'
// +optional
Key string `json:"key"`
// The number of retries to communicate with S3
// +optional
Retries *int32 `json:"retries,omitempty"`
// The secrets to use when configuring and authenticating s3 calls
Secrets S3Secrets `json:"secrets"`
// Image containing the AWS Cli
// +optional
AWSCliImage ContainerImage `json:"AWSCliImage,omitempty"`
}
func (spec *S3PersistenceSource) withDefaults(backupName string) (changed bool) {
changed = spec.AWSCliImage.withDefaults(DefaultAWSCliImageRepo, DefaultAWSCliImageVersion, DefaultPullPolicy) || changed
if spec.Key == "" {
spec.Key = backupName + ".tgz"
changed = true
} else if strings.HasPrefix(spec.Key, "/") {
spec.Key = strings.TrimPrefix(spec.Key, "/")
changed = true
}
if spec.Retries == nil {
retries := int32(DefaultS3Retries)
spec.Retries = &retries
changed = true
}
return changed
}
// S3Secrets describes the secrets provided for accessing s3.
type S3Secrets struct {
// The name of the secrets object to use
Name string `json:"fromSecret"`
// The key (within the provided secret) of an AWS Config file to use
// +optional
ConfigFile string `json:"configFile,omitempty"`
// The key (within the provided secret) of an AWS Credentials file to use
// +optional
CredentialsFile string `json:"credentialsFile,omitempty"`
// The key (within the provided secret) of the Access Key ID to use
// +optional
AccessKeyId string `json:"accessKeyId,omitempty"`
// The key (within the provided secret) of the Secret Access Key to use
// +optional
SecretAccessKey string `json:"secretAccessKey,omitempty"`
}
// UploadSpec defines the location and method of uploading the backup data
type VolumePersistenceSource struct {
// The volume for persistence
VolumeSource corev1.VolumeSource `json:"source"`
// The location of the persistence directory within the volume
// +optional
Path string `json:"path,omitempty"`
// The filename of the tarred & zipped backup file
// Defaults to the name of the backup/restore + '.tgz'
// +optional
Filename string `json:"filename"`
// BusyBox image for manipulating and moving data
// +optional
BusyBoxImage ContainerImage `json:"busyBoxImage,omitempty"`
}
func (spec *VolumePersistenceSource) withDefaults(backupName string) (changed bool) {
changed = spec.BusyBoxImage.withDefaults(DefaultBusyBoxImageRepo, DefaultBusyBoxImageVersion, DefaultPullPolicy) || changed
if spec.Path != "" && strings.HasPrefix(spec.Path, "/") {
spec.Path = strings.TrimPrefix(spec.Path, "/")
changed = true
}
if spec.Filename == "" {
spec.Filename = backupName + ".tgz"
changed = true
}
return changed
}
// SolrBackupStatus defines the observed state of SolrBackup
type SolrBackupStatus struct {
// Version of the Solr being backed up
SolrVersion string `json:"solrVersion"`
// The status of each collection's backup progress
// +optional
CollectionBackupStatuses []CollectionBackupStatus `json:"collectionBackupStatuses,omitempty"`
// Whether the backups are in progress of being persisted
PersistenceStatus BackupPersistenceStatus `json:"persistenceStatus"`
// Version of the Solr being backed up
// +optional
FinishTime *metav1.Time `json:"finishTimestamp,omitempty"`
// Whether the backup was successful
// +optional
Successful *bool `json:"successful,omitempty"`
// Whether the backup has finished
Finished bool `json:"finished,omitempty"`
}
// CollectionBackupStatus defines the progress of a Solr Collection's backup
type CollectionBackupStatus struct {
// Solr Collection name
Collection string `json:"collection"`
// Whether the collection is being backed up
// +optional
InProgress bool `json:"inProgress,omitempty"`
// Time that the collection backup started at
// +optional
StartTime *metav1.Time `json:"startTimestamp,omitempty"`
// The status of the asynchronous backup call to solr
// +optional
AsyncBackupStatus string `json:"asyncBackupStatus,omitempty"`
// Whether the backup has finished
Finished bool `json:"finished,omitempty"`
// Time that the collection backup finished at
// +optional
FinishTime *metav1.Time `json:"finishTimestamp,omitempty"`
// Whether the backup was successful
// +optional
Successful *bool `json:"successful,omitempty"`
}
// BackupPersistenceStatus defines the status of persisting Solr backup data
type BackupPersistenceStatus struct {
// Whether the collection is being backed up
// +optional
InProgress bool `json:"inProgress,omitempty"`
// Time that the collection backup started at
// +optional
StartTime *metav1.Time `json:"startTimestamp,omitempty"`
// Whether the persistence has finished
Finished bool `json:"finished,omitempty"`
// Time that the collection backup finished at
// +optional
FinishTime *metav1.Time `json:"finishTimestamp,omitempty"`
// Whether the backup was successful
// +optional
Successful *bool `json:"successful,omitempty"`
}
func (sb *SolrBackup) SharedLabels() map[string]string {
return sb.SharedLabelsWith(map[string]string{})
}
func (sb *SolrBackup) SharedLabelsWith(labels map[string]string) map[string]string {
newLabels := map[string]string{}
if labels != nil {
for k, v := range labels {
newLabels[k] = v
}
}
newLabels["solr-backup"] = sb.Name
return newLabels
}
// HeadlessServiceName returns the name of the headless service for the cloud
func (sb *SolrBackup) PersistenceJobName() string {
return fmt.Sprintf("%s-solr-backup-persistence", sb.GetName())
}
//+kubebuilder:object:root=true
//+kubebuilder:resource:scope=Namespaced
//+kubebuilder:storageversion
//+kubebuilder:categories=all
//+kubebuilder:subresource:status
//+kubebuilder:printcolumn:name="Cloud",type="string",JSONPath=".spec.solrCloud",description="Solr Cloud"
//+kubebuilder:printcolumn:name="Finished",type="boolean",JSONPath=".status.finished",description="Whether the backup has finished"
//+kubebuilder:printcolumn:name="Successful",type="boolean",JSONPath=".status.successful",description="Whether the backup was successful"
//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
// SolrBackup is the Schema for the solrbackups API
type SolrBackup struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec SolrBackupSpec `json:"spec,omitempty"`
Status SolrBackupStatus `json:"status,omitempty"`
}
// WithDefaults set default values when not defined in the spec.
func (sb *SolrBackup) WithDefaults() bool {
return sb.Spec.withDefaults(sb.Name)
}
//+kubebuilder:object:root=true
// SolrBackupList contains a list of SolrBackup
type SolrBackupList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []SolrBackup `json:"items"`
}
func init() {
SchemeBuilder.Register(&SolrBackup{}, &SolrBackupList{})
}