/*
Copyright © The ESO Authors

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

    https://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 (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// GrafanaSpec controls the behavior of the grafana generator.
type GrafanaSpec struct {
	// URL is the URL of the Grafana instance.
	URL string `json:"url"`
	// Auth is the authentication configuration to authenticate
	// against the Grafana instance.
	Auth GrafanaAuth `json:"auth"`
	// ServiceAccount is the configuration for the service account that
	// is supposed to be generated by the generator.
	ServiceAccount GrafanaServiceAccount `json:"serviceAccount"`
}

// GrafanaServiceAccount defines the configuration for a Grafana service account to be created.
type GrafanaServiceAccount struct {
	// Name is the name of the service account that will be created by ESO.
	Name string `json:"name"`
	// Role is the role of the service account.
	// See here for the documentation on basic roles offered by Grafana:
	// https://grafana.com/docs/grafana/latest/administration/roles-and-permissions/access-control/rbac-fixed-basic-role-definitions/
	Role string `json:"role"`
	// SecondsToLive is the number of seconds before the generated service account token will expire.
	// Some Grafana deployments (e.g. AWS Managed Grafana) require this value to be set.
	// +optional
	// +kubebuilder:validation:Minimum=1
	SecondsToLive *int64 `json:"secondsToLive,omitempty"`
}

// GrafanaAuth defines the authentication methods for connecting to a Grafana instance.
type GrafanaAuth struct {
	// A service account token used to authenticate against the Grafana instance.
	// Note: you need a token which has elevated permissions to create service accounts.
	// See here for the documentation on basic roles offered by Grafana:
	// https://grafana.com/docs/grafana/latest/administration/roles-and-permissions/access-control/rbac-fixed-basic-role-definitions/
	// +optional
	Token *SecretKeySelector `json:"token,omitempty"`
	// Basic auth credentials used to authenticate against the Grafana instance.
	// Note: you need a token which has elevated permissions to create service accounts.
	// See here for the documentation on basic roles offered by Grafana:
	// https://grafana.com/docs/grafana/latest/administration/roles-and-permissions/access-control/rbac-fixed-basic-role-definitions/
	// +optional
	Basic *GrafanaBasicAuth `json:"basic,omitempty"`
}

// GrafanaBasicAuth defines the credentials for basic authentication with Grafana.
type GrafanaBasicAuth struct {
	// A basic auth username used to authenticate against the Grafana instance.
	Username string `json:"username"`
	// A basic auth password used to authenticate against the Grafana instance.
	Password SecretKeySelector `json:"password"`
}

// GrafanaServiceAccountTokenState is the state type produced by the Grafana generator.
// It contains the service account ID, login and token ID which is enough to
// identify the service account.
type GrafanaServiceAccountTokenState struct {
	ServiceAccount GrafanaStateServiceAccount `json:"serviceAccount"`
}

// GrafanaStateServiceAccount contains the service account ID, login and token ID.
type GrafanaStateServiceAccount struct {
	ServiceAccountID      *int64  `json:"id"`
	ServiceAccountLogin   *string `json:"login"`
	ServiceAccountTokenID *int64  `json:"tokenID"`
}

// Grafana represents a generator for Grafana service account tokens.
// +kubebuilder:object:root=true
// +kubebuilder:storageversion
// +kubebuilder:subresource:status
// +kubebuilder:metadata:labels="external-secrets.io/component=controller"
// +kubebuilder:resource:scope=Namespaced,categories={external-secrets, external-secrets-generators}
type Grafana struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec GrafanaSpec `json:"spec,omitempty"`
}

// +kubebuilder:object:root=true

// GrafanaList contains a list of Grafana Generator resources.
type GrafanaList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []Grafana `json:"items"`
}
