github.com/metaprov/modela-operator@v0.0.0-20240118193048-f378be8b74d2/api/v1alpha1/modela_types.go (about) 1 /* 2 Copyright 2022. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package v1alpha1 18 19 import ( 20 "encoding/json" 21 "errors" 22 v1 "k8s.io/api/core/v1" 23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 "k8s.io/apimachinery/pkg/runtime" 25 ) 26 27 // The current phase of a Modela installation 28 type ModelaPhase string 29 30 const ( 31 ModelaPhaseInstallingVault = "InstallingVault" 32 ModelaPhaseInstallingCertManager = "InstallingCertManager" 33 ModelaPhaseInstallingObjectStorage = "InstallingObjectStorage" 34 ModelaPhaseInstallingOnlineStore = "InstallingOnlineStore" 35 ModelaPhaseInstallingNginx = "InstallingNginx" 36 ModelaPhaseInstallingPrometheus = "InstallingPrometheus" 37 ModelaPhaseInstallingGrafana = "InstallingGrafana" 38 ModelaPhaseInstallingLoki = "InstallingLoki" 39 ModelaPhaseInstallingDatabase = "InstallingSystemDatabase" 40 ModelaPhaseInstallingModela = "InstallingModela" 41 ModelaPhaseInstallingTenant = "InstallingTenant" 42 ModelaPhaseReady = "Ready" 43 ModelaPhaseUninstalling = "UninstallingComponent" 44 ModelaPhaseFailed = "Failed" 45 ) 46 47 var ( 48 ComponentNotInstalledByModelaError = errors.New("component not installed by Modela Operator") 49 ComponentMissingResourcesError = errors.New("component missing resources") 50 ) 51 52 // ConditionStatus defines conditions of resources 53 type ConditionStatus string 54 55 // These are valid condition statuses. "ConditionTrue" means a resource is in the condition; 56 // "ConditionFalse" means a resource is not in the condition; "ConditionUnknown" means kubernetes 57 // can't decide if a resource is in the condition or not. In the future, we could add other 58 // intermediate conditions, e.g. ConditionDegraded 59 const ( 60 ConditionTrue ConditionStatus = "True" 61 ConditionFalse ConditionStatus = "False" 62 ConditionUnknown ConditionStatus = "Unknown" 63 ) 64 65 // ClusterConditionType is of string type 66 type ModelaConditionType string 67 68 // ClusterCondition describes the state of a cluster object at a certain point 69 type ModelaCondition struct { 70 // Type of the condition. 71 Type ModelaConditionType `json:"type,omitempty"` 72 // Status of the condition, one of True, False, Unknown. 73 Status ConditionStatus `json:"status,omitempty"` 74 // Last time the condition transitioned from one status to another. 75 LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty"` 76 // The reason for the condition's last transition. 77 Reason string `json:"reason,omitempty"` 78 // A human-readable message indicating details about the transition. 79 Message string `json:"message,omitempty"` 80 } 81 82 // Unstructured values for rendering Helm Charts 83 // +k8s:deepcopy-gen=false 84 type ChartValues struct { 85 // Object is a JSON compatible map with string, float, int, bool, []interface{}, or 86 // map[string]interface{} children. 87 Object map[string]interface{} `json:"-"` 88 } 89 90 // MarshalJSON ensures that the unstructured object produces proper 91 // JSON when passed to Go's standard JSON library. 92 func (u *ChartValues) MarshalJSON() ([]byte, error) { 93 return json.Marshal(u.Object) 94 } 95 96 // UnmarshalJSON ensures that the unstructured object properly decodes 97 // JSON when passed to Go's standard JSON library. 98 func (u *ChartValues) UnmarshalJSON(data []byte) error { 99 m := make(map[string]interface{}) 100 if err := json.Unmarshal(data, &m); err != nil { 101 return err 102 } 103 104 u.Object = m 105 106 return nil 107 } 108 109 // Declaring this here prevents it from being generated. 110 func (u *ChartValues) DeepCopyInto(out *ChartValues) { 111 out.Object = runtime.DeepCopyJSON(u.Object) 112 } 113 114 // IngressSpec defines the configuration for Modela to be exposed externally through Ingress resources. 115 // The Kubernetes Ingress Class annotation (kubernetes.io/ingress.class) must be defined in the parent Modela resource 116 // for Ingress resources to be created. 117 type IngressSpec struct { 118 // Enabled indicates if Ingress resources will be created to expose the Modela API gateway and frontend. 119 // +kubebuilder:default:=false 120 Enabled bool `json:"enabled,omitempty"` 121 // Hostname specifies the host domain which will be used as the hostname for rules in Ingress resources managed 122 // by the Modela operator. By default, the hostname will default to a localhost alias. 123 // +kubebuilder:validation:Optional 124 // +kubebuilder:default:="localhost" 125 Hostname *string `json:"hostname,omitempty"` 126 } 127 128 // NginxSpec defines the configuration to install and configure the Nginx ingress controller 129 type NginxSpec struct { 130 // Indicates if Nginx should be installed 131 // +kubebuilder:default:=true 132 // +kubebuilder:validation:Optional 133 Install bool `json:"install"` 134 // ChartValues is the set of Helm values that is used to render the Nginx Ingress Chart. 135 // Values are determined from https://artifacthub.io/packages/helm/ingress-nginx/ingress-nginx 136 // +kubebuilder:pruning:PreserveUnknownFields 137 // +kubebuilder:validation:Optional 138 Values ChartValues `json:"values,omitempty"` 139 } 140 141 // NodePortSpec defines the configuration to expose Modela through Node Port services 142 type NodePortSpec struct { 143 // Indicates if Node Port services will be created 144 // +kubebuilder:default:=false 145 Enabled bool `json:"enabled,omitempty"` 146 // The port which Modela will be exposed through. The port, and the two ports above it, must be available. 147 // NodePort services will be allocated for the API Gateway, Proxy, and Frontend 148 // +kubebuilder:default:=30000 149 // +kubebuilder:validation:Minimum=30000 150 // +kubebuilder:validation:Maximum=32766 151 // +kubebuilder:validation:ExclusiveMaximum=true 152 Port int32 `json:"port,omitempty"` 153 // A map of labels that will select which Node to use when determining an external IP for the cluster. 154 // The external IP of the Node will be used to configure the frontend. 155 NodeSelector map[string]string `json:"nodeSelector,omitempty"` 156 } 157 158 // NetworkSpec defines the configuration for Modela to be exposed through Kubernetes networking features 159 type NetworkSpec struct { 160 // The configuration to create NodePort services 161 // +kubebuilder:validation:Optional 162 NodePort *NodePortSpec `json:"nodePort,omitempty"` 163 // The configuration to create Ingress resources 164 // +kubebuilder:validation:Optional 165 Ingress *IngressSpec `json:"ingress,omitempty"` 166 // The configuration to install Nginx 167 // +kubebuilder:validation:Optional 168 Nginx *NginxSpec `json:"nginx,omitempty"` 169 } 170 171 type ApiGatewaySpec struct { 172 // Define the number of API Gateway replicas 173 // +kubebuilder:default:=0 174 // +kubebuilder:validation:Optional 175 Replicas *int32 `json:"replicas,omitempty"` 176 177 // +kubebuilder:validation:Optional 178 // Resources specifies resource requests and limits for the data plane deployment. 179 // Default values: 100m CPU request, 200m CPU limit, 128Mi memory request, 256Mi memory limit. 180 Resources *v1.ResourceRequirements `json:"resources,omitempty"` 181 } 182 183 type ControlPlaneSpec struct { 184 // The number of Control Plane replicas 185 // +kubebuilder:default:=0 186 // +kubebuilder:validation:Optional 187 Replicas *int32 `json:"replicas,omitempty"` 188 189 // Resources specifies resource requests and limits for the control plane deployment. 190 // Default values: 256m CPU request, 512m CPU limit, 256Mi memory request, 512Mi memory limit. 191 Resources *v1.ResourceRequirements `json:"resources,omitempty"` 192 } 193 194 type DataPlaneSpec struct { 195 // The number of Data Plane replicas 196 // +kubebuilder:default:=0 197 // +kubebuilder:validation:Optional 198 Replicas *int32 `json:"replicas,omitempty"` 199 200 // Resources specifies resource requests and limits for the data plane deployment. 201 // Default values: 100m CPU request, 200m CPU limit, 256Mi memory request, 512Mi memory limit. 202 Resources *v1.ResourceRequirements `json:"resources,omitempty"` 203 } 204 205 type CertManagerSpec struct { 206 // Indicates if cert-manager should be installed. 207 // +kubebuilder:default:=true 208 // +kubebuilder:validation:Optional 209 Install bool `json:"install"` 210 211 // ChartValues is the set of Helm values that is used to render the Cert Manager Chart. 212 // Values are determined from https://artifacthub.io/packages/helm/cert-manager/cert-manager. 213 // +kubebuilder:pruning:PreserveUnknownFields 214 // +kubebuilder:validation:Optional 215 Values ChartValues `json:"values,omitempty"` 216 } 217 218 type VaultSpec struct { 219 // Indicates if Vault should be installed. Enabling installation will initialize Vault on the modela-system 220 // namespace and configure it with the appropriate secret engine and policies. This option is not recommended 221 // for production environments as the root token and vault keys will be stored inside Kubernetes secrets. 222 // When installed this way, the Modela Operator will automatically unseal the Vault when necessary. 223 // +kubebuilder:default:=true 224 // +kubebuilder:validation:Optional 225 Install bool `json:"install"` 226 227 // MountPath specifies the path where secrets consumed by Modela will be stored. 228 // +kubebuilder:default:="modela/secrets" 229 MountPath string `json:"mountPath,omitempty"` 230 231 // VaultAddress specifies the address for an external Vault server. If specified, the Vault server 232 // must be configured with a KVv2 secret engine mounted at MountPath. It must also be configured to 233 // authorize the modela-operator-controller-manager ServiceAccount with read/write permissions 234 // +kubebuilder:validation:Optional 235 VaultAddress *string `json:"vaultAddress,omitempty"` 236 237 // ChartValues is the set of Helm values that are used to render the Vault Chart. 238 // +kubebuilder:pruning:PreserveUnknownFields 239 // +kubebuilder:validation:Optional 240 Values ChartValues `json:"values,omitempty"` 241 } 242 243 type ObjectStorageSpec struct { 244 // Indicates if Minio should be installed. 245 // +kubebuilder:default:=true 246 // +kubebuilder:validation:Optional 247 Install bool `json:"install"` 248 249 // ChartValues is the set of Helm values that is used to render the Minio Chart. 250 Values ChartValues `json:"values,omitempty"` 251 } 252 253 type DatabaseSpec struct { 254 // ChartValues is the set of Helm values that is used to render the Postgres Chart. 255 // +kubebuilder:pruning:PreserveUnknownFields 256 // +kubebuilder:validation:Optional 257 PostgresValues ChartValues `json:"postgresValues,omitempty"` 258 259 // InstallPgvector indicates if Postgres will be installed with the pgvector vector database extension. 260 // Pgvector is required to use Postgres as a vector database with the Modela LLM RAG engine. 261 // +kubebuilder:default:=true 262 // +kubebuilder:validation:Optional 263 InstallPgvector bool `json:"installPgvector"` 264 265 // InstallMongoDB indicates if MongoDB will be installed. 266 // MongoDB is a required component of the Modela LLM RAG engine. 267 // +kubebuilder:default:=true 268 // +kubebuilder:validation:Optional 269 InstallMongoDB bool `json:"installMongoDB,omitempty"` 270 271 // ChartValues is the set of Helm values that is used to render the MongoDB Chart. 272 // +kubebuilder:pruning:PreserveUnknownFields 273 // +kubebuilder:validation:Optional 274 MongoDBValues ChartValues `json:"mongoDBValues,omitempty"` 275 } 276 277 type OnlineStoreSpec struct { 278 // Indicates if Redis should be installed as part of the built-in online store. 279 // +kubebuilder:default:=true 280 // +kubebuilder:validation:Optional 281 Install bool `json:"install,omitempty"` 282 283 // ChartValues is the set of Helm values that is used to render the Redis Chart. 284 // +kubebuilder:pruning:PreserveUnknownFields 285 // +kubebuilder:validation:Optional 286 Values ChartValues `json:"values,omitempty"` 287 } 288 289 type ObservabilitySpec struct { 290 // Prometheus indicates if the Prometheus Helm Chart will be installed 291 //+kubebuilder:validation:Optional 292 Prometheus bool `json:"installPrometheus,omitempty"` 293 // ChartValues is the set of Helm values that is used to render the Prometheus Chart. 294 // Values are determined from https://artifacthub.io/packages/helm/prometheus-community/prometheus 295 // +kubebuilder:pruning:PreserveUnknownFields 296 // +kubebuilder:validation:Optional 297 PrometheusValues ChartValues `json:"prometheusValues,omitempty"` 298 299 // Loki indicates if the Loki Helm Chart will be installed 300 //+kubebuilder:validation:Optional 301 Loki bool `json:"installLoki,omitempty"` 302 // ChartValues is the set of Helm values that is used to render the Loki Chart. 303 // Values are determined from https://artifacthub.io/packages/helm/grafana/loki 304 // +kubebuilder:pruning:PreserveUnknownFields 305 // +kubebuilder:validation:Optional 306 LokiValues ChartValues `json:"lokiValues,omitempty"` 307 308 // Grafana indicates if the Grafana Helm Chart will be installed 309 //+kubebuilder:validation:Optional 310 Grafana bool `json:"installGrafana,omitempty"` 311 // ChartValues is the set of Helm values that is used to render the Grafana Chart. 312 // Values are determined from https://artifacthub.io/packages/helm/grafana/grafana 313 // +kubebuilder:pruning:PreserveUnknownFields 314 // +kubebuilder:validation:Optional 315 GrafanaValues ChartValues `json:"grafanaValues,omitempty"` 316 } 317 318 type ModelaLicenseSpec struct { 319 //+kubebuilder:validation:Optional 320 LicenseKey *string `json:"licenseKey,omitempty"` 321 322 // If LinkLicense is enabled, the Modela Operator will open a linking session through modela.ai which a 323 // system administrator can use to log in to their modela.ai account and link their license. The URL which 324 // must be opened by the administrator will be stored in the status of the Modela resource. 325 LinkLicense *bool `json:"linkLicense,omitempty"` 326 } 327 328 type TenantSpec struct { 329 // The name of the Tenant. This will determine the name of the namespace containing the Tenant's resources. 330 // +kubebuilder:validation:Required 331 Name string `json:"name,omitempty"` 332 333 // The password for the default admin account (with the username "admin"). If empty, then the 334 // Modela Operator will set the password to "default". Setting a secure password is highly recommended. 335 // +kubebuilder:validation:Optional 336 AdminPassword *string `json:"adminPassword,omitempty"` 337 } 338 339 // ModelaSpec defines the desired state of Modela 340 type ModelaSpec struct { 341 // Distribution denotes the desired version of Modela. This version will determine the 342 // Docker image tags for all Modela images provided by Metaprov 343 // +kubebuilder:default:="develop" 344 // +kubebuilder:validation:Required 345 Distribution string `json:"distribution"` 346 347 // Observability specifies the configuration to install monitoring tools (Prometheus, Loki, Grafana) 348 Observability ObservabilitySpec `json:"observability,omitempty"` 349 350 // Network specifies the configuration to make Modela accessible through networking features 351 Network NetworkSpec `json:"network,omitempty"` 352 353 // License specifies the license information 354 // that will be applied to the installation of Modela 355 License ModelaLicenseSpec `json:"license,omitempty"` 356 357 // Tenants contains the collection of tenants that will be installed 358 //+kubebuilder:validation:Optional 359 Tenants []*TenantSpec `json:"tenants,omitempty"` 360 361 //+kubebuilder:validation:Optional 362 CertManager CertManagerSpec `json:"certManager,omitempty"` 363 364 //+kubebuilder:validation:Optional 365 ObjectStore ObjectStorageSpec `json:"objectStore,omitempty"` 366 367 //+kubebuilder:validation:Optional 368 Database DatabaseSpec `json:"database,omitempty"` 369 370 //+kubebuilder:validation:Optional 371 OnlineStore OnlineStoreSpec `json:"onlineStore,omitempty"` 372 373 //+kubebuilder:validation:Optional 374 ControlPlane ControlPlaneSpec `json:"controlPlane,omitempty"` 375 376 //+kubebuilder:validation:Optional 377 DataPlane DataPlaneSpec `json:"dataPlane,omitempty"` 378 379 //+kubebuilder:validation:Optional 380 ApiGateway ApiGatewaySpec `json:"apiGateway,omitempty"` 381 382 //+kubebuilder:validation:Optional 383 Vault VaultSpec `json:"vault,omitempty"` 384 } 385 386 // ModelaStatus defines the observed state of Modela 387 type ModelaStatus struct { 388 // InstalledVersion denotes the live image tags of all Modela images 389 InstalledVersion string `json:"installedVersion,omitempty"` 390 391 // Tenants contains the names of installed Tenant 392 Tenants []string `json:"installedTenants,omitempty"` 393 394 // LicenseToken contains the reference to the license token generated by the license linking process, which 395 // can be used to fetch the active license of a modela.ai 396 LicenseToken *v1.ObjectReference `json:"licenseTokenRef,omitempty"` 397 398 // LinkLicenseUrl contains the URL which the system administrator must open in order to link their 399 // https://modela.ai account to the Modela Operator. Once linked, the Modela Operator will automatically 400 // fetch the license of their account in the case that will it will expire. 401 LinkLicenseUrl *string `json:"linkLicenseUrl,omitempty"` 402 403 Phase ModelaPhase `json:"phase,omitempty"` 404 405 // The Modela resource controller will update FailureMessage with an error message in the case of a failure 406 FailureMessage *string `json:"failureMessage,omitempty"` 407 408 // The last time the Modela resource was updated 409 //+kubebuilder:validation:Optional 410 LastUpdated *metav1.Time `json:"lastUpdated,omitempty"` 411 412 // +patchMergeKey=type 413 // +patchStrategy=merge 414 // +kubebuilder:validation:Optional 415 Conditions []ModelaCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,8,rep,name=conditions"` 416 } 417 418 // Modela defines the configuration of the Modela operator 419 // +kubebuilder:object:root=true 420 // +kubebuilder:subresource:status 421 // +kubebuilder:resource:path=modelas,singular=modela,shortName="md",categories={data,modela,all} 422 type Modela struct { 423 metav1.TypeMeta `json:",inline"` 424 metav1.ObjectMeta `json:"metadata,omitempty"` 425 426 Spec ModelaSpec `json:"spec,omitempty"` 427 Status ModelaStatus `json:"status,omitempty"` 428 } 429 430 // ModelaList contains a list of Modela 431 // +kubebuilder:object:root=true 432 type ModelaList struct { 433 metav1.TypeMeta `json:",inline"` 434 metav1.ListMeta `json:"metadata,omitempty"` 435 Items []Modela `json:"items"` 436 } 437 438 func init() { 439 SchemeBuilder.Register(&Modela{}, &ModelaList{}) 440 }