Skip to content

Commit

Permalink
feat(installer): support install platform apps (#1832)
Browse files Browse the repository at this point in the history
  • Loading branch information
Leo Ryu authored Apr 12, 2022
1 parent 4d9796a commit b75278e
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 131 deletions.
19 changes: 18 additions & 1 deletion cmd/tke-installer/app/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ package config

import (
"helm.sh/helm/v3/pkg/chartutil"
"k8s.io/apimachinery/pkg/util/wait"
applicationv1 "tkestack.io/tke/api/application/v1"
"tkestack.io/tke/cmd/tke-installer/app/options"
helmaction "tkestack.io/tke/pkg/application/helm/action"
clusterprovider "tkestack.io/tke/pkg/platform/provider/cluster"
"tkestack.io/tke/pkg/util/log"
)
Expand Down Expand Up @@ -52,9 +55,10 @@ type Config struct {
EnableCustomExpansion bool
// CustomExpansionDir path to expansions. default `data/expansions`
CustomExpansionDir string
ExpansionApps []ExpansionApp
PlatformApps []PlatformApp
}
type PlatformApp struct {
type ExpansionApp struct {
Name string
Enable bool
Chart Chart
Expand All @@ -75,6 +79,19 @@ type Chart struct {
Values chartutil.Values
}

type PlatformApp struct {
HelmInstallOptions helmaction.InstallOptions
LocalChartPath string
ConditionFunc wait.ConditionFunc
Enable bool
Installed bool
// rawValues: json format or yaml format
RawValues string
RawValuesType applicationv1.RawValuesType
// values: can specify multiple or separate values: key1=val1,key2=val2
Values []string
}

// CreateConfigFromOptions creates a running configuration instance based
// on a given TKE apiserver command line or configuration file option.
func CreateConfigFromOptions(serverName string, opts *options.Options) (*Config, error) {
Expand Down
164 changes: 145 additions & 19 deletions cmd/tke-installer/app/installer/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,31 @@ package installer
import (
"context"
"fmt"
"time"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
applicationv1 "tkestack.io/tke/api/application/v1"
"tkestack.io/tke/cmd/tke-installer/app/config"
"tkestack.io/tke/cmd/tke-installer/app/installer/constants"
helmaction "tkestack.io/tke/pkg/application/helm/action"
helmutil "tkestack.io/tke/pkg/application/helm/util"
"tkestack.io/tke/pkg/util/apiclient"
)

func (t *TKE) completePlatformApps() error {
func (t *TKE) completeExpansionApps() error {

if len(t.Config.PlatformApps) == 0 {
if len(t.Config.ExpansionApps) == 0 {
return nil
}

for _, platformApp := range t.Config.PlatformApps {
if !platformApp.Enable {
for _, expansionApp := range t.Config.ExpansionApps {
if !expansionApp.Enable {
continue
}
err := t.completeChart(&platformApp.Chart)
err := t.completeChart(&expansionApp.Chart)
if err != nil {
return fmt.Errorf("bad platform app config. %v, %v", platformApp.Name, err)
return fmt.Errorf("bad platform app config. %v, %v", expansionApp.Name, err)
}
}

Expand Down Expand Up @@ -79,7 +85,7 @@ func (t *TKE) completeChart(chart *config.Chart) error {

func (t *TKE) installApplications(ctx context.Context) error {

if len(t.Config.PlatformApps) == 0 {
if len(t.Config.ExpansionApps) == 0 {
return nil
}

Expand All @@ -97,38 +103,38 @@ func (t *TKE) installApplications(ctx context.Context) error {
return fmt.Errorf("list all applications failed %v", err)
}

for _, platformApp := range t.Config.PlatformApps {
if !platformApp.Enable {
for _, expansionApp := range t.Config.ExpansionApps {
if !expansionApp.Enable {
continue
}
if t.applicationAlreadyInstalled(platformApp, apps.Items) {
t.log.Infof("application already exists. we don't override applications while installing. %v/%v", platformApp.Chart.TargetNamespace, platformApp.Chart.Name)
if t.applicationAlreadyInstalled(expansionApp, apps.Items) {
t.log.Infof("application already exists. we don't override applications while installing. %v/%v", expansionApp.Chart.TargetNamespace, expansionApp.Chart.Name)
continue
}
err := t.installApplication(ctx, platformApp)
err := t.installApplication(ctx, expansionApp)
if err != nil {
return fmt.Errorf("install application failed. %v, %v", platformApp.Name, err)
return fmt.Errorf("install application failed. %v, %v", expansionApp.Name, err)
}
t.log.Infof("finish application installation %v", platformApp.Name)
t.log.Infof("finish application installation %v", expansionApp.Name)
}

return nil
}

func (t *TKE) applicationAlreadyInstalled(platformApp config.PlatformApp, installedApps []applicationv1.App) bool {
func (t *TKE) applicationAlreadyInstalled(expansionApp config.ExpansionApp, installedApps []applicationv1.App) bool {

for _, installedApp := range installedApps {
// if there's an existed application with the same namespace+name, we consider it as already exists
if platformApp.Name == installedApp.Spec.Name && platformApp.Chart.TargetNamespace == installedApp.Namespace {
if expansionApp.Name == installedApp.Spec.Name && expansionApp.Chart.TargetNamespace == installedApp.Namespace {
return true
}
}
return false
}

func (t *TKE) installApplication(ctx context.Context, platformApp config.PlatformApp) error {
func (t *TKE) installApplication(ctx context.Context, expansionApp config.ExpansionApp) error {

chart := platformApp.Chart
chart := expansionApp.Chart

rawValues, err := chart.Values.YAML()
if err != nil {
Expand All @@ -143,7 +149,7 @@ func (t *TKE) installApplication(ctx context.Context, platformApp config.Platfor
Spec: applicationv1.AppSpec{
Type: constants.DefaultApplicationInstallDriverType,
TenantID: chart.TenantID,
Name: platformApp.Name,
Name: expansionApp.Name,
TargetCluster: chart.TargetCluster,
Chart: applicationv1.Chart{
TenantID: chart.TenantID,
Expand All @@ -163,3 +169,123 @@ func (t *TKE) installApplication(ctx context.Context, platformApp config.Platfor
}
return nil
}
func (t *TKE) initPlatformApps(ctx context.Context) error {
defaultPlatformApps := []config.PlatformApp{}
if t.Para.Config.Auth.TKEAuth != nil {
authAPIOptions, err := t.getTKEAuthAPIOptions(ctx)
if err != nil {
return fmt.Errorf("get tke-auth-api options failed: %v", err)
}
tkeAuth := config.PlatformApp{
HelmInstallOptions: helmaction.InstallOptions{
Namespace: t.namespace,
ReleaseName: "tke-auth",
Values: map[string]interface{}{
"api": authAPIOptions,
"controller": t.getTKEAuthControllerOptions(ctx),
},
DependencyUpdate: false,
ChartPathOptions: helmaction.ChartPathOptions{},
},
LocalChartPath: constants.ChartDirName + "tke-auth/",
Enable: true,
ConditionFunc: func() (bool, error) {
apiOk, err := apiclient.CheckDeployment(ctx, t.globalClient, t.namespace, "tke-auth-api")
if err != nil {
return false, nil
}
controllerOk, err := apiclient.CheckDeployment(ctx, t.globalClient, t.namespace, "tke-auth-controller")
if err != nil {
return false, nil
}
return apiOk && controllerOk, nil
},
}
defaultPlatformApps = append(defaultPlatformApps, tkeAuth)
}
platformAPIOptions, err := t.getTKEPlatformAPIOptions(ctx)
if err != nil {
return fmt.Errorf("get tke-platform-api options failed: %v", err)
}
tkePlatform := config.PlatformApp{
HelmInstallOptions: helmaction.InstallOptions{
Namespace: t.namespace,
ReleaseName: "tke-platform",
Values: map[string]interface{}{
"api": platformAPIOptions,
"controller": t.getTKEPlatformControllerOptions(ctx),
},
DependencyUpdate: false,
ChartPathOptions: helmaction.ChartPathOptions{},
},
LocalChartPath: constants.ChartDirName + "tke-platform/",
Enable: true,
ConditionFunc: func() (bool, error) {
apiOk, err := apiclient.CheckDeployment(ctx, t.globalClient, t.namespace, "tke-platform-api")
if err != nil {
return false, nil
}
controllerOk, err := apiclient.CheckDeployment(ctx, t.globalClient, t.namespace, "tke-platform-controller")
if err != nil {
return false, nil
}
return apiOk && controllerOk, nil
},
}
defaultPlatformApps = append(defaultPlatformApps, tkePlatform)
t.Config.PlatformApps = append(defaultPlatformApps, t.Config.PlatformApps...)
return nil
}

func (t *TKE) installPlatformApps(ctx context.Context) error {

if len(t.Config.PlatformApps) == 0 {
return nil
}
for i, platformApp := range t.Config.PlatformApps {
if !platformApp.Enable || platformApp.Installed {
continue
}
t.log.Infof("Start instal platform app %s in %s namespace", platformApp.HelmInstallOptions.ReleaseName, platformApp.HelmInstallOptions.Namespace)
err := t.installPlatformApp(ctx, platformApp)
if err != nil {
t.log.Errorf("Install %s failed", platformApp.HelmInstallOptions.ReleaseName)
}
t.Config.PlatformApps[i].Installed = true
t.log.Infof("End instal platform app %s in %s namespace", platformApp.HelmInstallOptions.ReleaseName, platformApp.HelmInstallOptions.Namespace)
}

return nil
}

func (t *TKE) installPlatformApp(ctx context.Context, platformApp config.PlatformApp) error {
platformApp.HelmInstallOptions.Timeout = 10 * time.Minute
if len(platformApp.RawValues) != 0 || len(platformApp.Values) != 0 {
values, err := helmutil.MergeValues(platformApp.Values, platformApp.RawValues, string(platformApp.RawValuesType))
if err != nil {
return err
}
platformApp.HelmInstallOptions.Values = values
}
if len(platformApp.LocalChartPath) != 0 {
if _, err := t.helmClient.InstallWithLocal(&platformApp.HelmInstallOptions, platformApp.LocalChartPath); err != nil {
uninstallOptions := helmaction.UninstallOptions{
Timeout: 10 * time.Minute,
ReleaseName: platformApp.HelmInstallOptions.ReleaseName,
Namespace: platformApp.HelmInstallOptions.Namespace,
}
reponse, err := t.helmClient.Uninstall(&uninstallOptions)
if err != nil {
return fmt.Errorf("clean %s failed %v", reponse.Release.Name, err)
}
return err
}
}
if platformApp.ConditionFunc != nil {
err := wait.PollImmediate(5*time.Second, 10*time.Minute, platformApp.ConditionFunc)
if err != nil {
return err
}
}
return nil
}
13 changes: 7 additions & 6 deletions cmd/tke-installer/app/installer/application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package installer
import (
"context"
"fmt"
"helm.sh/helm/v3/pkg/chartutil"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"os"
"testing"

"helm.sh/helm/v3/pkg/chartutil"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
registryv1 "tkestack.io/tke/api/registry/v1"
"tkestack.io/tke/cmd/tke-installer/app/config"
helmaction "tkestack.io/tke/pkg/application/helm/action"
Expand Down Expand Up @@ -61,21 +62,21 @@ func TestTKE_installApplication(t *testing.T) {
TargetNamespace: "default",
Values: chartutil.Values{},
}
platformApp := config.PlatformApp{
expansionApp := config.ExpansionApp{
Name: name,
Enable: true,
Chart: *chart,
}

if tke.applicationAlreadyInstalled(platformApp, apps.Items) {
if tke.applicationAlreadyInstalled(expansionApp, apps.Items) {
t.Log("already installed")
} else {
err = tke.installApplication(context.Background(), platformApp)
err = tke.installApplication(context.Background(), expansionApp)
if err != nil {
t.Fatal(err)
}
}
b, err := json.MarshalIndent([]config.PlatformApp{
b, err := json.MarshalIndent([]config.ExpansionApp{
{
Name: name,
Enable: true,
Expand Down
Loading

0 comments on commit b75278e

Please sign in to comment.