Rainbond/worker/appm/controller/controller.go
2019-03-12 09:59:09 +08:00

237 lines
6.0 KiB
Go

// RAINBOND, Application Management Platform
// Copyright (C) 2014-2017 Goodrain Co., Ltd.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. For any non-GPL usage of Rainbond,
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
// must be obtained first.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package controller
import (
"context"
"fmt"
"sync"
"github.com/goodrain/rainbond/worker/appm/store"
"github.com/goodrain/rainbond/worker/appm/types/v1"
"github.com/goodrain/rainbond/util"
"k8s.io/client-go/kubernetes"
)
//Controller service operating controller interface
type Controller interface {
Begin()
Stop() error
}
//TypeController controller type
type TypeController string
//TypeStartController start service type
var TypeStartController TypeController = "start"
//TypeStopController start service type
var TypeStopController TypeController = "stop"
//TypeRestartController restart service type
var TypeRestartController TypeController = "restart"
//TypeUpgradeController start service type
var TypeUpgradeController TypeController = "upgrade"
//TypeScalingController start service type
var TypeScalingController TypeController = "scaling"
// TypeApplyRuleController -
var TypeApplyRuleController TypeController = "apply_rule"
// TypeApplyConfigController -
var TypeApplyConfigController TypeController = "apply_config"
//Manager controller manager
type Manager struct {
ctx context.Context
cancel context.CancelFunc
client *kubernetes.Clientset
controllers map[string]Controller
store store.Storer
lock sync.Mutex
}
//NewManager new manager
func NewManager(store store.Storer, client *kubernetes.Clientset) *Manager {
ctx, cancel := context.WithCancel(context.Background())
return &Manager{
ctx: ctx,
cancel: cancel,
client: client,
controllers: make(map[string]Controller),
store: store,
}
}
//Stop stop all controller
func (m *Manager) Stop() error {
m.cancel()
return nil
}
//GetControllerSize get running controller number
func (m *Manager) GetControllerSize() int {
m.lock.Lock()
defer m.lock.Unlock()
return len(m.controllers)
}
//StartController create and start service controller
func (m *Manager) StartController(controllerType TypeController, apps ...v1.AppService) error {
var controller Controller
controllerID := util.NewUUID()
switch controllerType {
case TypeStartController:
controller = &startController{
controllerID: controllerID,
appService: apps,
manager: m,
stopChan: make(chan struct{}),
}
case TypeStopController:
controller = &stopController{
controllerID: controllerID,
appService: apps,
manager: m,
stopChan: make(chan struct{}),
}
case TypeScalingController:
controller = &scalingController{
controllerID: controllerID,
appService: apps,
manager: m,
stopChan: make(chan struct{}),
}
case TypeUpgradeController:
controller = &upgradeController{
controllerID: controllerID,
appService: apps,
manager: m,
stopChan: make(chan struct{}),
}
case TypeRestartController:
controller = &restartController{
controllerID: controllerID,
appService: apps,
manager: m,
stopChan: make(chan struct{}),
}
case TypeApplyRuleController:
controller = &applyRuleController{
controllerID: controllerID,
appService: apps,
manager: m,
stopChan: make(chan struct{}),
}
case TypeApplyConfigController:
controller = &applyConfigController{
controllerID: controllerID,
appService: apps[0],
manager: m,
stopChan: make(chan struct{}),
}
default:
return fmt.Errorf("No support controller")
}
m.lock.Lock()
defer m.lock.Unlock()
m.controllers[controllerID] = controller
go controller.Begin()
return nil
}
func (m *Manager) callback(controllerID string, err error) {
m.lock.Lock()
defer m.lock.Unlock()
delete(m.controllers, controllerID)
}
func getLoggerOption(status string) map[string]string {
return map[string]string{"step": "appruntime", "status": status}
}
//GetCallbackLoggerOption get callback logger
func GetCallbackLoggerOption() map[string]string {
return map[string]string{"step": "callback", "status": "failure"}
}
//GetTimeoutLoggerOption get callback logger
func GetTimeoutLoggerOption() map[string]string {
return map[string]string{"step": "callback", "status": "timeout"}
}
//GetLastLoggerOption get last logger
func GetLastLoggerOption() map[string]string {
return map[string]string{"step": "last", "status": "success"}
}
type sequencelist []sequence
type sequence []*v1.AppService
func (s *sequencelist) Contains(id string) bool {
for _, l := range *s {
for _, l2 := range l {
if l2.ServiceID == id {
return true
}
}
}
return false
}
func (s *sequencelist) Add(ids []*v1.AppService) {
*s = append(*s, ids)
}
func foundsequence(source map[string]*v1.AppService, sl *sequencelist) {
if len(source) == 0 {
return
}
var deleteKey []string
source:
for _, s := range source {
for _, d := range s.Dependces {
if !sl.Contains(d) {
continue source
}
}
deleteKey = append(deleteKey, s.ServiceID)
}
var list []*v1.AppService
for _, d := range deleteKey {
list = append(list, source[d])
delete(source, d)
}
sl.Add(list)
foundsequence(source, sl)
}
func decisionSequence(appService []*v1.AppService) sequencelist {
var sourceIDs = make(map[string]*v1.AppService, len(appService))
for _, a := range appService {
sourceIDs[a.ServiceID] = a
}
var sl sequencelist
foundsequence(sourceIDs, &sl)
return sl
}