2021-07-14 09:15:21 +00:00
|
|
|
package cli
|
|
|
|
|
|
|
|
import (
|
2021-10-12 02:32:14 +00:00
|
|
|
"context"
|
2021-07-14 09:15:21 +00:00
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"strconv"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
portainer "github.com/portainer/portainer/api"
|
2021-12-01 00:18:57 +00:00
|
|
|
"github.com/portainer/portainer/api/internal/registryutils"
|
2021-07-14 09:15:21 +00:00
|
|
|
v1 "k8s.io/api/core/v1"
|
|
|
|
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
secretDockerConfigKey = ".dockerconfigjson"
|
2022-01-17 05:53:32 +00:00
|
|
|
labelRegistryType = "io.portainer.kubernetes.registry.type"
|
|
|
|
annotationRegistryID = "portainer.io/registry.id"
|
2021-07-14 09:15:21 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
dockerConfig struct {
|
|
|
|
Auths map[string]registryDockerConfig `json:"auths"`
|
|
|
|
}
|
|
|
|
|
|
|
|
registryDockerConfig struct {
|
|
|
|
Username string `json:"username"`
|
|
|
|
Password string `json:"password"`
|
|
|
|
Email string `json:"email"`
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
func (kcl *KubeClient) DeleteRegistrySecret(registry *portainer.Registry, namespace string) error {
|
2021-10-12 02:32:14 +00:00
|
|
|
err := kcl.cli.CoreV1().Secrets(namespace).Delete(context.TODO(), registrySecretName(registry), metav1.DeleteOptions{})
|
2021-07-14 09:15:21 +00:00
|
|
|
if err != nil && !k8serrors.IsNotFound(err) {
|
|
|
|
return errors.Wrap(err, "failed removing secret")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-12-01 00:18:57 +00:00
|
|
|
func (kcl *KubeClient) CreateRegistrySecret(registry *portainer.Registry, namespace string) (err error) {
|
|
|
|
username, password, err := registryutils.GetRegEffectiveCredential(registry)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-07-14 09:15:21 +00:00
|
|
|
config := dockerConfig{
|
|
|
|
Auths: map[string]registryDockerConfig{
|
|
|
|
registry.URL: {
|
2021-12-01 00:18:57 +00:00
|
|
|
Username: username,
|
|
|
|
Password: password,
|
2021-07-14 09:15:21 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
configByte, err := json.Marshal(config)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "failed marshal config")
|
|
|
|
}
|
|
|
|
|
|
|
|
secret := &v1.Secret{
|
|
|
|
TypeMeta: metav1.TypeMeta{},
|
|
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
|
|
Name: registrySecretName(registry),
|
2021-12-01 00:18:57 +00:00
|
|
|
Labels: map[string]string{
|
|
|
|
labelRegistryType: strconv.Itoa(int(registry.Type)),
|
|
|
|
},
|
2021-07-14 09:15:21 +00:00
|
|
|
Annotations: map[string]string{
|
2021-12-01 00:18:57 +00:00
|
|
|
annotationRegistryID: strconv.Itoa(int(registry.ID)),
|
2021-07-14 09:15:21 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
Data: map[string][]byte{
|
|
|
|
secretDockerConfigKey: configByte,
|
|
|
|
},
|
|
|
|
Type: v1.SecretTypeDockerConfigJson,
|
|
|
|
}
|
|
|
|
|
2021-10-12 02:32:14 +00:00
|
|
|
_, err = kcl.cli.CoreV1().Secrets(namespace).Create(context.TODO(), secret, metav1.CreateOptions{})
|
2021-07-14 09:15:21 +00:00
|
|
|
if err != nil && !k8serrors.IsAlreadyExists(err) {
|
|
|
|
return errors.Wrap(err, "failed saving secret")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cli *KubeClient) IsRegistrySecret(namespace, secretName string) (bool, error) {
|
2021-10-12 02:32:14 +00:00
|
|
|
secret, err := cli.cli.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, metav1.GetOptions{})
|
2021-07-14 09:15:21 +00:00
|
|
|
if err != nil {
|
|
|
|
if k8serrors.IsNotFound(err) {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
isSecret := secret.Type == v1.SecretTypeDockerConfigJson
|
|
|
|
|
|
|
|
return isSecret, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func registrySecretName(registry *portainer.Registry) string {
|
|
|
|
return fmt.Sprintf("registry-%d", registry.ID)
|
|
|
|
}
|