mirror of
https://github.com/alibaba/higress.git
synced 2026-03-02 07:30:49 +08:00
214 lines
6.3 KiB
Go
214 lines
6.3 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 (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/alibaba/higress/pkg/cmd/hgctl/helm"
|
|
"github.com/alibaba/higress/pkg/cmd/hgctl/helm/object"
|
|
"github.com/alibaba/higress/pkg/cmd/hgctl/kubernetes"
|
|
)
|
|
|
|
type Installer struct {
|
|
started bool
|
|
components map[ComponentName]Component
|
|
kubeCli kubernetes.CLIClient
|
|
profile *helm.Profile
|
|
writer io.Writer
|
|
}
|
|
|
|
// Run must be invoked before invoking other functions.
|
|
func (o *Installer) Run() error {
|
|
for name, component := range o.components {
|
|
if !component.Enabled() {
|
|
continue
|
|
}
|
|
if err := component.Run(); err != nil {
|
|
return fmt.Errorf("component %s run failed, err: %s", name, err)
|
|
}
|
|
}
|
|
o.started = true
|
|
return nil
|
|
}
|
|
|
|
// RenderManifests renders component manifests specified by profile.
|
|
func (o *Installer) RenderManifests() (map[ComponentName]string, error) {
|
|
if !o.started {
|
|
return nil, errors.New("HigressOperator is not running")
|
|
}
|
|
res := make(map[ComponentName]string)
|
|
for name, component := range o.components {
|
|
if !component.Enabled() {
|
|
continue
|
|
}
|
|
manifest, err := component.RenderManifest()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("component %s RenderManifest err: %v", name, err)
|
|
}
|
|
res[name] = manifest
|
|
}
|
|
return res, nil
|
|
}
|
|
|
|
// GenerateManifests generates component manifests to k8s cluster
|
|
func (o *Installer) GenerateManifests(manifestMap map[ComponentName]string) error {
|
|
if o.kubeCli == nil {
|
|
return errors.New("no injected k8s cli into Installer")
|
|
}
|
|
for _, manifest := range manifestMap {
|
|
fmt.Fprint(o.writer, manifest)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ApplyManifests apply component manifests to k8s cluster
|
|
func (o *Installer) ApplyManifests(manifestMap map[ComponentName]string) error {
|
|
if o.kubeCli == nil {
|
|
return errors.New("no injected k8s cli into Installer")
|
|
}
|
|
for name, manifest := range manifestMap {
|
|
namespace := o.components[name].Namespace()
|
|
if err := o.applyManifest(manifest, namespace); err != nil {
|
|
return fmt.Errorf("component %s ApplyManifest err: %v", name, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (o *Installer) applyManifest(manifest string, ns string) error {
|
|
if err := o.kubeCli.CreateNamespace(ns); err != nil {
|
|
return err
|
|
}
|
|
objs, err := object.ParseK8sObjectsFromYAMLManifest(manifest)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, obj := range objs {
|
|
// check namespaced object if namespace property has been existed
|
|
if obj.Namespace == "" && o.isNamespacedObject(obj) {
|
|
obj.Namespace = ns
|
|
obj.UnstructuredObject().SetNamespace(ns)
|
|
}
|
|
if o.isNamespacedObject(obj) {
|
|
fmt.Fprintf(o.writer, "✔️ Installed %s:%s:%s.\n", obj.Kind, obj.Name, obj.Namespace)
|
|
} else {
|
|
fmt.Fprintf(o.writer, "✔️ Installed %s::%s.\n", obj.Kind, obj.Name)
|
|
}
|
|
if err := o.kubeCli.ApplyObject(obj.UnstructuredObject()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// DeleteManifests delete component manifests to k8s cluster
|
|
func (o *Installer) DeleteManifests(manifestMap map[ComponentName]string) error {
|
|
if o.kubeCli == nil {
|
|
return errors.New("no injected k8s cli into Installer")
|
|
}
|
|
for name, manifest := range manifestMap {
|
|
namespace := o.components[name].Namespace()
|
|
if err := o.deleteManifest(manifest, namespace); err != nil {
|
|
return fmt.Errorf("component %s DeleteManifest err: %v", name, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// deleteManifest delete manifest to certain namespace
|
|
func (o *Installer) deleteManifest(manifest string, ns string) error {
|
|
objs, err := object.ParseK8sObjectsFromYAMLManifest(manifest)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, obj := range objs {
|
|
// check namespaced object if namespace property has been existed
|
|
if obj.Namespace == "" && o.isNamespacedObject(obj) {
|
|
obj.Namespace = ns
|
|
obj.UnstructuredObject().SetNamespace(ns)
|
|
}
|
|
if o.isNamespacedObject(obj) {
|
|
fmt.Fprintf(o.writer, "✔️ Removed %s:%s:%s.\n", obj.Kind, obj.Name, obj.Namespace)
|
|
} else {
|
|
fmt.Fprintf(o.writer, "✔️ Removed %s::%s.\n", obj.Kind, obj.Name)
|
|
}
|
|
if err := o.kubeCli.DeleteObject(obj.UnstructuredObject()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (o *Installer) isNamespacedObject(obj *object.K8sObject) bool {
|
|
if obj.Kind != "CustomResourceDefinition" && obj.Kind != "ClusterRole" && obj.Kind != "ClusterRoleBinding" {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func NewInstaller(profile *helm.Profile, cli kubernetes.CLIClient, writer io.Writer, quiet bool) (*Installer, error) {
|
|
if profile == nil {
|
|
return nil, errors.New("install profile is empty")
|
|
}
|
|
// initialize components
|
|
components := make(map[ComponentName]Component)
|
|
opts := []ComponentOption{
|
|
WithComponentNamespace(profile.Global.Namespace),
|
|
WithComponentChartPath(profile.InstallPackagePath),
|
|
WithComponentVersion(profile.Charts.Higress.Version),
|
|
WithComponentRepoURL(profile.Charts.Higress.Url),
|
|
WithComponentChartName(profile.Charts.Higress.Name),
|
|
}
|
|
if quiet {
|
|
opts = append(opts, WithQuiet())
|
|
}
|
|
higressComponent, err := NewHigressComponent(profile, writer, opts...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("NewHigressComponent failed, err: %s", err)
|
|
}
|
|
components[Higress] = higressComponent
|
|
|
|
if profile.IstioEnabled() {
|
|
opts := []ComponentOption{
|
|
WithComponentNamespace(profile.Global.IstioNamespace),
|
|
WithComponentChartPath(profile.InstallPackagePath),
|
|
WithComponentVersion(profile.Charts.Istio.Version),
|
|
WithComponentRepoURL(profile.Charts.Istio.Url),
|
|
WithComponentChartName(profile.Charts.Istio.Name),
|
|
}
|
|
if quiet {
|
|
opts = append(opts, WithQuiet())
|
|
}
|
|
|
|
istioCRDComponent, err := NewIstioCRDComponent(profile, writer, opts...)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("NewIstioCRDComponent failed, err: %s", err)
|
|
}
|
|
components[Istio] = istioCRDComponent
|
|
}
|
|
op := &Installer{
|
|
profile: profile,
|
|
components: components,
|
|
kubeCli: cli,
|
|
writer: writer,
|
|
}
|
|
return op, nil
|
|
}
|