Skip to content

Commit

Permalink
feat:add installation for higress standalone in local docker environm…
Browse files Browse the repository at this point in the history
…ent (alibaba#606)

Co-authored-by: 澄潭 <[email protected]>
  • Loading branch information
2456868764 and johnlanni authored Nov 2, 2023
1 parent de1dd3b commit 9136908
Show file tree
Hide file tree
Showing 42 changed files with 21,140 additions and 413 deletions.
1 change: 1 addition & 0 deletions .licenserc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ header:
- 'tools/'
- 'test/README.md'
- 'pkg/cmd/hgctl/testdata/config'
- 'pkg/cmd/hgctl/manifests'

comment: on-failure
dependency:
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/klauspost/compress v1.15.9 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
github.com/lestrrat-go/backoff/v2 v2.0.7 // indirect
Expand Down Expand Up @@ -225,6 +227,7 @@ require (
github.com/prometheus/procfs v0.7.3 // indirect
github.com/prometheus/statsd_exporter v0.21.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rogpeppe/go-internal v1.6.1 // indirect
github.com/rubenv/sql-migrate v0.0.0-20210614095031-55d5740dbbcc // indirect
github.com/russross/blackfriday v1.6.0 // indirect
github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b // indirect
Expand Down
3 changes: 2 additions & 1 deletion pkg/cmd/hgctl/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ func newDashboardCmd() *cobra.Command {
controllerDebugCmd := controllerDebugCmd()
controllerDebugCmd.PersistentFlags().IntVar(&controllerPort, "ui-port", defaultControllerPort, "The component dashboard UI port.")
dashboardCmd.AddCommand(controllerDebugCmd)

flags := dashboardCmd.PersistentFlags()
options.AddKubeConfigFlags(flags)
return dashboardCmd
}

Expand Down
40 changes: 35 additions & 5 deletions pkg/cmd/hgctl/helm/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,40 @@ import (
"sigs.k8s.io/yaml"
)

// ReadYamlProfile gets the overlay yaml file from list of files and return profile value from file overlay and set overlay.
func ReadYamlProfile(inFilenames []string, setFlags []string) (string, string, error) {
// GetProfileFromFlags get profile name from flags.
func GetProfileFromFlags(setFlags []string) (string, error) {
profileName := DefaultProfileName
// The profile coming from --set flag has the highest precedence.
psf := GetValueForSetFlag(setFlags, "profile")
if psf != "" {
profileName = psf
}
return "", profileName, nil
return profileName, nil
}

func GetValuesOverylayFromFiles(inFilenames []string) (string, error) {
// Convert layeredYamls under values node in profile file to support helm values
overLayYamls := ""
// Get Overlays from files
if len(inFilenames) > 0 {
layeredYamls, err := ReadLayeredYAMLs(inFilenames)
if err != nil {
return "", err
}
vals := make(map[string]any)
if err := yaml.Unmarshal([]byte(layeredYamls), &vals); err != nil {
return "", fmt.Errorf("%s:\n\nYAML:\n%s", err, layeredYamls)
}
values := make(map[string]any)
values["values"] = vals
out, err := yaml.Marshal(values)
if err != nil {
return "", err
}
overLayYamls = string(out)
}

return overLayYamls, nil
}

func GetUninstallProfileName() string {
Expand Down Expand Up @@ -101,12 +126,17 @@ func GenerateConfig(inFilenames []string, setFlags []string) (string, *Profile,
return "", nil, "", err
}

fy, profileName, err := ReadYamlProfile(inFilenames, setFlags)
profileName, err := GetProfileFromFlags(setFlags)
if err != nil {
return "", nil, "", err
}

valuesOverlay, err := GetValuesOverylayFromFiles(inFilenames)
if err != nil {
return "", nil, "", err
}

profileString, profile, err := GenProfile(profileName, fy, setFlags)
profileString, profile, err := GenProfile(profileName, valuesOverlay, setFlags)

if err != nil {
return "", nil, "", err
Expand Down
181 changes: 120 additions & 61 deletions pkg/cmd/hgctl/helm/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ package helm
import (
"errors"
"fmt"
"strings"

"istio.io/istio/operator/pkg/util"
"sigs.k8s.io/yaml"
)

Expand All @@ -43,83 +45,72 @@ type Profile struct {
}

type ProfileGlobal struct {
Install InstallMode `json:"install,omitempty"`
IngressClass string `json:"ingressClass,omitempty"`
WatchNamespace string `json:"watchNamespace,omitempty"`
DisableAlpnH2 bool `json:"disableAlpnH2,omitempty"`
EnableStatus bool `json:"enableStatus,omitempty"`
EnableIstioAPI bool `json:"enableIstioAPI,omitempty"`
Namespace string `json:"namespace,omitempty"`
IstioNamespace string `json:"istioNamespace,omitempty"`
Install InstallMode `json:"install,omitempty"`
IngressClass string `json:"ingressClass,omitempty"`
EnableIstioAPI bool `json:"enableIstioAPI,omitempty"`
EnableGatewayAPI bool `json:"enableGatewayAPI,omitempty"`
Namespace string `json:"namespace,omitempty"`
}

func (p ProfileGlobal) SetFlags(install InstallMode) ([]string, error) {
sets := make([]string, 0)
sets = append(sets, fmt.Sprintf("global.ingressClass=%s", p.IngressClass))
sets = append(sets, fmt.Sprintf("global.watchNamespace=%s", p.WatchNamespace))
sets = append(sets, fmt.Sprintf("global.disableAlpnH2=%t", p.DisableAlpnH2))
sets = append(sets, fmt.Sprintf("global.enableStatus=%t", p.EnableStatus))
sets = append(sets, fmt.Sprintf("global.enableIstioAPI=%t", p.EnableIstioAPI))
sets = append(sets, fmt.Sprintf("global.istioNamespace=%s", p.IstioNamespace))
if install == InstallLocalK8s {
sets = append(sets, fmt.Sprintf("global.local=%t", true))
if install == InstallK8s || install == InstallLocalK8s {
sets = append(sets, fmt.Sprintf("global.ingressClass=%s", p.IngressClass))
sets = append(sets, fmt.Sprintf("global.enableIstioAPI=%t", p.EnableIstioAPI))
sets = append(sets, fmt.Sprintf("global.enableGatewayAPI=%t", p.EnableGatewayAPI))
if install == InstallLocalK8s {
sets = append(sets, fmt.Sprintf("global.local=%t", true))
}
}
return sets, nil
}

func (p ProfileGlobal) Validate(install InstallMode) []error {
errs := make([]error, 0)
// now only support k8s and local-k8s installation mode
if p.Install != InstallK8s && p.Install != InstallLocalK8s {
errs = append(errs, errors.New("global.install only can be set to k8s or local-k8s"))
}
if len(p.IngressClass) == 0 {
errs = append(errs, errors.New("global.ingressClass can't be empty"))
}
if len(p.Namespace) == 0 {
errs = append(errs, errors.New("global.namespace can't be empty"))
// now only support k8s, local-k8s, local-docker installation mode
if install != InstallK8s && install != InstallLocalK8s && install != InstallLocalDocker {
errs = append(errs, errors.New("global.install only can be set to k8s, local-k8s or local-docker"))
}
if len(p.IstioNamespace) == 0 {
errs = append(errs, errors.New("global.istioNamespace can't be empty"))
if install == InstallK8s || install == InstallLocalK8s {
if len(p.IngressClass) == 0 {
errs = append(errs, errors.New("global.ingressClass can't be empty"))
}
if len(p.Namespace) == 0 {
errs = append(errs, errors.New("global.namespace can't be empty"))
}
}
return errs
}

type ProfileConsole struct {
Port uint32 `json:"port,omitempty"`
Replicas uint32 `json:"replicas,omitempty"`
ServiceType string `json:"serviceType,omitempty"`
Domain string `json:"domain,omitempty"`
TlsSecretName string `json:"tlsSecretName,omitempty"`
WebLoginPrompt string `json:"webLoginPrompt,omitempty"`
AdminPasswordValue string `json:"adminPasswordValue,omitempty"`
AdminPasswordLength uint32 `json:"adminPasswordLength,omitempty"`
O11yEnabled bool `json:"o11YEnabled,omitempty"`
PvcRwxSupported bool `json:"pvcRwxSupported,omitempty"`
Port uint32 `json:"port,omitempty"`
Replicas uint32 `json:"replicas,omitempty"`
AdminPasswordValue string `json:"adminPasswordValue,omitempty"`
O11yEnabled bool `json:"o11YEnabled,omitempty"`
}

func (p ProfileConsole) SetFlags(install InstallMode) ([]string, error) {
sets := make([]string, 0)
sets = append(sets, fmt.Sprintf("higress-console.replicaCount=%d", p.Replicas))
sets = append(sets, fmt.Sprintf("higress-console.service.type=%s", p.ServiceType))
sets = append(sets, fmt.Sprintf("higress-console.domain=%s", p.Domain))
sets = append(sets, fmt.Sprintf("higress-console.tlsSecretName=%s", p.TlsSecretName))
sets = append(sets, fmt.Sprintf("higress-console.web.login.prompt=%s", p.WebLoginPrompt))
sets = append(sets, fmt.Sprintf("higress-console.admin.password.value=%s", p.AdminPasswordValue))
sets = append(sets, fmt.Sprintf("higress-console.admin.password.length=%d", p.AdminPasswordLength))
sets = append(sets, fmt.Sprintf("higress-console.o11y.enabled=%t", p.O11yEnabled))
sets = append(sets, fmt.Sprintf("higress-console.pvc.rwxSupported=%t", p.PvcRwxSupported))
if install == InstallK8s || install == InstallLocalK8s {
sets = append(sets, fmt.Sprintf("higress-console.replicaCount=%d", p.Replicas))
sets = append(sets, fmt.Sprintf("higress-console.admin.password.value=%s", p.AdminPasswordValue))
sets = append(sets, fmt.Sprintf("higress-console.o11y.enabled=%t", p.O11yEnabled))
}
return sets, nil
}

func (p ProfileConsole) Validate(install InstallMode) []error {
errs := make([]error, 0)
if p.Replicas <= 0 {
errs = append(errs, errors.New("console.replica need be large than zero"))
if install == InstallK8s || install == InstallLocalK8s {
if p.Replicas <= 0 {
errs = append(errs, errors.New("console.replica need be large than zero"))
}
}

if p.ServiceType != "ClusterIP" && p.ServiceType != "NodePort" && p.ServiceType != "LoadBalancer" {
errs = append(errs, errors.New("console.serviceType can only be set to ClusterIP, NodePort or LoadBalancer"))
if install == InstallLocalDocker {
if p.Port <= 0 {
errs = append(errs, errors.New("console.port need be large than zero"))
}
}

return errs
Expand All @@ -134,16 +125,31 @@ type ProfileGateway struct {

func (p ProfileGateway) SetFlags(install InstallMode) ([]string, error) {
sets := make([]string, 0)
sets = append(sets, fmt.Sprintf("higress-core.gateway.replicas=%d", p.Replicas))
if install == InstallK8s || install == InstallLocalK8s {
sets = append(sets, fmt.Sprintf("higress-core.gateway.replicas=%d", p.Replicas))
}
return sets, nil
}

func (p ProfileGateway) Validate(install InstallMode) []error {
errs := make([]error, 0)
if p.Replicas <= 0 {
errs = append(errs, errors.New("gateway.replica need be large than zero"))
if install == InstallK8s || install == InstallLocalK8s {
if p.Replicas <= 0 {
errs = append(errs, errors.New("gateway.replica need be large than zero"))
}
}

if install == InstallLocalDocker {
if p.HttpPort <= 0 {
errs = append(errs, errors.New("gateway.httpPort need be large than zero"))
}
if p.HttpsPort <= 0 {
errs = append(errs, errors.New("gateway.httpsPort need be large than zero"))
}
if p.MetricsPort <= 0 {
errs = append(errs, errors.New("gateway.MetricsPort need be large than zero"))
}
}
return errs
}

Expand All @@ -153,16 +159,19 @@ type ProfileController struct {

func (p ProfileController) SetFlags(install InstallMode) ([]string, error) {
sets := make([]string, 0)
sets = append(sets, fmt.Sprintf("higress-core.controller.replicas=%d", p.Replicas))
if install == InstallK8s || install == InstallLocalK8s {
sets = append(sets, fmt.Sprintf("higress-core.controller.replicas=%d", p.Replicas))
}
return sets, nil
}

func (p ProfileController) Validate(install InstallMode) []error {
errs := make([]error, 0)
if p.Replicas <= 0 {
errs = append(errs, errors.New("controller.replica need be large than zero"))
if install == InstallK8s || install == InstallLocalK8s {
if p.Replicas <= 0 {
errs = append(errs, errors.New("controller.replica need be large than zero"))
}
}

return errs
}

Expand All @@ -176,6 +185,31 @@ type ProfileStorage struct {

func (p ProfileStorage) Validate(install InstallMode) []error {
errs := make([]error, 0)
if install == InstallLocalDocker {
if len(p.Url) == 0 {
errs = append(errs, errors.New("storage.url can't be empty"))
}
if len(p.Ns) == 0 {
errs = append(errs, errors.New("storage.ns can't be empty"))
}

if !strings.HasPrefix(p.Url, "nacos://") && !strings.HasPrefix(p.Url, "file://") {
errs = append(errs, fmt.Errorf("invalid storage url: %s", p.Url))
} else {
// check localhost or 127.0.0.0
if strings.Contains(p.Url, "localhost") || strings.Contains(p.Url, "/127.") {
errs = append(errs, errors.New("localhost or loopback addresses in nacos url won't work"))
}
}

if len(p.DataEncKey) > 0 && len(p.DataEncKey) != 32 {
errs = append(errs, fmt.Errorf("expecting 32 characters for dataEncKey, but got %d length", len(p.DataEncKey)))
}

if len(p.Username) > 0 && len(p.Password) == 0 || len(p.Username) == 0 && len(p.Password) > 0 {
errs = append(errs, errors.New("both nacos username and password should be provided"))
}
}
return errs
}

Expand All @@ -186,8 +220,8 @@ type Chart struct {
}

type ProfileCharts struct {
Higress Chart `json:"higress,omitempty"`
Istio Chart `json:"istio,omitempty"`
Higress Chart `json:"higress,omitempty"`
Standalone Chart `json:"standalone,omitempty"`
}

func (p ProfileCharts) Validate(install InstallMode) []error {
Expand Down Expand Up @@ -222,8 +256,13 @@ func (p *Profile) ValuesYaml() (string, error) {
}
valueOverlayYAML = string(out)
}

flagsYAML, err := overlaySetFlagValues("", setFlags)
if err != nil {
return "", err
}
// merge values and setFlags
overlayYAML, err := overlaySetFlagValues(valueOverlayYAML, setFlags)
overlayYAML, err := util.OverlayYAML(flagsYAML, valueOverlayYAML)
if err != nil {
return "", err
}
Expand All @@ -237,6 +276,26 @@ func (p *Profile) IstioEnabled() bool {
return false
}

func (p *Profile) GatewayAPIEnabled() bool {
if (p.Global.Install == InstallK8s || p.Global.Install == InstallLocalK8s) && p.Global.EnableGatewayAPI {
return true
}
return false
}

func (p *Profile) GetIstioNamespace() string {
if valuesGlobal, ok1 := p.Values["global"]; ok1 {
if global, ok2 := valuesGlobal.(map[string]any); ok2 {
if istioNamespace, ok3 := global["istioNamespace"]; ok3 {
if namespace, ok4 := istioNamespace.(string); ok4 {
return namespace
}
}
}
}
return ""
}

func (p *Profile) Validate() error {
errs := make([]error, 0)
errsGlobal := p.Global.Validate(p.Global.Install)
Expand All @@ -256,7 +315,7 @@ func (p *Profile) Validate() error {
errs = append(errs, errsController...)
}
errsStorage := p.Storage.Validate(p.Global.Install)
if len(errsController) > 0 {
if len(errsStorage) > 0 {
errs = append(errs, errsStorage...)
}
errsCharts := p.Charts.Validate(p.Global.Install)
Expand Down
Loading

0 comments on commit 9136908

Please sign in to comment.