From 707940d7c3619883a0c1ac7d6f69997d7b8e5a4e Mon Sep 17 00:00:00 2001 From: GLYASAI Date: Fri, 16 Apr 2021 10:07:34 +0800 Subject: [PATCH] create helm app --- Makefile | 1 + api/controller/application.go | 10 +- api/handler/application_handler.go | 62 +- api/model/model.go | 21 +- cmd/helmappcontroller/main.go | 3 +- db/model/application.go | 19 +- pkg/apis/rainbond/v1alpha1/helmapp_types.go | 4 +- util/commonutil/convert_types.go | 918 ++++++++++++++++++++ worker/controllers/helmapp/detector.go | 4 +- worker/controllers/helmapp/helm/app.go | 51 +- worker/controllers/helmapp/helm/repo.go | 23 +- 11 files changed, 1038 insertions(+), 78 deletions(-) create mode 100644 util/commonutil/convert_types.go diff --git a/Makefile b/Makefile index c36bff769..d333481b3 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,7 @@ manifests: controller-gen # Generate code generate: controller-gen + chmod +x vendor/k8s.io/code-generator/generate-groups.sh ./hack/k8s/codegen/update-generated.sh $(CONTROLLER_GEN) object:headerFile="hack/k8s/codegen/boilerplate.go.txt" paths="./pkg/apis/..." diff --git a/api/controller/application.go b/api/controller/application.go index 087da1adb..3c879e4f0 100644 --- a/api/controller/application.go +++ b/api/controller/application.go @@ -27,7 +27,11 @@ func (a *ApplicationController) CreateApp(w http.ResponseWriter, r *http.Request httputil.ReturnBcodeError(r, w, bcode.NewBadRequest("the field 'app_tore_name' is required")) return } - if tenantReq.HelmAppName == "" { + if tenantReq.AppTemplateName == "" { + httputil.ReturnBcodeError(r, w, bcode.NewBadRequest("the field 'app_template_name' is required")) + return + } + if tenantReq.AppTemplateName == "" { httputil.ReturnBcodeError(r, w, bcode.NewBadRequest("the field 'helm_app_name' is required")) return } @@ -42,7 +46,7 @@ func (a *ApplicationController) CreateApp(w http.ResponseWriter, r *http.Request tenantReq.TenantID = tenant.UUID // create app - app, err := handler.GetApplicationHandler().CreateApp(&tenantReq) + app, err := handler.GetApplicationHandler().CreateApp(r.Context(), &tenantReq) if err != nil { httputil.ReturnBcodeError(r, w, err) return @@ -60,7 +64,7 @@ func (a *ApplicationController) BatchCreateApp(w http.ResponseWriter, r *http.Re // get current tenant tenant := r.Context().Value(middleware.ContextKey("tenant")).(*dbmodel.Tenants) - respList, err := handler.GetApplicationHandler().BatchCreateApp(&apps, tenant.UUID) + respList, err := handler.GetApplicationHandler().BatchCreateApp(r.Context(), &apps, tenant.UUID) if err != nil { httputil.ReturnBcodeError(r, w, err) return diff --git a/api/handler/application_handler.go b/api/handler/application_handler.go index 7b1d0ad28..e7f46a416 100644 --- a/api/handler/application_handler.go +++ b/api/handler/application_handler.go @@ -11,23 +11,28 @@ import ( "github.com/goodrain/rainbond/api/util/bcode" "github.com/goodrain/rainbond/db" dbmodel "github.com/goodrain/rainbond/db/model" + "github.com/goodrain/rainbond/pkg/apis/rainbond/v1alpha1" + "github.com/goodrain/rainbond/pkg/generated/clientset/versioned" "github.com/goodrain/rainbond/util" + "github.com/goodrain/rainbond/util/commonutil" "github.com/goodrain/rainbond/worker/client" "github.com/goodrain/rainbond/worker/server/pb" "github.com/jinzhu/gorm" "github.com/sirupsen/logrus" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // ApplicationAction - type ApplicationAction struct { - statusCli *client.AppRuntimeSyncClient - promClient prometheus.Interface + statusCli *client.AppRuntimeSyncClient + promClient prometheus.Interface + rainbondClient versioned.Interface } // ApplicationHandler defines handler methods to TenantApplication. type ApplicationHandler interface { - CreateApp(req *model.Application) (*model.Application, error) - BatchCreateApp(req *model.CreateAppRequest, tenantID string) ([]model.CreateAppResponse, error) + CreateApp(ctx context.Context, req *model.Application) (*model.Application, error) + BatchCreateApp(ctx context.Context, req *model.CreateAppRequest, tenantID string) ([]model.CreateAppResponse, error) UpdateApp(srcApp *dbmodel.Application, req model.UpdateAppRequest) (*dbmodel.Application, error) ListApps(tenantID, appName string, page, pageSize int) (*model.ListAppResponse, error) GetAppByID(appID string) (*dbmodel.Application, error) @@ -53,16 +58,16 @@ func NewApplicationHandler(statusCli *client.AppRuntimeSyncClient, promClient pr } // CreateApp - -func (a *ApplicationAction) CreateApp(req *model.Application) (*model.Application, error) { +func (a *ApplicationAction) CreateApp(ctx context.Context, req *model.Application) (*model.Application, error) { appReq := &dbmodel.Application{ - EID: req.EID, - TenantID: req.TenantID, - AppID: util.NewUUID(), - AppName: req.AppName, - AppType: req.AppType, - AppStoreName: req.AppStoreName, - HelmAppName: req.HelmAppName, - Version: req.Version, + EID: req.EID, + TenantID: req.TenantID, + AppID: util.NewUUID(), + AppName: req.AppName, + AppType: req.AppType, + AppStoreName: req.AppStoreName, + AppTemplateName: req.AppTemplateName, + Version: req.Version, } req.AppID = appReq.AppID @@ -77,22 +82,45 @@ func (a *ApplicationAction) CreateApp(req *model.Application) (*model.Applicatio } } - // create app.rainbond.io - return nil + // create helmapp.rainbond.goodrain.io + return a.createHelmApp(ctx, appReq) }) return req, err } +func (a *ApplicationAction) createHelmApp(ctx context.Context, app *dbmodel.Application) error { + helmApp := &v1alpha1.HelmApp{ + ObjectMeta: metav1.ObjectMeta{ + Name: app.AppName, + Namespace: app.TenantID, + // TODO: rainbond labels. + }, + Spec: v1alpha1.HelmAppSpec{ + EID: app.EID, + TemplateName: app.AppTemplateName, + Version: app.Version, + Revision: commonutil.Int32(0), + AppStore: &v1alpha1.HelmAppStore{ + Version: "", // TODO: setup version. + Name: app.AppStoreName, + URL: app.AppStoreURL, + }, + }} + + _, err := a.rainbondClient.RainbondV1alpha1().HelmApps(helmApp.Name).Create(ctx, helmApp, metav1.CreateOptions{}) + return err +} + // BatchCreateApp - -func (a *ApplicationAction) BatchCreateApp(apps *model.CreateAppRequest, tenantID string) ([]model.CreateAppResponse, error) { +func (a *ApplicationAction) BatchCreateApp(ctx context.Context, apps *model.CreateAppRequest, tenantID string) ([]model.CreateAppResponse, error) { var ( resp model.CreateAppResponse respList []model.CreateAppResponse ) for _, app := range apps.AppsInfo { app.TenantID = tenantID - regionApp, err := GetApplicationHandler().CreateApp(&app) + regionApp, err := GetApplicationHandler().CreateApp(ctx, &app) if err != nil { logrus.Errorf("Batch Create App [%v] error is [%v] ", app.AppName, err) continue diff --git a/api/model/model.go b/api/model/model.go index 9555e6aef..92262d587 100644 --- a/api/model/model.go +++ b/api/model/model.go @@ -1649,16 +1649,17 @@ func NewAppStatusFromImport(app *ImportAppStruct) *dbmodel.AppStatus { // Application - type Application struct { - EID string `json:"eid" validate:"required"` - AppName string `json:"app_name" validate:"required"` - AppType string `json:"app_type" validate:"required,oneof=rainbond helm"` - ConsoleAppID int64 `json:"console_app_id"` - AppID string `json:"app_id"` - TenantID string `json:"tenant_id"` - ServiceIDs []string `json:"service_ids"` - AppStoreName string `json:"app_store_name"` - HelmAppName string `json:"helm_app_name"` - Version string `json:"version"` + EID string `json:"eid" validate:"required"` + AppName string `json:"app_name" validate:"required"` + AppType string `json:"app_type" validate:"required,oneof=rainbond helm"` + ConsoleAppID int64 `json:"console_app_id"` + AppID string `json:"app_id"` + TenantID string `json:"tenant_id"` + ServiceIDs []string `json:"service_ids"` + AppStoreName string `json:"app_store_name"` + AppStoreURL string `json:"app_store_url"` + AppTemplateName string `json:"app_template_name"` + Version string `json:"version"` } // CreateAppRequest - diff --git a/cmd/helmappcontroller/main.go b/cmd/helmappcontroller/main.go index 2b37531bd..b6dde9230 100644 --- a/cmd/helmappcontroller/main.go +++ b/cmd/helmappcontroller/main.go @@ -38,8 +38,7 @@ func main() { }, Spec: rainbondv1alpha1.HelmAppSpec{ PreStatus: "", - AppName: "rainbond-operator", - Version: "v1.0.0", + Version: "1.3.0", Revision: Int32(0), Values: "", AppStore: &rainbondv1alpha1.HelmAppStore{ diff --git a/db/model/application.go b/db/model/application.go index 7fbad2991..5415ce228 100644 --- a/db/model/application.go +++ b/db/model/application.go @@ -15,15 +15,16 @@ func IsGovernanceModeValid(governanceMode string) bool { // Application - type Application struct { Model - EID string `gorm:"column:eid" json:"eid"` - TenantID string `gorm:"column:tenant_id" json:"tenant_id"` - AppName string `gorm:"column:app_name" json:"app_name"` - AppID string `gorm:"column:app_id" json:"app_id"` - AppType string `gorm:"column:app_type;default:rainbond" json:"app_type"` - AppStoreName string `gorm:"column:app_store_name" json:"app_store_name"` - HelmAppName string `gorm:"column:helm_app_name" json:"helm_app_name"` - Version string `gorm:"column:Version" json:"Version"` - GovernanceMode string `gorm:"column:governance_mode;default:'BUILD_IN_SERVICE_MESH'" json:"governance_mode"` + EID string `gorm:"column:eid" json:"eid"` + TenantID string `gorm:"column:tenant_id" json:"tenant_id"` + AppName string `gorm:"column:app_name" json:"app_name"` + AppID string `gorm:"column:app_id" json:"app_id"` + AppType string `gorm:"column:app_type;default:rainbond" json:"app_type"` + AppStoreName string `gorm:"column:app_store_name" json:"app_store_name"` + AppStoreURL string `gorm:"column:app_store_url" json:"app_store_url"` + AppTemplateName string `gorm:"column:app_template_name" json:"app_template_name"` + Version string `gorm:"column:Version" json:"Version"` + GovernanceMode string `gorm:"column:governance_mode;default:'BUILD_IN_SERVICE_MESH'" json:"governance_mode"` } // TableName return tableName "application" diff --git a/pkg/apis/rainbond/v1alpha1/helmapp_types.go b/pkg/apis/rainbond/v1alpha1/helmapp_types.go index 77bb78739..d727e5534 100644 --- a/pkg/apis/rainbond/v1alpha1/helmapp_types.go +++ b/pkg/apis/rainbond/v1alpha1/helmapp_types.go @@ -96,13 +96,15 @@ type HelmAppSpec struct { // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster // Important: Run "make" to regenerate code after modifying this file + EID string `json:"eid"` + // The prerequisite status. // +kubebuilder:validation:Enum=NotConfigured;Configured PreStatus string `json:"preStatus,omitempty"` // The application name. // TODO: validation - AppName string `json:"appName"` + TemplateName string `json:"appName"` // The application version. // TODO: validation diff --git a/util/commonutil/convert_types.go b/util/commonutil/convert_types.go new file mode 100644 index 000000000..e334ab7b5 --- /dev/null +++ b/util/commonutil/convert_types.go @@ -0,0 +1,918 @@ +package commonutil + +import "time" + +// String returns a pointer to the string value passed in. +func String(v string) *string { + return &v +} + +// StringValue returns the value of the string pointer passed in or +// "" if the pointer is nil. +func StringValue(v *string) string { + if v != nil { + return *v + } + return "" +} + +// StringSlice converts a slice of string values into a slice of +// string pointers +func StringSlice(src []string) []*string { + dst := make([]*string, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// StringValueSlice converts a slice of string pointers into a slice of +// string values +func StringValueSlice(src []*string) []string { + dst := make([]string, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// StringMap converts a string map of string values into a string +// map of string pointers +func StringMap(src map[string]string) map[string]*string { + dst := make(map[string]*string) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// StringValueMap converts a string map of string pointers into a string +// map of string values +func StringValueMap(src map[string]*string) map[string]string { + dst := make(map[string]string) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Bool returns a pointer to the bool value passed in. +func Bool(v bool) *bool { + return &v +} + +// BoolValue returns the value of the bool pointer passed in or +// false if the pointer is nil. +func BoolValue(v *bool) bool { + if v != nil { + return *v + } + return false +} + +// BoolSlice converts a slice of bool values into a slice of +// bool pointers +func BoolSlice(src []bool) []*bool { + dst := make([]*bool, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// BoolValueSlice converts a slice of bool pointers into a slice of +// bool values +func BoolValueSlice(src []*bool) []bool { + dst := make([]bool, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// BoolMap converts a string map of bool values into a string +// map of bool pointers +func BoolMap(src map[string]bool) map[string]*bool { + dst := make(map[string]*bool) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// BoolValueMap converts a string map of bool pointers into a string +// map of bool values +func BoolValueMap(src map[string]*bool) map[string]bool { + dst := make(map[string]bool) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Int returns a pointer to the int value passed in. +func Int(v int) *int { + return &v +} + +// IntValue returns the value of the int pointer passed in or +// 0 if the pointer is nil. +func IntValue(v *int) int { + if v != nil { + return *v + } + return 0 +} + +// IntSlice converts a slice of int values into a slice of +// int pointers +func IntSlice(src []int) []*int { + dst := make([]*int, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// IntValueSlice converts a slice of int pointers into a slice of +// int values +func IntValueSlice(src []*int) []int { + dst := make([]int, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// IntMap converts a string map of int values into a string +// map of int pointers +func IntMap(src map[string]int) map[string]*int { + dst := make(map[string]*int) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// IntValueMap converts a string map of int pointers into a string +// map of int values +func IntValueMap(src map[string]*int) map[string]int { + dst := make(map[string]int) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Uint returns a pointer to the uint value passed in. +func Uint(v uint) *uint { + return &v +} + +// UintValue returns the value of the uint pointer passed in or +// 0 if the pointer is nil. +func UintValue(v *uint) uint { + if v != nil { + return *v + } + return 0 +} + +// UintSlice converts a slice of uint values uinto a slice of +// uint pointers +func UintSlice(src []uint) []*uint { + dst := make([]*uint, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// UintValueSlice converts a slice of uint pointers uinto a slice of +// uint values +func UintValueSlice(src []*uint) []uint { + dst := make([]uint, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// UintMap converts a string map of uint values uinto a string +// map of uint pointers +func UintMap(src map[string]uint) map[string]*uint { + dst := make(map[string]*uint) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// UintValueMap converts a string map of uint pointers uinto a string +// map of uint values +func UintValueMap(src map[string]*uint) map[string]uint { + dst := make(map[string]uint) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Int8 returns a pointer to the int8 value passed in. +func Int8(v int8) *int8 { + return &v +} + +// Int8Value returns the value of the int8 pointer passed in or +// 0 if the pointer is nil. +func Int8Value(v *int8) int8 { + if v != nil { + return *v + } + return 0 +} + +// Int8Slice converts a slice of int8 values into a slice of +// int8 pointers +func Int8Slice(src []int8) []*int8 { + dst := make([]*int8, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// Int8ValueSlice converts a slice of int8 pointers into a slice of +// int8 values +func Int8ValueSlice(src []*int8) []int8 { + dst := make([]int8, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// Int8Map converts a string map of int8 values into a string +// map of int8 pointers +func Int8Map(src map[string]int8) map[string]*int8 { + dst := make(map[string]*int8) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// Int8ValueMap converts a string map of int8 pointers into a string +// map of int8 values +func Int8ValueMap(src map[string]*int8) map[string]int8 { + dst := make(map[string]int8) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Int16 returns a pointer to the int16 value passed in. +func Int16(v int16) *int16 { + return &v +} + +// Int16Value returns the value of the int16 pointer passed in or +// 0 if the pointer is nil. +func Int16Value(v *int16) int16 { + if v != nil { + return *v + } + return 0 +} + +// Int16Slice converts a slice of int16 values into a slice of +// int16 pointers +func Int16Slice(src []int16) []*int16 { + dst := make([]*int16, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// Int16ValueSlice converts a slice of int16 pointers into a slice of +// int16 values +func Int16ValueSlice(src []*int16) []int16 { + dst := make([]int16, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// Int16Map converts a string map of int16 values into a string +// map of int16 pointers +func Int16Map(src map[string]int16) map[string]*int16 { + dst := make(map[string]*int16) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// Int16ValueMap converts a string map of int16 pointers into a string +// map of int16 values +func Int16ValueMap(src map[string]*int16) map[string]int16 { + dst := make(map[string]int16) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Int32 returns a pointer to the int32 value passed in. +func Int32(v int32) *int32 { + return &v +} + +// Int32Value returns the value of the int32 pointer passed in or +// 0 if the pointer is nil. +func Int32Value(v *int32) int32 { + if v != nil { + return *v + } + return 0 +} + +// Int32Slice converts a slice of int32 values into a slice of +// int32 pointers +func Int32Slice(src []int32) []*int32 { + dst := make([]*int32, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// Int32ValueSlice converts a slice of int32 pointers into a slice of +// int32 values +func Int32ValueSlice(src []*int32) []int32 { + dst := make([]int32, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// Int32Map converts a string map of int32 values into a string +// map of int32 pointers +func Int32Map(src map[string]int32) map[string]*int32 { + dst := make(map[string]*int32) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// Int32ValueMap converts a string map of int32 pointers into a string +// map of int32 values +func Int32ValueMap(src map[string]*int32) map[string]int32 { + dst := make(map[string]int32) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Int64 returns a pointer to the int64 value passed in. +func Int64(v int64) *int64 { + return &v +} + +// Int64Value returns the value of the int64 pointer passed in or +// 0 if the pointer is nil. +func Int64Value(v *int64) int64 { + if v != nil { + return *v + } + return 0 +} + +// Int64Slice converts a slice of int64 values into a slice of +// int64 pointers +func Int64Slice(src []int64) []*int64 { + dst := make([]*int64, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// Int64ValueSlice converts a slice of int64 pointers into a slice of +// int64 values +func Int64ValueSlice(src []*int64) []int64 { + dst := make([]int64, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// Int64Map converts a string map of int64 values into a string +// map of int64 pointers +func Int64Map(src map[string]int64) map[string]*int64 { + dst := make(map[string]*int64) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// Int64ValueMap converts a string map of int64 pointers into a string +// map of int64 values +func Int64ValueMap(src map[string]*int64) map[string]int64 { + dst := make(map[string]int64) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Uint8 returns a pointer to the uint8 value passed in. +func Uint8(v uint8) *uint8 { + return &v +} + +// Uint8Value returns the value of the uint8 pointer passed in or +// 0 if the pointer is nil. +func Uint8Value(v *uint8) uint8 { + if v != nil { + return *v + } + return 0 +} + +// Uint8Slice converts a slice of uint8 values into a slice of +// uint8 pointers +func Uint8Slice(src []uint8) []*uint8 { + dst := make([]*uint8, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// Uint8ValueSlice converts a slice of uint8 pointers into a slice of +// uint8 values +func Uint8ValueSlice(src []*uint8) []uint8 { + dst := make([]uint8, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// Uint8Map converts a string map of uint8 values into a string +// map of uint8 pointers +func Uint8Map(src map[string]uint8) map[string]*uint8 { + dst := make(map[string]*uint8) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// Uint8ValueMap converts a string map of uint8 pointers into a string +// map of uint8 values +func Uint8ValueMap(src map[string]*uint8) map[string]uint8 { + dst := make(map[string]uint8) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Uint16 returns a pointer to the uint16 value passed in. +func Uint16(v uint16) *uint16 { + return &v +} + +// Uint16Value returns the value of the uint16 pointer passed in or +// 0 if the pointer is nil. +func Uint16Value(v *uint16) uint16 { + if v != nil { + return *v + } + return 0 +} + +// Uint16Slice converts a slice of uint16 values into a slice of +// uint16 pointers +func Uint16Slice(src []uint16) []*uint16 { + dst := make([]*uint16, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// Uint16ValueSlice converts a slice of uint16 pointers into a slice of +// uint16 values +func Uint16ValueSlice(src []*uint16) []uint16 { + dst := make([]uint16, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// Uint16Map converts a string map of uint16 values into a string +// map of uint16 pointers +func Uint16Map(src map[string]uint16) map[string]*uint16 { + dst := make(map[string]*uint16) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// Uint16ValueMap converts a string map of uint16 pointers into a string +// map of uint16 values +func Uint16ValueMap(src map[string]*uint16) map[string]uint16 { + dst := make(map[string]uint16) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Uint32 returns a pointer to the uint32 value passed in. +func Uint32(v uint32) *uint32 { + return &v +} + +// Uint32Value returns the value of the uint32 pointer passed in or +// 0 if the pointer is nil. +func Uint32Value(v *uint32) uint32 { + if v != nil { + return *v + } + return 0 +} + +// Uint32Slice converts a slice of uint32 values into a slice of +// uint32 pointers +func Uint32Slice(src []uint32) []*uint32 { + dst := make([]*uint32, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// Uint32ValueSlice converts a slice of uint32 pointers into a slice of +// uint32 values +func Uint32ValueSlice(src []*uint32) []uint32 { + dst := make([]uint32, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// Uint32Map converts a string map of uint32 values into a string +// map of uint32 pointers +func Uint32Map(src map[string]uint32) map[string]*uint32 { + dst := make(map[string]*uint32) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// Uint32ValueMap converts a string map of uint32 pointers into a string +// map of uint32 values +func Uint32ValueMap(src map[string]*uint32) map[string]uint32 { + dst := make(map[string]uint32) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Uint64 returns a pointer to the uint64 value passed in. +func Uint64(v uint64) *uint64 { + return &v +} + +// Uint64Value returns the value of the uint64 pointer passed in or +// 0 if the pointer is nil. +func Uint64Value(v *uint64) uint64 { + if v != nil { + return *v + } + return 0 +} + +// Uint64Slice converts a slice of uint64 values into a slice of +// uint64 pointers +func Uint64Slice(src []uint64) []*uint64 { + dst := make([]*uint64, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// Uint64ValueSlice converts a slice of uint64 pointers into a slice of +// uint64 values +func Uint64ValueSlice(src []*uint64) []uint64 { + dst := make([]uint64, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// Uint64Map converts a string map of uint64 values into a string +// map of uint64 pointers +func Uint64Map(src map[string]uint64) map[string]*uint64 { + dst := make(map[string]*uint64) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// Uint64ValueMap converts a string map of uint64 pointers into a string +// map of uint64 values +func Uint64ValueMap(src map[string]*uint64) map[string]uint64 { + dst := make(map[string]uint64) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Float32 returns a pointer to the float32 value passed in. +func Float32(v float32) *float32 { + return &v +} + +// Float32Value returns the value of the float32 pointer passed in or +// 0 if the pointer is nil. +func Float32Value(v *float32) float32 { + if v != nil { + return *v + } + return 0 +} + +// Float32Slice converts a slice of float32 values into a slice of +// float32 pointers +func Float32Slice(src []float32) []*float32 { + dst := make([]*float32, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// Float32ValueSlice converts a slice of float32 pointers into a slice of +// float32 values +func Float32ValueSlice(src []*float32) []float32 { + dst := make([]float32, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// Float32Map converts a string map of float32 values into a string +// map of float32 pointers +func Float32Map(src map[string]float32) map[string]*float32 { + dst := make(map[string]*float32) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// Float32ValueMap converts a string map of float32 pointers into a string +// map of float32 values +func Float32ValueMap(src map[string]*float32) map[string]float32 { + dst := make(map[string]float32) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Float64 returns a pointer to the float64 value passed in. +func Float64(v float64) *float64 { + return &v +} + +// Float64Value returns the value of the float64 pointer passed in or +// 0 if the pointer is nil. +func Float64Value(v *float64) float64 { + if v != nil { + return *v + } + return 0 +} + +// Float64Slice converts a slice of float64 values into a slice of +// float64 pointers +func Float64Slice(src []float64) []*float64 { + dst := make([]*float64, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// Float64ValueSlice converts a slice of float64 pointers into a slice of +// float64 values +func Float64ValueSlice(src []*float64) []float64 { + dst := make([]float64, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// Float64Map converts a string map of float64 values into a string +// map of float64 pointers +func Float64Map(src map[string]float64) map[string]*float64 { + dst := make(map[string]*float64) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// Float64ValueMap converts a string map of float64 pointers into a string +// map of float64 values +func Float64ValueMap(src map[string]*float64) map[string]float64 { + dst := make(map[string]float64) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} + +// Time returns a pointer to the time.Time value passed in. +func Time(v time.Time) *time.Time { + return &v +} + +// TimeValue returns the value of the time.Time pointer passed in or +// time.Time{} if the pointer is nil. +func TimeValue(v *time.Time) time.Time { + if v != nil { + return *v + } + return time.Time{} +} + +// SecondsTimeValue converts an int64 pointer to a time.Time value +// representing seconds since Epoch or time.Time{} if the pointer is nil. +func SecondsTimeValue(v *int64) time.Time { + if v != nil { + return time.Unix((*v / 1000), 0) + } + return time.Time{} +} + +// MillisecondsTimeValue converts an int64 pointer to a time.Time value +// representing milliseconds sinch Epoch or time.Time{} if the pointer is nil. +func MillisecondsTimeValue(v *int64) time.Time { + if v != nil { + return time.Unix(0, (*v * 1000000)) + } + return time.Time{} +} + +// TimeUnixMilli returns a Unix timestamp in milliseconds from "January 1, 1970 UTC". +// The result is undefined if the Unix time cannot be represented by an int64. +// Which includes calling TimeUnixMilli on a zero Time is undefined. +// +// This utility is useful for service API's such as CloudWatch Logs which require +// their unix time values to be in milliseconds. +// +// See Go stdlib https://golang.org/pkg/time/#Time.UnixNano for more information. +func TimeUnixMilli(t time.Time) int64 { + return t.UnixNano() / int64(time.Millisecond/time.Nanosecond) +} + +// TimeSlice converts a slice of time.Time values into a slice of +// time.Time pointers +func TimeSlice(src []time.Time) []*time.Time { + dst := make([]*time.Time, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// TimeValueSlice converts a slice of time.Time pointers into a slice of +// time.Time values +func TimeValueSlice(src []*time.Time) []time.Time { + dst := make([]time.Time, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// TimeMap converts a string map of time.Time values into a string +// map of time.Time pointers +func TimeMap(src map[string]time.Time) map[string]*time.Time { + dst := make(map[string]*time.Time) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// TimeValueMap converts a string map of time.Time pointers into a string +// map of time.Time values +func TimeValueMap(src map[string]*time.Time) map[string]time.Time { + dst := make(map[string]time.Time) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} diff --git a/worker/controllers/helmapp/detector.go b/worker/controllers/helmapp/detector.go index cfd9e4464..19652793c 100644 --- a/worker/controllers/helmapp/detector.go +++ b/worker/controllers/helmapp/detector.go @@ -15,7 +15,7 @@ type Detector struct { func NewDetector(helmApp *v1alpha1.HelmApp, status *Status, h *helm.Helm, repo *helm.Repo) *Detector { appStore := helmApp.Spec.AppStore - app := helm.NewApp(helmApp.Spec.AppName, helmApp.Namespace, helmApp.Spec.AppName, appStore.Name, helmApp.Spec.Version, h) + app := helm.NewApp(helmApp.Name, helmApp.Namespace, helmApp.Spec.TemplateName, appStore.Name, helmApp.Spec.Version, h) return &Detector{ helmApp: helmApp, status: status, @@ -42,7 +42,7 @@ func (d *Detector) Detect() error { // pull chart if !d.status.IsConditionTrue(v1alpha1.HelmAppChartReady) { - err := d.app.Pull(d.helmApp.Spec.AppStore.Name + "/" + d.helmApp.Spec.AppName) + err := d.app.Pull() if err != nil { d.status.UpdateCondition(v1alpha1.NewHelmAppCondition( v1alpha1.HelmAppChartReady, corev1.ConditionFalse, "ChartFailed", err.Error())) diff --git a/worker/controllers/helmapp/helm/app.go b/worker/controllers/helmapp/helm/app.go index fb60ad8cb..8cfb092ee 100644 --- a/worker/controllers/helmapp/helm/app.go +++ b/worker/controllers/helmapp/helm/app.go @@ -3,45 +3,46 @@ package helm import ( "bytes" "encoding/base64" - "github.com/sirupsen/logrus" - "helm.sh/helm/v3/pkg/action" - "helm.sh/helm/v3/pkg/cli" "io/fs" "io/ioutil" "path" "path/filepath" "strings" + + "github.com/sirupsen/logrus" + "helm.sh/helm/v3/pkg/action" + "helm.sh/helm/v3/pkg/cli" ) type App struct { - name string - repo string - releaseName string - namespace string - version string - chartDir string + templateName string + repo string + name string + namespace string + version string + chartDir string helm *Helm } func (a *App) Chart() string { - return a.repo + "/" + a.name + return a.repo + "/" + a.templateName } // TODO: use appName and templateName -func NewApp(releaseName string, namespace, name, repo string, version string, helm *Helm) *App { +func NewApp(name, namespace, templateName, repo string, version string, helm *Helm) *App { return &App{ - name: name, - repo: repo, - releaseName: releaseName, - namespace: namespace, - version: version, - helm: helm, - chartDir: "/tmp/helm/chart", + name: name, + namespace: namespace, + templateName: templateName, + repo: repo, + version: version, + helm: helm, + chartDir: "/tmp/helm/chart", } } -func (a *App) Pull(chart string) error { +func (a *App) Pull() error { client := action.NewPull() settings := cli.New() settings.RepositoryConfig = a.helm.repoFile @@ -50,7 +51,7 @@ func (a *App) Pull(chart string) error { client.DestDir = a.chartDir client.Version = a.version - output, err := client.Run(chart) + output, err := client.Run(a.chart()) if err != nil { return err } @@ -58,14 +59,18 @@ func (a *App) Pull(chart string) error { return nil } +func (a *App) chart() string { + return a.repo + "/" + a.templateName +} + func (a *App) PreInstall() error { var buf bytes.Buffer - return a.helm.PreInstall(a.name, a.namespace, a.Chart(), &buf) + return a.helm.PreInstall(a.templateName, a.namespace, a.Chart(), &buf) } func (a *App) ParseChart() (string, error) { - //chartPath := path.Join(a.chartDir, a.name + a.version + ".tgz") - chartDir := path.Join(a.chartDir, a.name) + //chartPath := path.Join(a.chartDir, a.templateName + a.version + ".tgz") + chartDir := path.Join(a.chartDir, a.templateName) var values string err := filepath.Walk(chartDir, func(path string, info fs.FileInfo, err error) error { diff --git a/worker/controllers/helmapp/helm/repo.go b/worker/controllers/helmapp/helm/repo.go index c17a1cbd6..a706408d5 100644 --- a/worker/controllers/helmapp/helm/repo.go +++ b/worker/controllers/helmapp/helm/repo.go @@ -4,19 +4,20 @@ import ( "bytes" "context" "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" + "github.com/gofrs/flock" "github.com/pkg/errors" "github.com/sirupsen/logrus" "helm.sh/helm/v3/pkg/cli" "helm.sh/helm/v3/pkg/getter" "helm.sh/helm/v3/pkg/repo" - "io" - "io/ioutil" - "os" - "path/filepath" "sigs.k8s.io/yaml" - "strings" - "time" ) // Repositories that have been permanently deleted and no longer work @@ -37,8 +38,8 @@ type Repo struct { // NewRepo creates a new repo. func NewRepo(repoFile, repoCache string) *Repo { return &Repo{ - repoFile: repoFile, - repoCache: repoCache, + repoFile: repoFile, + repoCache: repoCache, } } @@ -100,15 +101,15 @@ func (o *Repo) add(out io.Writer, name, url, username, password string) error { } // If the repo exists do one of two things: - // 1. If the configuration for the name is the same continue without error + // 1. If the configuration for the templateName is the same continue without error // 2. When the config is different require --force-update if !o.forceUpdate && f.Has(name) { existing := f.Get(name) if c != *existing { - // The input coming in for the name is different from what is already + // The input coming in for the templateName is different from what is already // configured. Return an error. - return errors.Errorf("repository name (%s) already exists, please specify a different name", name) + return errors.Errorf("repository templateName (%s) already exists, please specify a different templateName", name) } // The add is idempotent so do nothing