mirror of
https://github.com/alibaba/higress.git
synced 2026-02-28 14:40:50 +08:00
248 lines
7.6 KiB
Go
248 lines
7.6 KiB
Go
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
|
//
|
|
// 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
|
|
//
|
|
// 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 installer
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/alibaba/higress/hgctl/pkg/helm"
|
|
"github.com/alibaba/higress/hgctl/pkg/kubernetes"
|
|
"github.com/alibaba/higress/hgctl/pkg/util"
|
|
corev1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/api/errors"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
)
|
|
|
|
const (
|
|
ProfileConfigmapKey = "profile"
|
|
ProfileConfigmapName = "higress-profile"
|
|
ProfileConfigmapAnnotation = "higress.io/install"
|
|
ProfileFilePrefix = "install"
|
|
)
|
|
|
|
type ProfileContext struct {
|
|
Profile *helm.Profile
|
|
SourceType string
|
|
Namespace string
|
|
PathOrName string
|
|
Install helm.InstallMode
|
|
HigressVersion string
|
|
}
|
|
|
|
type ProfileStore interface {
|
|
Save(profile *helm.Profile) (string, error)
|
|
List() ([]*ProfileContext, error)
|
|
Delete(profile *helm.Profile) (string, error)
|
|
}
|
|
|
|
type FileDirProfileStore struct {
|
|
profilesPath string
|
|
}
|
|
|
|
func (f *FileDirProfileStore) Save(profile *helm.Profile) (string, error) {
|
|
namespace := profile.Global.Namespace
|
|
install := profile.Global.Install
|
|
var profileName = ""
|
|
if install == helm.InstallK8s || install == helm.InstallLocalK8s {
|
|
profileName = filepath.Join(f.profilesPath, fmt.Sprintf("%s-%s.yaml", ProfileFilePrefix, namespace))
|
|
} else {
|
|
profileName = filepath.Join(f.profilesPath, fmt.Sprintf("%s-%s.yaml", ProfileFilePrefix, install))
|
|
}
|
|
if err := util.WriteFileString(profileName, util.ToYAML(profile), 0o644); err != nil {
|
|
return "", err
|
|
}
|
|
return profileName, nil
|
|
}
|
|
|
|
func (f *FileDirProfileStore) List() ([]*ProfileContext, error) {
|
|
profileContexts := make([]*ProfileContext, 0)
|
|
dir, err := os.ReadDir(f.profilesPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, file := range dir {
|
|
if !strings.HasSuffix(file.Name(), ".yaml") {
|
|
continue
|
|
}
|
|
if file.IsDir() {
|
|
continue
|
|
}
|
|
fileName := filepath.Join(f.profilesPath, file.Name())
|
|
content, err2 := os.ReadFile(fileName)
|
|
if err2 != nil {
|
|
continue
|
|
}
|
|
profile, err3 := helm.UnmarshalProfile(string(content))
|
|
if err3 != nil {
|
|
continue
|
|
}
|
|
profileContext := &ProfileContext{
|
|
Profile: profile,
|
|
Namespace: profile.Global.Namespace,
|
|
Install: profile.Global.Install,
|
|
HigressVersion: profile.HigressVersion,
|
|
SourceType: "file",
|
|
PathOrName: fileName,
|
|
}
|
|
profileContexts = append(profileContexts, profileContext)
|
|
}
|
|
return profileContexts, nil
|
|
}
|
|
|
|
func (f *FileDirProfileStore) Delete(profile *helm.Profile) (string, error) {
|
|
namespace := profile.Global.Namespace
|
|
install := profile.Global.Install
|
|
var profileName = ""
|
|
if install == helm.InstallK8s || install == helm.InstallLocalK8s {
|
|
profileName = filepath.Join(f.profilesPath, fmt.Sprintf("%s-%s.yaml", ProfileFilePrefix, namespace))
|
|
} else {
|
|
profileName = filepath.Join(f.profilesPath, fmt.Sprintf("%s-%s.yaml", ProfileFilePrefix, install))
|
|
}
|
|
if err := os.Remove(profileName); err != nil {
|
|
return "", err
|
|
}
|
|
return profileName, nil
|
|
}
|
|
|
|
func NewFileDirProfileStore(profilesPath string) (ProfileStore, error) {
|
|
if _, err := os.Stat(profilesPath); os.IsNotExist(err) {
|
|
if err = os.MkdirAll(profilesPath, os.ModePerm); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
profileStore := &FileDirProfileStore{
|
|
profilesPath: profilesPath,
|
|
}
|
|
return profileStore, nil
|
|
}
|
|
|
|
type ConfigmapProfileStore struct {
|
|
kubeCli kubernetes.CLIClient
|
|
}
|
|
|
|
func (c *ConfigmapProfileStore) Save(profile *helm.Profile) (string, error) {
|
|
bytes, err := json.Marshal(profile)
|
|
jsonProfile := ""
|
|
if err == nil {
|
|
jsonProfile = string(bytes)
|
|
}
|
|
annotation := make(map[string]string, 0)
|
|
annotation[ProfileConfigmapAnnotation] = jsonProfile
|
|
configmap := &corev1.ConfigMap{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: profile.Global.Namespace,
|
|
Name: ProfileConfigmapName,
|
|
Annotations: annotation,
|
|
},
|
|
}
|
|
configmap.Data = make(map[string]string, 0)
|
|
configmap.Data[ProfileConfigmapKey] = util.ToYAML(profile)
|
|
name := fmt.Sprintf("%s/%s", profile.Global.Namespace, ProfileConfigmapName)
|
|
if err := c.applyConfigmap(configmap); err != nil {
|
|
return "", err
|
|
}
|
|
return name, nil
|
|
}
|
|
|
|
func (c *ConfigmapProfileStore) List() ([]*ProfileContext, error) {
|
|
profileContexts := make([]*ProfileContext, 0)
|
|
configmapList, err := c.listConfigmaps(ProfileConfigmapName, "", 100)
|
|
if err != nil {
|
|
return profileContexts, err
|
|
}
|
|
for _, configmap := range configmapList.Items {
|
|
if data, ok := configmap.Data[ProfileConfigmapKey]; ok {
|
|
profile, err := helm.UnmarshalProfile(data)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
profileContext := &ProfileContext{
|
|
Profile: profile,
|
|
Namespace: profile.Global.Namespace,
|
|
Install: profile.Global.Install,
|
|
HigressVersion: profile.HigressVersion,
|
|
SourceType: "configmap",
|
|
PathOrName: fmt.Sprintf("%s/%s", profile.Global.Namespace, configmap.Name),
|
|
}
|
|
profileContexts = append(profileContexts, profileContext)
|
|
}
|
|
}
|
|
return profileContexts, nil
|
|
}
|
|
|
|
func (c *ConfigmapProfileStore) Delete(profile *helm.Profile) (string, error) {
|
|
configmap := &corev1.ConfigMap{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: profile.Global.Namespace,
|
|
Name: ProfileConfigmapName,
|
|
},
|
|
}
|
|
name := fmt.Sprintf("%s/%s", profile.Global.Namespace, ProfileConfigmapName)
|
|
if err := c.deleteConfigmap(configmap); err != nil {
|
|
return "", err
|
|
}
|
|
return name, nil
|
|
}
|
|
|
|
func (c *ConfigmapProfileStore) listConfigmaps(name string, namespace string, size int64) (*corev1.ConfigMapList, error) {
|
|
var result *corev1.ConfigMapList
|
|
var err error
|
|
if len(namespace) == 0 {
|
|
result, err = c.kubeCli.KubernetesInterface().CoreV1().ConfigMaps("").List(context.Background(), metav1.ListOptions{Limit: size, FieldSelector: fmt.Sprintf("metadata.name=%s", name)})
|
|
} else {
|
|
result, err = c.kubeCli.KubernetesInterface().CoreV1().ConfigMaps(namespace).List(context.Background(), metav1.ListOptions{Limit: size, FieldSelector: fmt.Sprintf("metadata.name=%s", name)})
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (c *ConfigmapProfileStore) applyConfigmap(configmap *corev1.ConfigMap) error {
|
|
_, err := c.kubeCli.KubernetesInterface().CoreV1().ConfigMaps(configmap.Namespace).Get(context.Background(), configmap.Name, metav1.GetOptions{})
|
|
if err != nil && errors.IsNotFound(err) {
|
|
_, err = c.kubeCli.KubernetesInterface().CoreV1().ConfigMaps(configmap.Namespace).Create(context.Background(), configmap, metav1.CreateOptions{})
|
|
return err
|
|
} else if err != nil {
|
|
return err
|
|
} else {
|
|
_, err = c.kubeCli.KubernetesInterface().CoreV1().ConfigMaps(configmap.Namespace).Update(context.Background(), configmap, metav1.UpdateOptions{})
|
|
return err
|
|
}
|
|
}
|
|
|
|
func (c *ConfigmapProfileStore) deleteConfigmap(configmap *corev1.ConfigMap) error {
|
|
err := c.kubeCli.KubernetesInterface().CoreV1().ConfigMaps(configmap.Namespace).Delete(context.Background(), configmap.Name, metav1.DeleteOptions{})
|
|
if err != nil {
|
|
if !errors.IsNotFound(err) {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func NewConfigmapProfileStore(kubeCli kubernetes.CLIClient) (ProfileStore, error) {
|
|
profileStore := &ConfigmapProfileStore{
|
|
kubeCli: kubeCli,
|
|
}
|
|
return profileStore, nil
|
|
}
|