220 lines
5.5 KiB
Go
220 lines
5.5 KiB
Go
package minio
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"oc-datacenter/conf"
|
|
|
|
oclib "cloud.o-forge.io/core/oc-lib"
|
|
"github.com/minio/madmin-go/v4"
|
|
"github.com/minio/minio-go/v7"
|
|
"github.com/minio/minio-go/v7/pkg/credentials"
|
|
v1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/client-go/kubernetes"
|
|
"k8s.io/client-go/rest"
|
|
|
|
"github.com/necmettindev/randomstring"
|
|
)
|
|
|
|
type MinioService struct {
|
|
Url string
|
|
RootKey string
|
|
RootSecret string
|
|
MinioAdminClient *madmin.AdminClient
|
|
}
|
|
|
|
type StatementEntry struct {
|
|
Effect string `json:"Effect"`
|
|
Action []string `json:"Action"`
|
|
Resource string `json:"Resource"`
|
|
}
|
|
|
|
type PolicyDocument struct {
|
|
Version string `json:"Version"`
|
|
Statement []StatementEntry `json:"Statement"`
|
|
}
|
|
|
|
func NewMinioService(url string) *MinioService {
|
|
return &MinioService{
|
|
Url: url,
|
|
RootKey: conf.GetConfig().MinioRootKey,
|
|
RootSecret: conf.GetConfig().MinioRootSecret,
|
|
}
|
|
}
|
|
|
|
func (m *MinioService) CreateClient() error {
|
|
cred := credentials.NewStaticV4(m.RootKey, m.RootSecret, "")
|
|
cli, err := madmin.NewWithOptions(m.Url, &madmin.Options{Creds: cred, Secure: false}) // Maybe in the future we should use the secure option ?
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
m.MinioAdminClient = cli
|
|
return nil
|
|
}
|
|
|
|
func (m *MinioService) CreateCredentials(executionId string) (string, string, error) {
|
|
|
|
policy := PolicyDocument{
|
|
Version: "2012-10-17",
|
|
Statement: []StatementEntry{
|
|
{
|
|
Effect: "Allow",
|
|
Action: []string{"s3:GetObject", "s3:PutObject"},
|
|
Resource: "arn:aws:s3:::" + executionId + "/*",
|
|
},
|
|
},
|
|
}
|
|
|
|
p, err := json.Marshal(policy)
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
randAccess, randSecret := getRandomCreds()
|
|
|
|
req := madmin.AddServiceAccountReq{
|
|
Policy: p,
|
|
TargetUser: m.RootKey,
|
|
AccessKey: randAccess,
|
|
SecretKey: randSecret,
|
|
}
|
|
|
|
res, err := m.MinioAdminClient.AddServiceAccount(context.Background(), req)
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
return res.AccessKey, res.SecretKey, nil
|
|
|
|
}
|
|
|
|
func getRandomCreds() (string, string) {
|
|
opts := randomstring.GenerationOptions{
|
|
Length: 20,
|
|
}
|
|
|
|
a, _ := randomstring.GenerateString(opts)
|
|
|
|
opts.Length = 40
|
|
s, _ := randomstring.GenerateString(opts)
|
|
|
|
return a, s
|
|
|
|
}
|
|
func (m *MinioService) CreateMinioConfigMap(minioID string, executionId string, url string) error {
|
|
config, err := rest.InClusterConfig()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
clientset, err := kubernetes.NewForConfig(config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
configMap := &v1.ConfigMap{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: minioID + "artifact-repository",
|
|
Namespace: executionId,
|
|
},
|
|
Data: map[string]string{
|
|
minioID + "s3-local": fmt.Sprintf(`
|
|
s3:
|
|
bucket: %s
|
|
endpoint: %s
|
|
insecure: true
|
|
accessKeySecret:
|
|
name: %s-secret-s3
|
|
key: accesskey
|
|
secretKeySecret:
|
|
name: %s-secret-s3
|
|
key: secretkey
|
|
`, minioID+"-"+executionId, url, minioID, minioID),
|
|
},
|
|
}
|
|
|
|
existing, err := clientset.CoreV1().
|
|
ConfigMaps(executionId).
|
|
Get(context.Background(), minioID+"artifact-repository", metav1.GetOptions{})
|
|
|
|
if err == nil {
|
|
// Update
|
|
existing.Data = configMap.Data
|
|
_, err = clientset.CoreV1().
|
|
ConfigMaps(executionId).
|
|
Update(context.Background(), existing, metav1.UpdateOptions{})
|
|
} else {
|
|
// Create
|
|
_, err = clientset.CoreV1().
|
|
ConfigMaps(executionId).
|
|
Create(context.Background(), configMap, metav1.CreateOptions{})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *MinioService) CreateBucket(minioID string, executionId string) error {
|
|
l := oclib.GetLogger()
|
|
cred := credentials.NewStaticV4(m.RootKey, m.RootSecret, "")
|
|
client, err := minio.New(m.Url, &minio.Options{
|
|
Creds: cred,
|
|
Secure: false,
|
|
})
|
|
if err != nil {
|
|
l.Error().Msg("Error when creating the minio client for the data plane")
|
|
return err
|
|
}
|
|
|
|
err = client.MakeBucket(context.Background(), minioID+"-"+executionId, minio.MakeBucketOptions{})
|
|
if err != nil {
|
|
l.Error().Msg("Error when creating the bucket for namespace " + executionId)
|
|
return err
|
|
}
|
|
|
|
l.Info().Msg("Created the bucket " + minioID + "-" + executionId + " on " + m.Url + " minio")
|
|
return nil
|
|
}
|
|
|
|
// DeleteCredentials revokes a scoped Minio service account by its access key.
|
|
func (m *MinioService) DeleteCredentials(accessKey string) error {
|
|
if err := m.MinioAdminClient.DeleteServiceAccount(context.Background(), accessKey); err != nil {
|
|
return fmt.Errorf("DeleteCredentials: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// DeleteBucket removes the execution bucket from Minio.
|
|
func (m *MinioService) DeleteBucket(minioID, executionId string) error {
|
|
l := oclib.GetLogger()
|
|
cred := credentials.NewStaticV4(m.RootKey, m.RootSecret, "")
|
|
client, err := minio.New(m.Url, &minio.Options{Creds: cred, Secure: false})
|
|
if err != nil {
|
|
l.Error().Msg("Error when creating minio client for bucket deletion")
|
|
return err
|
|
}
|
|
bucketName := minioID + "-" + executionId
|
|
if err := client.RemoveBucket(context.Background(), bucketName); err != nil {
|
|
l.Error().Msg("Error when deleting bucket " + bucketName)
|
|
return err
|
|
}
|
|
l.Info().Msg("Deleted bucket " + bucketName + " on " + m.Url)
|
|
return nil
|
|
}
|
|
|
|
// DeleteMinioConfigMap removes the artifact-repository ConfigMap from the execution namespace.
|
|
func (m *MinioService) DeleteMinioConfigMap(minioID, executionId string) error {
|
|
cfg, err := rest.InClusterConfig()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
clientset, err := kubernetes.NewForConfig(cfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return clientset.CoreV1().ConfigMaps(executionId).Delete(
|
|
context.Background(), minioID+"artifact-repository", metav1.DeleteOptions{},
|
|
)
|
|
}
|