diff --git a/t1-orch/.gitignore b/t1-orch/.gitignore new file mode 100644 index 0000000..3e131c0 --- /dev/null +++ b/t1-orch/.gitignore @@ -0,0 +1,3 @@ +vendor +.idea +.vscode \ No newline at end of file diff --git a/t1-orch/application/adapters/consul-provider/convert-from-provider.go b/t1-orch/application/adapters/consul-provider/convert-from-provider.go new file mode 100644 index 0000000..ab9a8ef --- /dev/null +++ b/t1-orch/application/adapters/consul-provider/convert-from-provider.go @@ -0,0 +1,153 @@ +package consul_provider + +import ( + "net" + "net/http" + "strconv" + "strings" + "time" + + "github.com/khannz/crispy-palm-tree/t1-orch/domain" + "github.com/khannz/crispy-palm-tree/t1-orch/providers/consul" + "github.com/pkg/errors" +) + +var ( + //ErrNonePayload no payload to be pass into =update + ErrNonePayload = errors.New("payload is none") + + //ErrUnsupportedPayload payload is unsupported by package + ErrUnsupportedPayload = errors.New("unsupported payload") +) + +type ( + ServiceTransportData consul.ServiceTransportData + applicationServerTransports []consul.ApplicationServerTransport +) + +func (from ServiceTransportData) ToServiceInfoConf() (domain.ServiceInfoConf, error) { + + var source []consul.ServiceTransport + switch t := from.Payload.(type) { + case consul.ServicesPayload: + source = t.Services + case consul.NonePayload: + return nil, ErrNonePayload + default: + return nil, ErrUnsupportedPayload + } + + servicesInfo := make(domain.ServiceInfoConf, len(source)) + for _, serviceTransport := range source { + var ( + err error + quorum int + helloTimer time.Duration + responseTimer time.Duration + aliveThreshold int + deadThreshold int + applicationServers domain.ApplicationServers + ) + + if quorum, err = strconv.Atoi(serviceTransport.Quorum); err != nil { + return nil, err + } + + if helloTimer, err = time.ParseDuration(serviceTransport.HelloTimer); err != nil { + return nil, err + } + + if responseTimer, err = time.ParseDuration(serviceTransport.ResponseTimer); err != nil { + return nil, err + } + + if aliveThreshold, err = strconv.Atoi(serviceTransport.AliveThreshold); err != nil { + return nil, err + } + + if deadThreshold, err = strconv.Atoi(serviceTransport.DeadThreshold); err != nil { + return nil, err + } + + applicationServers, err = applicationServerTransports(serviceTransport.ApplicationServersTransport). + ApplicationServers( + responseTimer, + aliveThreshold, + deadThreshold, + ) + if err != nil { + return nil, err + } + + serviceInfo := domain.ServiceInfo{ + Address: serviceTransport.IP + ":" + serviceTransport.Port, + IP: serviceTransport.IP, + Port: serviceTransport.Port, + IsUp: false, + BalanceType: serviceTransport.BalanceType, + RoutingType: serviceTransport.RoutingType, + Protocol: serviceTransport.Protocol, + Quorum: quorum, + HealthcheckType: serviceTransport.HealthcheckType, + HelloTimer: helloTimer, + ResponseTimer: responseTimer, + HCNearFieldsMode: false, + HCUserDefinedData: nil, + AliveThreshold: aliveThreshold, + DeadThreshold: deadThreshold, + ApplicationServers: applicationServers, + HCStop: make(chan struct{}, 1), + HCStopped: make(chan struct{}, 1), + } + + if strings.EqualFold(serviceTransport.HealthcheckType, "http") || + strings.EqualFold(serviceTransport.HealthcheckType, "https") { + + if serviceTransport.Uri == "" { + serviceInfo.Uri = "/" + } else { + serviceInfo.Uri = serviceTransport.Uri + } + if len(serviceTransport.ValidResponseCodes) == 0 { + serviceInfo.ValidResponseCodes = []int64{http.StatusOK} + } else { + serviceInfo.ValidResponseCodes = serviceTransport.ValidResponseCodes + } + } + servicesInfo[serviceInfo.Address] = &serviceInfo + } + + return servicesInfo, nil +} + +func (from applicationServerTransports) ApplicationServers(responseTimer time.Duration, aliveThreshold, deadThreshold int) (domain.ApplicationServers, error) { + applicationServers := make(domain.ApplicationServers, len(from)) + for _, applicationServerTransport := range from { + ip, _, err := net.ParseCIDR(applicationServerTransport.IP + "/32") + if err != nil { + return nil, err + } + var internalHC domain.InternalHC + internalHC.HealthcheckType = applicationServerTransport.HealthcheckAddress + internalHC.HealthcheckAddress = applicationServerTransport.HealthcheckAddress + internalHC.ResponseTimer = responseTimer + internalHC.LastIndexForAlive = 0 + internalHC.LastIndexForDead = 0 + internalHC.Mark = int(domain.IPType(ip).Int()) + internalHC.NearFieldsMode = false + internalHC.UserDefinedData = nil + internalHC.AliveThreshold = make([]bool, aliveThreshold) + internalHC.DeadThreshold = make([]bool, deadThreshold) + + applicationServer := domain.ApplicationServer{ + Address: applicationServerTransport.IP + ":" + applicationServerTransport.Port, + IP: applicationServerTransport.IP, + Port: applicationServerTransport.Port, + IsUp: false, + HealthcheckAddress: applicationServerTransport.HealthcheckAddress, + InternalHC: internalHC, + } + applicationServers[applicationServer.Address] = &applicationServer + } + return applicationServers, nil +} diff --git a/t1-orch/application/adapters/waddle-provider/convert-from-provider.go b/t1-orch/application/adapters/waddle-provider/convert-from-provider.go new file mode 100644 index 0000000..b2f6487 --- /dev/null +++ b/t1-orch/application/adapters/waddle-provider/convert-from-provider.go @@ -0,0 +1,69 @@ +package waddle_provider + +import ( + "fmt" + "time" + + "github.com/khannz/crispy-palm-tree/t1-orch/domain" + "github.com/khannz/crispy-palm-tree/t1-orch/providers/waddle" +) + +type ( + ServiceConfigData waddle.ServiceConfigData +) + +func (from ServiceConfigData) ToServiceInfoConf() (domain.ServiceInfoConf, error) { + services := from.GetServices() + + servicesInfo := make(domain.ServiceInfoConf, len(services)) + for _, service := range services { + r := map[string]*domain.ApplicationServer{} + srv := &domain.ServiceInfo{} + + // TODO: no idea what is purpose of Address + srv.Address = fmt.Sprintf("%s:%d", service.GetAddress(), service.GetPort()) + + srv.Protocol = service.GetProtocol().String() + srv.IP = service.GetAddress() + srv.Port = fmt.Sprintf("%d", service.GetPort()) + + srv.BalanceType = service.GetBalancingType().String() + srv.RoutingType = service.GetRoutingType().String() + + // TODO: srv.HealthcheckType = service.Get + + for _, anReal := range service.GetReals() { + /*// + var ( + err error + applicationServers domain.ApplicationServers + ) + */ + + /* + FIXME: until migration to protos-v2.* this logic with overwriting is acceptable + since following values in protos-v1.* should be shared for every Real + */ + hc := anReal.GetHealthcheck() + srv.HelloTimer = time.Duration(hc.GetHelloTimer()) * time.Millisecond + srv.ResponseTimer = time.Duration(hc.GetResponseTimer()) * time.Millisecond + srv.AliveThreshold = int(hc.AliveThreshold) + srv.DeadThreshold = int(hc.DeadThreshold) + srv.HealthcheckType = hc.Type + //srv.Uri = hc.Uri // TODO: does it implemented in core logic + //srv.ValidResponseCodes = hc.ResponseCodes // TODO: does it implemented in core logic + + res := &domain.ApplicationServer{ + Address: fmt.Sprintf("%s:%d", anReal.GetAddress(), anReal.GetPort()), + IP: anReal.GetAddress(), + Port: fmt.Sprintf("%d", anReal.GetPort()), + HealthcheckAddress: fmt.Sprintf("%s:%d", hc.Address, hc.Port), + } + + r[res.Address] = res + } + srv.ApplicationServers = r + servicesInfo[srv.Address] = srv + } + return servicesInfo, nil +} diff --git a/t1-orch/application/consul-models.go b/t1-orch/application/consul-models.go deleted file mode 100644 index d67bf8d..0000000 --- a/t1-orch/application/consul-models.go +++ /dev/null @@ -1,27 +0,0 @@ -package application - -// ServiceTransport ... -type ServiceTransport struct { - IP string `json:"ip"` - Port string `json:"port"` - BalanceType string `json:"balanceType"` - RoutingType string `json:"routingType"` - Protocol string `json:"protocol"` - HealthcheckType string `json:"healthcheckType"` - HelloTimer string `json:"helloTimer"` - ResponseTimer string `json:"responseTimer"` - AliveThreshold string `json:"aliveThreshold"` - DeadThreshold string `json:"deadThreshold"` - Quorum string `json:"quorum"` - // Hysteresis string `json:"hysteresis"` - ApplicationServersTransport []*ApplicationServerTransport `json:"-"` - Uri string `json:"uri"` // only for http(s) hc types - ValidResponseCodes []int64 `json:"validResponseCodes"` // only for http(s) hc types -} - -// ApplicationServerTransport ... -type ApplicationServerTransport struct { - IP string `json:"ip"` - Port string `json:"port"` - HealthcheckAddress string `json:"healthcheckAddress"` -} diff --git a/t1-orch/application/consul-worker.go b/t1-orch/application/consul-worker.go deleted file mode 100644 index 8001bdf..0000000 --- a/t1-orch/application/consul-worker.go +++ /dev/null @@ -1,169 +0,0 @@ -package application - -import ( - "encoding/json" - "fmt" - "time" - - consulapi "github.com/hashicorp/consul/api" - "github.com/khannz/crispy-palm-tree/t1-orch/domain" - "github.com/sirupsen/logrus" -) - -const consulWorkerName = "consul worker" - -// ConsulWorker ... -type ConsulWorker struct { - facade *T1OrchFacade - client *consulapi.Client - kvClient *consulapi.KV - subscribePath string - appServersPath string - serviceManifest string - needToRemoveServicesIfDataEmpty bool - jobChan chan map[string]*domain.ServiceInfo - logging *logrus.Logger -} - -// NewConsulWorker ... -func NewConsulWorker(facade *T1OrchFacade, - consulAddress, - consulSubscribePath, - consulAppServersPath, - serviceManifest string, - logging *logrus.Logger) (*ConsulWorker, error) { - clientAPI := consulapi.DefaultConfig() - clientAPI.Address = consulAddress - client, err := consulapi.NewClient(clientAPI) - if err != nil { - return nil, err - } - return &ConsulWorker{ - facade: facade, - client: client, - kvClient: client.KV(), - subscribePath: consulSubscribePath, - appServersPath: consulAppServersPath, - serviceManifest: serviceManifest, - needToRemoveServicesIfDataEmpty: true, - jobChan: make(chan map[string]*domain.ServiceInfo), - logging: logging, - }, nil -} - -func (consulWorker *ConsulWorker) ConsulConfigWatch() { - defer close(consulWorker.jobChan) - currentIndex := uint64(0) - queryOptions := &consulapi.QueryOptions{WaitIndex: currentIndex} - for { - balancingServices, meta, err := consulWorker.kvClient.Keys(consulWorker.subscribePath, "/", queryOptions) - if err != nil { - consulWorker.logging.WithFields(logrus.Fields{ - "entity": consulWorkerName, - }).Errorf("can't get balancing services: %v", err) - time.Sleep(1 * time.Second) - continue - } - if balancingServices == nil || meta == nil || len(balancingServices) <= 1 { - if consulWorker.needToRemoveServicesIfDataEmpty { - consulWorker.logging.WithFields(logrus.Fields{ - "entity": consulWorkerName, - }).Infof("balancing services not found. started deleting existing services: %v", err) - consulWorker.jobChan <- nil - consulWorker.needToRemoveServicesIfDataEmpty = false - } - time.Sleep(5 * time.Second) - continue - } else if currentIndex == meta.LastIndex { - // ~ every 300-330 sec indexes autocheck - consulWorker.logging.WithFields(logrus.Fields{ - "entity": consulWorkerName, - }).Tracef("metaindex not change: %v", currentIndex) - time.Sleep(1 * time.Second) - continue - } - - consulWorker.needToRemoveServicesIfDataEmpty = true - - currentIndex = meta.LastIndex - - servicesInfo, err := consulWorker.formUpdateServicesInfo(balancingServices) - if err != nil { - consulWorker.logging.WithFields(logrus.Fields{ - "entity": consulWorkerName, - }).Errorf("can't form update services info: %v", err) - time.Sleep(1 * time.Second) - continue - } - - consulWorker.jobChan <- servicesInfo - } -} - -func (consulWorker *ConsulWorker) formUpdateServicesInfo(balancingServices []string) (map[string]*domain.ServiceInfo, error) { - balancingServicesTransportArray := make([]*ServiceTransport, 0, len(balancingServices)-1) - for _, bsPath := range balancingServices { - if bsPath == consulWorker.subscribePath { - continue - } - - applicationServersPaths, _, err := consulWorker.kvClient.Keys(bsPath+consulWorker.appServersPath, "/", nil) - if err != nil { - return nil, fmt.Errorf("can't get application servers paths: %v", err) - } - - if len(applicationServersPaths) <= 1 { - return nil, fmt.Errorf("application servers not found for service %v", bsPath) - } - - applicationServersTransportArray := make([]*ApplicationServerTransport, 0, len(applicationServersPaths)-1) - for _, applicationServersPath := range applicationServersPaths { - if applicationServersPath == bsPath+consulWorker.appServersPath { - continue - } - applicationServerPair, _, err := consulWorker.kvClient.Get(applicationServersPath, nil) - if err != nil { - return nil, fmt.Errorf("can't get application servers pair: %v", err) - } - applicationServerTransport := &ApplicationServerTransport{} - if err := json.Unmarshal(applicationServerPair.Value, applicationServerTransport); err != nil { - return nil, fmt.Errorf("can't get unmarshall application server transport: %v", err) - } - applicationServersTransportArray = append(applicationServersTransportArray, applicationServerTransport) - } - serviceManifestPair, _, err := consulWorker.kvClient.Get(bsPath+consulWorker.serviceManifest, nil) - if err != nil || serviceManifestPair == nil { - return nil, fmt.Errorf("can't get service manifest pair: %v", err) - } - balancingServiceTransport := &ServiceTransport{} - if err := json.Unmarshal(serviceManifestPair.Value, balancingServiceTransport); err != nil { - return nil, fmt.Errorf("can't get unmarshall service transport: %v", err) - } - balancingServiceTransport.ApplicationServersTransport = applicationServersTransportArray - balancingServicesTransportArray = append(balancingServicesTransportArray, balancingServiceTransport) - } - - servicesInfo, err := convertBalancingServicesTransportArrayToDomainModel(balancingServicesTransportArray) - if err != nil { - return nil, fmt.Errorf("can't convert services transport to domain model: %v", err) - } - return servicesInfo, nil -} - -func (consulWorker *ConsulWorker) JobWorker() { - for servicesInfo := range consulWorker.jobChan { - if servicesInfo != nil { - if err := consulWorker.facade.ApplyNewConfig(servicesInfo); err != nil { - consulWorker.logging.WithFields(logrus.Fields{ - "entity": consulWorkerName, - }).Errorf("config update error: %v", err) - } - } else { - if err := consulWorker.facade.RemoveAllConfig(); err != nil { - consulWorker.logging.WithFields(logrus.Fields{ - "entity": consulWorkerName, - }).Errorf("config update error: %v", err) - } - } - } -} diff --git a/t1-orch/application/facade.go b/t1-orch/application/facade.go index 3f4071e..ebee784 100644 --- a/t1-orch/application/facade.go +++ b/t1-orch/application/facade.go @@ -11,7 +11,7 @@ import ( // TODO: agregate errors in facade -const facadeApplyName = "facade apply config" +const facadeApplyName = "facade.ApplyConfig" // T1OrchFacade struct type T1OrchFacade struct { @@ -22,7 +22,7 @@ type T1OrchFacade struct { HealthcheckEntity *healthcheck.HealthcheckEntity GracefulShutdown *domain.GracefulShutdown IDgenerator domain.IDgenerator - RuntimeServices map[string]*domain.ServiceInfo + RuntimeServices domain.ServiceInfoConf Logging *logrus.Logger } @@ -44,16 +44,16 @@ func NewT1OrchFacade(memoryWorker domain.MemoryWorker, HealthcheckEntity: hc, GracefulShutdown: gracefulShutdown, IDgenerator: idGenerator, - RuntimeServices: make(map[string]*domain.ServiceInfo), + RuntimeServices: make(domain.ServiceInfoConf), Logging: logging, } } -func (t1OrchFacade *T1OrchFacade) ApplyNewConfig(updatedServicesInfo map[string]*domain.ServiceInfo) error { +func (t1OrchFacade *T1OrchFacade) ApplyNewConfig(updatedServicesInfo domain.ServiceInfoConf) error { start := time.Now() id := t1OrchFacade.IDgenerator.NewID() // form diff for runtime config - servicesForCreate, servicesForUpdate, servicesForRemove := t1OrchFacade.formDiffForNewConfig(updatedServicesInfo) + servicesForCreate, servicesForUpdate, servicesForRemove := t1OrchFacade.makeDiff4Conf(updatedServicesInfo) t1OrchFacade.Logging.WithFields(logrus.Fields{ "entity": facadeApplyName, "event id": id, @@ -75,54 +75,54 @@ func (t1OrchFacade *T1OrchFacade) ApplyNewConfig(updatedServicesInfo map[string] // TODO: usecases in gorutines if len(servicesForCreate) != 0 { - if err := t1OrchFacade.CreateServices(servicesForCreate, id); err != nil { + if err := t1OrchFacade.createServices(servicesForCreate, id); err != nil { t1OrchFacade.Logging.WithFields(logrus.Fields{ "entity": facadeApplyName, "event id": id, }).Errorf("create services error: %v", err) } else { t1OrchFacade.Logging.WithFields(logrus.Fields{ - "entity": consulWorkerName, + "duration for create services": time.Since(start), }).Infof("create %v services done", len(servicesForCreate)) } } if len(servicesForUpdate) != 0 { - if err := t1OrchFacade.UpdateServices(servicesForUpdate, id); err != nil { + if err := t1OrchFacade.updateServices(servicesForUpdate, id); err != nil { t1OrchFacade.Logging.WithFields(logrus.Fields{ "entity": facadeApplyName, "event id": id, }).Errorf("update services error: %v", err) } else { t1OrchFacade.Logging.WithFields(logrus.Fields{ - "entity": consulWorkerName, + "entity": facadeApplyName, "duration for create services": time.Since(start), }).Infof("update %v services done", len(servicesForUpdate)) } } if len(servicesForRemove) != 0 { - if err := t1OrchFacade.RemoveServices(servicesForRemove, id); err != nil { + if err := t1OrchFacade.removeServices(servicesForRemove, id); err != nil { t1OrchFacade.Logging.WithFields(logrus.Fields{ "entity": facadeApplyName, "event id": id, }).Errorf("remove services error: %v", err) } else { t1OrchFacade.Logging.WithFields(logrus.Fields{ - "entity": consulWorkerName, + "entity": facadeApplyName, "duration for create services": time.Since(start), }).Infof("remove %v services done", len(servicesForRemove)) } } t1OrchFacade.Logging.WithFields(logrus.Fields{ - "entity": consulWorkerName, + "entity": facadeApplyName, "duration for apply new config": time.Since(start), }).Info("apply config done") return nil } -func (t1OrchFacade *T1OrchFacade) CreateServices(servicesForCreate map[string]*domain.ServiceInfo, +func (t1OrchFacade *T1OrchFacade) createServices(servicesForCreate domain.ServiceInfoConf, id string) error { newNewServiceEntity := usecase.NewNewServiceEntity(t1OrchFacade.MemoryWorker, t1OrchFacade.TunnelWorker, @@ -139,7 +139,7 @@ func (t1OrchFacade *T1OrchFacade) CreateServices(servicesForCreate map[string]*d return nil } -func (t1OrchFacade *T1OrchFacade) RemoveServices(servicesForRemove map[string]*domain.ServiceInfo, +func (t1OrchFacade *T1OrchFacade) removeServices(servicesForRemove domain.ServiceInfoConf, id string) error { newRemoveServiceEntity := usecase.NewRemoveServiceEntity(t1OrchFacade.MemoryWorker, t1OrchFacade.TunnelWorker, @@ -156,7 +156,7 @@ func (t1OrchFacade *T1OrchFacade) RemoveServices(servicesForRemove map[string]*d return nil } -func (t1OrchFacade *T1OrchFacade) UpdateServices(servicesForUpdate map[string]*domain.ServiceInfo, +func (t1OrchFacade *T1OrchFacade) updateServices(servicesForUpdate domain.ServiceInfoConf, id string) error { newUpdateServiceEntity := usecase.NewUpdateServiceEntity(t1OrchFacade.MemoryWorker, t1OrchFacade.TunnelWorker, @@ -173,7 +173,7 @@ func (t1OrchFacade *T1OrchFacade) UpdateServices(servicesForUpdate map[string]*d return nil } -func (t1OrchFacade *T1OrchFacade) RemoveAllConfig() error { +func (t1OrchFacade *T1OrchFacade) RemoveAllConfigs() error { start := time.Now() id := t1OrchFacade.IDgenerator.NewID() servicesForRemove := t1OrchFacade.MemoryWorker.GetServices() @@ -201,16 +201,16 @@ func (t1OrchFacade *T1OrchFacade) RemoveAllConfig() error { } } t1OrchFacade.Logging.WithFields(logrus.Fields{ - "entity": consulWorkerName, + "entity": facadeApplyName, "duration for apply new config": time.Since(start), }).Info("remove all services done") return nil } -func (t1OrchFacade *T1OrchFacade) formDiffForNewConfig(updatedServicesInfo map[string]*domain.ServiceInfo) (map[string]*domain.ServiceInfo, map[string]*domain.ServiceInfo, map[string]*domain.ServiceInfo) { - servicesForCreate := make(map[string]*domain.ServiceInfo) - servicesForUpdate := make(map[string]*domain.ServiceInfo) - servicesForRemove := make(map[string]*domain.ServiceInfo) +func (t1OrchFacade *T1OrchFacade) makeDiff4Conf(updatedServicesInfo domain.ServiceInfoConf) (c domain.ServiceInfoConf, u domain.ServiceInfoConf, d domain.ServiceInfoConf) { + servicesForCreate := make(domain.ServiceInfoConf) + servicesForUpdate := make(domain.ServiceInfoConf) + servicesForRemove := make(domain.ServiceInfoConf) currentServices := t1OrchFacade.MemoryWorker.GetServices() diff --git a/t1-orch/application/jobs/conf-loaders/consul-loader/loader-cron-job.go b/t1-orch/application/jobs/conf-loaders/consul-loader/loader-cron-job.go new file mode 100644 index 0000000..066b7b8 --- /dev/null +++ b/t1-orch/application/jobs/conf-loaders/consul-loader/loader-cron-job.go @@ -0,0 +1,121 @@ +package consul_loader + +import ( + "context" + "sync" + "sync/atomic" + + appJobs "github.com/gradusp/go-platform/app/jobs" + "github.com/gradusp/go-platform/pkg/backoff" + "github.com/gradusp/go-platform/pkg/patterns/observer" + "github.com/gradusp/go-platform/pkg/scheduler" + "github.com/gradusp/go-platform/pkg/tm" + "github.com/khannz/crispy-palm-tree/t1-orch/providers" + consulProvider "github.com/khannz/crispy-palm-tree/t1-orch/providers/consul" + "github.com/pkg/errors" +) + +//Config config to create job +type Config struct { + ConsulProviderConfig consulProvider.ProviderConfig + JobName string + TaskScheduler scheduler.Scheduler + JobBackoff backoff.Backoff + JobExecutor tm.TaskManger +} + +//NewCronJob new cron job for load data from Consul +func NewCronJob(ctx context.Context, conf Config) (appJobs.JobScheduler, error) { + const api = "consul-loader/NewCronJob" + + provider, err := consulProvider.NewServiceConfigProvider(conf.ConsulProviderConfig) + if err != nil { + return nil, errors.Wrap(err, api) + } + defer func() { + if provider != nil { + _ = provider.Close() + } + }() + loader := &loaderFromConsul{ + provider: provider, + } + jobConf := appJobs.JobSchedulerConf{ + JobID: conf.JobName, + NewTask: loader.produceJob, + Backoff: conf.JobBackoff, + TaskScheduler: conf.TaskScheduler, + } + if t := conf.JobExecutor; t != nil { + jobConf.TaskManager = func(_ context.Context) tm.TaskManger { + return t + } + } + if loader.JobScheduler, err = appJobs.NewJobScheduler(ctx, jobConf); err != nil { + return nil, errors.Wrap(err, api) + } + subj := loader.JobScheduler.Subject() + obs := observer.NewObserver(loader.jobEventsObserver, false, appJobs.OnJobFinished{}) + subj.ObserversAttach(obs) + loader.closers = append(loader.closers, func() error { + subj.ObserversDetach(obs) + return nil + }) + loader.closers = append(loader.closers, loader.JobScheduler.Close) + loader.closers = append(loader.closers, loader.provider.Close) + provider = nil + return loader, nil +} + +//------------------------------------------------------- IMPL -------------------------------------------------// + +type loaderFromConsul struct { + appJobs.JobScheduler + waitIndex uint64 + closeOnce sync.Once + provider providers.ServicesConfigProvider + + closers []func() error +} + +//Close impl io.Closer +func (loader *loaderFromConsul) Close() error { + loader.closeOnce.Do(func() { + closers := loader.closers + loader.closers = nil + for _, c := range closers { + _ = c() + } + }) + return nil +} + +func (loader *loaderFromConsul) produceJob(ctx context.Context) (tm.Task, []interface{}, error) { + task, err := tm.MakeSimpleTask("1", loader.provider.Get) + if err != nil { + return nil, nil, err + } + args := []interface{}{ctx} + if idx := atomic.LoadUint64(&loader.waitIndex); idx != 0 { + args = append(args, consulProvider.WithWaitIndex{WaitIndex: idx}) + } + return task, args, nil +} + +func (loader *loaderFromConsul) jobEventsObserver(event observer.EventType) { + switch evt := event.(type) { + case appJobs.OnJobFinished: + out, ok := evt.JobResult.(appJobs.JobOutput) + if !ok { + return + } + for _, o := range out.Output { + if jobOutput, _ := o.(providers.ServicesConfig); jobOutput != nil { + if p1, ok := jobOutput.(consulProvider.ServiceTransportData); ok { + atomic.StoreUint64(&loader.waitIndex, p1.QueryMeta.LastIndex) + return + } + } + } + } +} diff --git a/t1-orch/application/jobs/conf-loaders/waddle-loader/loader-cron-job.go b/t1-orch/application/jobs/conf-loaders/waddle-loader/loader-cron-job.go new file mode 100644 index 0000000..1e49792 --- /dev/null +++ b/t1-orch/application/jobs/conf-loaders/waddle-loader/loader-cron-job.go @@ -0,0 +1,66 @@ +package waddle_loader + +import ( + "context" + "time" + + appJobs "github.com/gradusp/go-platform/app/jobs" + "github.com/gradusp/go-platform/pkg/backoff" + "github.com/gradusp/go-platform/pkg/scheduler" + "github.com/gradusp/go-platform/pkg/tm" + "github.com/khannz/crispy-palm-tree/t1-orch/providers" + "github.com/khannz/crispy-palm-tree/t1-orch/providers/waddle" + "github.com/pkg/errors" +) + +//Config config to create job +type Config struct { + Provider providers.ServicesConfigProvider //is not owned + JobName string + JobMaxDuration time.Duration + NodeIP string + TaskScheduler scheduler.Scheduler //is not owned + JobBackoff backoff.Backoff + JobExecutor tm.TaskManger //is not owned +} + +type loader = Config + +//NewCronJob ... +func NewCronJob(ctx context.Context, conf Config) (appJobs.JobScheduler, error) { + const api = "waddle-loader/NewCronJob" + + jobConf := appJobs.JobSchedulerConf{ + JobID: conf.JobName, + NewTask: conf.produceJob, + Backoff: conf.JobBackoff, + TaskScheduler: conf.TaskScheduler, + } + if t := conf.JobExecutor; t != nil { + jobConf.TaskManager = func(_ context.Context) tm.TaskManger { + return t + } + } + sched, err := appJobs.NewJobScheduler(ctx, jobConf) + return sched, errors.Wrap(err, api) +} + +func (loader *loader) produceJob(ctx context.Context) (tm.Task, []interface{}, error) { + f := loader.Provider.Get + if loader.JobMaxDuration > 0 { + f = func(ctx context.Context, opts ...providers.GetOption) (providers.ServicesConfig, error) { + ctx1, c := context.WithTimeout(ctx, loader.JobMaxDuration) + defer c() + return loader.Provider.Get(ctx1, opts...) + } + } + task, err := tm.MakeSimpleTask("1", f) + if err != nil { + return nil, nil, err + } + args := []interface{}{ctx} + if len(loader.NodeIP) > 0 { + args = append(args, waddle.WithNodeIP{NodeIp: loader.NodeIP}) + } + return task, args, nil +} diff --git a/t1-orch/application/jobs/consumers/facade-interface.go b/t1-orch/application/jobs/consumers/facade-interface.go new file mode 100644 index 0000000..c9b8fbd --- /dev/null +++ b/t1-orch/application/jobs/consumers/facade-interface.go @@ -0,0 +1,11 @@ +package consumers + +import ( + "github.com/khannz/crispy-palm-tree/t1-orch/domain" +) + +//FacadeInterface facade interface +type FacadeInterface interface { + ApplyNewConfig(updatedServicesInfo domain.ServiceInfoConf) error + RemoveAllConfigs() error +} diff --git a/t1-orch/application/jobs/consumers/facade-job-observer.go b/t1-orch/application/jobs/consumers/facade-job-observer.go new file mode 100644 index 0000000..f765335 --- /dev/null +++ b/t1-orch/application/jobs/consumers/facade-job-observer.go @@ -0,0 +1,99 @@ +package consumers + +import ( + "errors" + "io" + "sync" + + appJobs "github.com/gradusp/go-platform/app/jobs" + "github.com/gradusp/go-platform/pkg/patterns/observer" + consulProviderAdapter "github.com/khannz/crispy-palm-tree/t1-orch/application/adapters/consul-provider" + _ "github.com/khannz/crispy-palm-tree/t1-orch/application/adapters/waddle-provider" + waddleProviderAdapter "github.com/khannz/crispy-palm-tree/t1-orch/application/adapters/waddle-provider" + "github.com/khannz/crispy-palm-tree/t1-orch/providers" + consulProvider "github.com/khannz/crispy-palm-tree/t1-orch/providers/consul" + waddleProvider "github.com/khannz/crispy-palm-tree/t1-orch/providers/waddle" + "github.com/sirupsen/logrus" +) + +//NewFacadeConsumer ... +func NewFacadeConsumer(job appJobs.JobScheduler, facade FacadeInterface, logger *logrus.Logger) io.Closer { + ret := &facadeConsumer{ + JobName: job.ID(), + facade: facade, + logger: logger, + } + subj := job.Subject() + obs := observer.NewObserver(ret.observe, false, appJobs.OnJobFinished{}) + subj.ObserversAttach(obs) + ret.close = func() { + subj.ObserversDetach(obs) + } + return ret +} + +//facadeConsumer observer jobs results and run facade methods if need +type facadeConsumer struct { + JobName string + facade FacadeInterface + logger *logrus.Logger + + closeOnce sync.Once + close func() +} + +//Close io.Closer +func (cons *facadeConsumer) Close() error { + cons.closeOnce.Do(func() { + cons.close() + cons.close = nil + }) + return nil +} + +func (cons *facadeConsumer) observe(evt observer.EventType) { + switch fin := evt.(type) { + case appJobs.OnJobFinished: + if fin.JobID != cons.JobName { + return + } + switch t := fin.JobResult.(type) { + case appJobs.JobOutput: + for _, item := range t.Output { + if c, ok := item.(providers.ServicesConfig); ok { + var err error + switch data := c.(type) { + case consulProvider.ServiceTransportData: + err = cons.consumeConsulData(data) + case waddleProvider.ServiceConfigData: + err = cons.consumeWaddleData(data) + } + if err != nil && cons.logger != nil { + cons.logger.WithFields(logrus.Fields{ + "entity": cons.JobName, + }).Errorf("config update error: %v", err) + } + return + } + } + } + } +} + +func (cons *facadeConsumer) consumeConsulData(data consulProvider.ServiceTransportData) error { + converted, err := consulProviderAdapter.ServiceTransportData(data).ToServiceInfoConf() + if err == nil { + err = cons.facade.ApplyNewConfig(converted) + } else if errors.Is(err, consulProviderAdapter.ErrNonePayload) { + err = cons.facade.RemoveAllConfigs() + } + return err +} + +func (cons *facadeConsumer) consumeWaddleData(data waddleProvider.ServiceConfigData) error { + converted, err := waddleProviderAdapter.ServiceConfigData(data).ToServiceInfoConf() + if err == nil { + err = cons.facade.ApplyNewConfig(converted) + } + return err +} diff --git a/t1-orch/application/utils.go b/t1-orch/application/utils.go deleted file mode 100644 index 060ca8b..0000000 --- a/t1-orch/application/utils.go +++ /dev/null @@ -1,130 +0,0 @@ -package application - -import ( - "math/big" - "net" - "strconv" - "time" - - "github.com/khannz/crispy-palm-tree/t1-orch/domain" -) - -func convertBalancingServicesTransportArrayToDomainModel(servicesTransport []*ServiceTransport) (map[string]*domain.ServiceInfo, error) { - servicesInfo := make(map[string]*domain.ServiceInfo, len(servicesTransport)) - for _, serviceTransport := range servicesTransport { - - quorum, err := strconv.Atoi(serviceTransport.Quorum) - if err != nil { - return nil, err - } - - helloTimer, err := time.ParseDuration(serviceTransport.HelloTimer) - if err != nil { - return nil, err - } - - responseTimer, err := time.ParseDuration(serviceTransport.ResponseTimer) - if err != nil { - return nil, err - } - - aliveThreshold, err := strconv.Atoi(serviceTransport.AliveThreshold) - if err != nil { - return nil, err - } - - deadThreshold, err := strconv.Atoi(serviceTransport.DeadThreshold) - if err != nil { - return nil, err - } - - applicationServers, err := convertApplicationServersTransportToDomainModel(serviceTransport.ApplicationServersTransport, - responseTimer, - aliveThreshold, - deadThreshold) - if err != nil { - return nil, err - } - - serviceInfo := &domain.ServiceInfo{ - Address: serviceTransport.IP + ":" + serviceTransport.Port, - IP: serviceTransport.IP, - Port: serviceTransport.Port, - IsUp: false, - BalanceType: serviceTransport.BalanceType, - RoutingType: serviceTransport.RoutingType, - Protocol: serviceTransport.Protocol, - Quorum: quorum, - HealthcheckType: serviceTransport.HealthcheckType, - HelloTimer: helloTimer, - ResponseTimer: responseTimer, - HCNearFieldsMode: false, - HCUserDefinedData: nil, - AliveThreshold: aliveThreshold, - DeadThreshold: deadThreshold, - ApplicationServers: applicationServers, - FailedApplicationServers: domain.NewFailedApplicationServers(), - HCStop: make(chan struct{}, 1), - HCStopped: make(chan struct{}, 1), - } - - if serviceTransport.HealthcheckType == "http" || serviceTransport.HealthcheckType == "https" { - if serviceTransport.Uri == "" { - serviceInfo.Uri = "/" - } else { - serviceInfo.Uri = serviceTransport.Uri - } - if len(serviceTransport.ValidResponseCodes) == 0 { - defaultResponseCode := make([]int64, 1, 1) - defaultResponseCode[0] = 200 - serviceInfo.ValidResponseCodes = defaultResponseCode - } else { - serviceInfo.ValidResponseCodes = serviceTransport.ValidResponseCodes - } - } - - servicesInfo[serviceInfo.Address] = serviceInfo - } - - return servicesInfo, nil -} - -func convertApplicationServersTransportToDomainModel(applicationServersTransport []*ApplicationServerTransport, - responseTimer time.Duration, - aliveThreshold, deadThreshold int) (map[string]*domain.ApplicationServer, error) { - applicationServers := make(map[string]*domain.ApplicationServer, len(applicationServersTransport)) - for _, applicationServerTransport := range applicationServersTransport { - internalHC := domain.InternalHC{} - ip, _, err := net.ParseCIDR(applicationServerTransport.IP + "/32") - if err != nil { - return nil, err - } - internalHC.HealthcheckType = applicationServerTransport.HealthcheckAddress - internalHC.HealthcheckAddress = applicationServerTransport.HealthcheckAddress - internalHC.ResponseTimer = responseTimer - internalHC.LastIndexForAlive = 0 - internalHC.LastIndexForDead = 0 - internalHC.Mark = int(ip4toInt(ip)) - internalHC.NearFieldsMode = false - internalHC.UserDefinedData = nil - internalHC.AliveThreshold = make([]bool, aliveThreshold) - internalHC.DeadThreshold = make([]bool, deadThreshold) - - applicationServer := &domain.ApplicationServer{ - Address: applicationServerTransport.IP + ":" + applicationServerTransport.Port, - IP: applicationServerTransport.IP, - Port: applicationServerTransport.Port, - IsUp: false, - HealthcheckAddress: applicationServerTransport.HealthcheckAddress, - InternalHC: internalHC, - } - applicationServers[applicationServer.Address] = applicationServer - } - return applicationServers, nil -} - -func ip4toInt(ipv4Address net.IP) int64 { - ipv4Int := big.NewInt(0) - ipv4Int.SetBytes(ipv4Address.To4()) - return ipv4Int.Int64() -} diff --git a/t1-orch/cmd/config.go b/t1-orch/cmd/config.go index 87e1030..78e00c9 100644 --- a/t1-orch/cmd/config.go +++ b/t1-orch/cmd/config.go @@ -26,6 +26,14 @@ var ( logging *logrus.Logger ) +const ( + //ConsulDataProvider ... + ConsulDataProvider = "consul" + + //WaddleDataProvider ... + WaddleDataProvider = "waddle" +) + func init() { cobra.OnInitialize(initConfig) @@ -111,6 +119,16 @@ func init() { 2*time.Second, "ipvs request timeout") + rootCmd.PersistentFlags().String("source-provider", + ConsulDataProvider, + "select data provider") + rootCmd.PersistentFlags().String("waddle-address", + "", + "waddle data provider address like tcp://127.0.0.1:9000 | unix:///var/run/waddle.sock") + rootCmd.PersistentFlags().String("waddle-node-ip", + "", + "waddle node IP") + rootCmd.PersistentFlags().String("consul-address", "127.0.0.1:18700", "consul address") @@ -173,6 +191,20 @@ func validateValues() { // logging.Fatalf("t1 id must be set") //} + switch v := viper.GetString("source-provider"); v { + case ConsulDataProvider: + case WaddleDataProvider: + if v := viper.GetString("waddle-address"); len(v) == 0 { + logging.Fatal("unknown 'waddle-address' should be provided") + } + if v := viper.GetString("waddle-node-ip"); len(v) == 0 { + logging.Fatal("unknown 'waddle-node-ip' should be provided") + } + default: + logging.Fatalf("unknown 'source-provider'('%v'); select one from of ['%s', '%s']", + v, ConsulDataProvider, WaddleDataProvider) + } + switch viper.GetString("id-type") { case "nanoid": case "uuid4": diff --git a/t1-orch/cmd/init-cron-jobs.go b/t1-orch/cmd/init-cron-jobs.go new file mode 100644 index 0000000..b156fff --- /dev/null +++ b/t1-orch/cmd/init-cron-jobs.go @@ -0,0 +1,186 @@ +package run + +import ( + "context" + "sync" + "time" + + appJobs "github.com/gradusp/go-platform/app/jobs" + "github.com/gradusp/go-platform/pkg/backoff" + pkgNet "github.com/gradusp/go-platform/pkg/net" + "github.com/gradusp/go-platform/pkg/patterns/observer" + "github.com/gradusp/go-platform/pkg/scheduler" + "github.com/gradusp/go-platform/pkg/tm" + grpcRetry "github.com/grpc-ecosystem/go-grpc-middleware/retry" + consulJobLoader "github.com/khannz/crispy-palm-tree/t1-orch/application/jobs/conf-loaders/consul-loader" + waddleJobLoader "github.com/khannz/crispy-palm-tree/t1-orch/application/jobs/conf-loaders/waddle-loader" + waddleService "github.com/khannz/crispy-palm-tree/t1-orch/external-api/waddle" + "github.com/khannz/crispy-palm-tree/t1-orch/providers" + consulProvider "github.com/khannz/crispy-palm-tree/t1-orch/providers/consul" + "github.com/khannz/crispy-palm-tree/t1-orch/providers/waddle" + "github.com/spf13/viper" + "google.golang.org/grpc" +) + +type jobConstructor struct { + ctx context.Context + taskManger tm.TaskManger + scheduler scheduler.Scheduler + backoff backoff.Backoff + observers []observer.Observer +} + +func (constructor *jobConstructor) constructConsulJob() (appJobs.JobScheduler, error) { + conf := consulJobLoader.Config{ + ConsulProviderConfig: consulProvider.ProviderConfig{ + ConsulAddress: viper.GetString("consul-address"), + ConsulSubscribePath: viper.GetString("consul-subscribe-path"), + ConsulAppServersPath: viper.GetString("consul-app-servers-path"), + ServiceManifest: viper.GetString("consul-manifest-name"), + }, + JobName: "consul-job-loader", + JobExecutor: constructor.taskManger, + TaskScheduler: constructor.scheduler, + JobBackoff: constructor.backoff, + } + ctx, cancel := context.WithCancel(constructor.ctx) + defer func() { + if cancel != nil { + cancel() + } + }() + sourceLoaderJob, err := consulJobLoader.NewCronJob(ctx, conf) + if err != nil { + return nil, err + } + ret := &wrappedJob{ + JobScheduler: sourceLoaderJob, + } + subj := ret.Subject() + subj.ObserversAttach(constructor.observers...) + c := cancel + cancel = nil + ret.closers = append(ret.closers, + func() error { + subj.ObserversDetach(constructor.observers...) + return nil + }, + func() error { + c() + return nil + }, + sourceLoaderJob.Close, + ) + return ret, nil +} + +func (constructor *jobConstructor) constructWaddleJob() (appJobs.JobScheduler, error) { + waddleAddr := viper.GetString("waddle-address") + nodeIP := viper.GetString("waddle-node-ip") + + ctx, cancel := context.WithCancel(constructor.ctx) + defer func() { + if cancel != nil { + cancel() + } + }() + endpoint, err := pkgNet.ParseEndpoint(waddleAddr) + if err != nil { + return nil, err + } + if endpoint.IsUnixDomain() { + waddleAddr = endpoint.FQN() + } else { + waddleAddr = endpoint.String() + } + opts := []grpcRetry.CallOption{ + //grpcRetry.WithBackoff(grpcRetry.BackoffExponential(5 * time.Millisecond)), + grpcRetry.WithBackoff(grpcRetry.BackoffLinear(500 * time.Millisecond)), + grpcRetry.WithMax(10), + } + var gConn *grpc.ClientConn + gConn, err = grpc.DialContext(ctx, + waddleAddr, + grpc.WithInsecure(), + grpc.WithChainUnaryInterceptor(grpcRetry.UnaryClientInterceptor(opts...)), + ) + if err != nil { + return nil, err + } + var client waddleService.NodeInfoServiceClient + client, err = waddleService.NewNodeInfoServiceClient(ctx, gConn) + if err != nil { + return nil, err + } + defer func() { + if client != nil { + _ = client.Close() + } + }() + var dataProv providers.ServicesConfigProvider + dataProv, err = waddle.NewServiceConfigProvider(waddle.ProviderConfig{ + WaddleServiceClient: client, + }) + if err != nil { + return nil, err + } + client = nil + defer func() { + if dataProv != nil { + _ = dataProv.Close() + } + }() + jobConf := waddleJobLoader.Config{ + JobName: "waddle-job-loader", + NodeIP: nodeIP, + Provider: dataProv, + JobExecutor: constructor.taskManger, + TaskScheduler: constructor.scheduler, + JobBackoff: constructor.backoff, + } + var sourceLoaderJob appJobs.JobScheduler + sourceLoaderJob, err = waddleJobLoader.NewCronJob(ctx, jobConf) + if err != nil { + return nil, err + } + + ret := &wrappedJob{ + JobScheduler: sourceLoaderJob, + } + subj := ret.Subject() + subj.ObserversAttach(constructor.observers...) + c := cancel + cancel = nil + ret.closers = append(ret.closers, + func() error { + subj.ObserversDetach(constructor.observers...) + return nil + }, + func() error { + c() + return nil + }, + sourceLoaderJob.Close, + dataProv.Close, + ) + dataProv = nil + return ret, nil +} + +type wrappedJob struct { + appJobs.JobScheduler + closeOnce sync.Once + closers []func() error +} + +//Close io.Closer +func (job *wrappedJob) Close() error { + job.closeOnce.Do(func() { + closers := job.closers + job.closers = nil + for _, c := range closers { + _ = c() + } + }) + return nil +} diff --git a/t1-orch/cmd/run.go b/t1-orch/cmd/run.go index f407f51..97c1567 100644 --- a/t1-orch/cmd/run.go +++ b/t1-orch/cmd/run.go @@ -2,16 +2,26 @@ package run import ( "context" + "errors" "fmt" + "io" "os" "os/signal" "syscall" "time" + appJobs "github.com/gradusp/go-platform/app/jobs" + "github.com/gradusp/go-platform/pkg/backoff" + "github.com/gradusp/go-platform/pkg/functional" + "github.com/gradusp/go-platform/pkg/patterns/observer" + "github.com/gradusp/go-platform/pkg/scheduler" + "github.com/gradusp/go-platform/pkg/tm" "github.com/khannz/crispy-palm-tree/t1-orch/application" + "github.com/khannz/crispy-palm-tree/t1-orch/application/jobs/consumers" "github.com/khannz/crispy-palm-tree/t1-orch/domain" "github.com/khannz/crispy-palm-tree/t1-orch/healthcheck" "github.com/khannz/crispy-palm-tree/t1-orch/portadapter" + consulProvider "github.com/khannz/crispy-palm-tree/t1-orch/providers/consul" "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -29,7 +39,8 @@ var runCmd = &cobra.Command{ idForRootProcess := idGenerator.NewID() // validate fields - logging.WithFields(logrus.Fields{ + + fields := logrus.Fields{ "version": version, "build time": buildTime, "event id": idForRootProcess, @@ -58,15 +69,23 @@ var runCmd = &cobra.Command{ "ipvs address": viper.GetString("ipvs-addr"), "ipvs timeout": viper.GetDuration("ipvs-timeout"), - "consul address": viper.GetString("consul-address"), - "consul subscribe path": viper.GetString("consul-subscribe-path"), - "consul app servers path": viper.GetString("consul-app-servers-path"), - "consul service manifest": viper.GetString("consul-manifest-name"), - + "use data provider": viper.GetString("source-provider"), //"consul"|"waddle" //"t1 id": viper.GetString("t1-id"), - }).Info("") + } + + if viper.GetString("source-provider") == ConsulDataProvider { + fields["consul address"] = viper.GetString("consul-address") + fields["consul subscribe path"] = viper.GetString("consul-subscribe-path") + fields["consul app servers path"] = viper.GetString("consul-app-servers-path") + fields["consul service manifest"] = viper.GetString("consul-manifest-name") + } else { + fields["waddle address"] = viper.GetString("waddle-address") + fields["waddle node IP"] = viper.GetString("waddle-node-ip") + } - gracefulShutdown := &domain.GracefulShutdown{} + logging.WithFields(fields).Info("") + + gracefulShutdown := new(domain.GracefulShutdown) // TODO: global locker. consul and get runtime may concurrent. if consul update => retake runtime after apply @@ -88,7 +107,7 @@ var runCmd = &cobra.Command{ // mem init memoryWorker := &portadapter.MemoryWorker{ - Services: make(map[string]*domain.ServiceInfo), + Services: make(domain.ServiceInfoConf), ApplicationServersTunnelInfo: make(map[string]int), } @@ -119,31 +138,68 @@ var runCmd = &cobra.Command{ idGenerator, logging) - // TODO: unimplemented read runtime - grpcServer := application.NewGrpcServer(viper.GetString("orch-addr"), facade, logging) // gorutine inside - if err := grpcServer.StartServer(); err != nil { - logging.WithFields(logrus.Fields{"event id": idForRootProcess}).Fatalf("grpc server start error: %v", err) + jobScheduleInterval := scheduler.NewConstIntervalScheduler(time.Minute) //TODO: может вынести в конфиг? + jc := &jobConstructor{ + ctx: context.Background(), + taskManger: tm.NewTaskManager(), + scheduler: jobScheduleInterval, + backoff: backoff.ExponentialBackoffBuilder(). + WithInitialInterval(500 * time.Millisecond). + WithMaxInterval(5 * time.Minute). + Build(), + } + jc.observers = append(jc.observers, + observer.NewObserver(func(evt observer.EventType) { + switch t := evt.(type) { + case appJobs.OnJobFinished: + e := t.FindError() + if e == nil { + break + } + isFatal := errors.Is(e, functional.ErrArgsNotMatched2Signature) || + errors.Is(e, consulProvider.ErrDataNotFit2Model) + + if isFatal { + logging.Fatalf("from job '%s' got fataL %v", t.JobID, e) + } + case appJobs.OnJobSchedulerStop: + logging.Fatalf("from job '%s' got fataL %v", t.JobID, t.Reason) + case appJobs.OnJobLog: + logging.Infof("%s", t) + } + }, false, + appJobs.OnJobLog{}, + appJobs.OnJobFinished{}, + appJobs.OnJobSchedulerStop{}, + ), + ) + + var sourceLoaderJob appJobs.JobScheduler + if viper.GetString("source-provider") == ConsulDataProvider { + sourceLoaderJob, err = jc.constructConsulJob() + } else { + sourceLoaderJob, err = jc.constructWaddleJob() } - defer grpcServer.CloseServer() - - // consul worker start - consulWorker, err := application.NewConsulWorker(facade, - viper.GetString("consul-address"), - viper.GetString("consul-subscribe-path"), - viper.GetString("consul-app-servers-path"), - viper.GetString("consul-manifest-name"), - logging) if err != nil { - logging.WithFields(logrus.Fields{"event id": idForRootProcess}).Fatalf("connect to consul fail: %v", err) + logging.Fatal(err.Error()) } - logging.WithFields(logrus.Fields{"event id": idForRootProcess}).Info("connected to consul") - go consulWorker.ConsulConfigWatch() - go consulWorker.JobWorker() + consumerCloser := consumers.NewFacadeConsumer(sourceLoaderJob, facade, logging) - logging.WithFields(logrus.Fields{"event id": idForRootProcess}).Info("orch is running") + // TODO: unimplemented read runtime + grpcServer := application.NewGrpcServer(viper.GetString("orch-addr"), facade, logging) // gorutine inside + if err = grpcServer.StartServer(); err != nil { + logging.WithFields(logrus.Fields{"event id": idForRootProcess}).Fatalf("grpc server start error: %v", err) + } + sourceLoaderJob.Enable(true) + sourceLoaderJob.Schedule() <-signalChan // shutdown signal + for _, c := range []io.Closer{consumerCloser, sourceLoaderJob, jobScheduleInterval} { + _ = c.Close() + } + grpcServer.CloseServer() + logging.WithFields(logrus.Fields{"event id": idForRootProcess}).Info("got shutdown signal") gracefulShutdownUsecases(gracefulShutdown, viper.GetDuration("max-shutdown-time"), logging) @@ -166,7 +222,7 @@ func gracefulShutdownUsecases(gracefulShutdown *domain.GracefulShutdown, maxWait gracefulShutdown.ShutdownNow = true gracefulShutdown.Unlock() - ticker := time.NewTicker(time.Duration(100 * time.Millisecond)) // hardcode + ticker := time.NewTicker(100 * time.Millisecond) // hardcode defer ticker.Stop() ctx, cancel := context.WithTimeout(context.Background(), maxWaitTimeForJobsIsDone) @@ -175,17 +231,17 @@ func gracefulShutdownUsecases(gracefulShutdown *domain.GracefulShutdown, maxWait select { case <-ticker.C: gracefulShutdown.Lock() - if gracefulShutdown.UsecasesJobs <= 0 { + state := gracefulShutdown.UsecasesJobs + gracefulShutdown.Unlock() + if state <= 0 { logging.Info("All jobs is done") - defer gracefulShutdown.Unlock() return } - gracefulShutdown.Unlock() - continue case <-ctx.Done(): gracefulShutdown.Lock() - logging.Warnf("%v jobs is fail when program stop", gracefulShutdown.UsecasesJobs) - defer gracefulShutdown.Unlock() + state := gracefulShutdown.UsecasesJobs + gracefulShutdown.Unlock() + logging.Warnf("%v jobs is fail when program stop", state) return } } diff --git a/t1-orch/cmd/waddle-job_test.go b/t1-orch/cmd/waddle-job_test.go new file mode 100644 index 0000000..4ef25ff --- /dev/null +++ b/t1-orch/cmd/waddle-job_test.go @@ -0,0 +1,247 @@ +package run + +import ( + "context" + "os" + "strings" + "testing" + "time" + + "github.com/golang/protobuf/jsonpb" + appJobs "github.com/gradusp/go-platform/app/jobs" + "github.com/gradusp/go-platform/logger" + "github.com/gradusp/go-platform/pkg/backoff" + pkgNet "github.com/gradusp/go-platform/pkg/net" + "github.com/gradusp/go-platform/pkg/patterns/observer" + "github.com/gradusp/go-platform/pkg/scheduler" + "github.com/gradusp/go-platform/pkg/tm" + "github.com/gradusp/go-platform/server" + waddleService "github.com/gradusp/protos/pkg/waddle" + "github.com/khannz/crispy-palm-tree/t1-orch/application/jobs/consumers" + "github.com/khannz/crispy-palm-tree/t1-orch/domain" + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "go.uber.org/zap" + "google.golang.org/grpc" +) + +type ( + //waddleServerMock mock-waddle сервис + waddleServerMock struct { + mock.Mock + waddleService.UnimplementedNodeServiceServer + } + + //facadeMock mock-фасад Orch + facadeMock struct { + mock.Mock + } +) + +var _ server.APIService = (*waddleServerMock)(nil) + +var payload = ` +{ + "services": [ + { + "reals": [ + { + "id": "435a6d06-aa12-4bcb-aac7-5560ffbd4ebe", + "address": "10.44.222.161/32", + "port": 10013, + "healthcheck": { + "id": "074caade-ba45-4076-835c-fc8df9edda82", + "hello_timer": 1000, + "response_timer": 800, + "alive_threshold": 5, + "dead_threshold": 3, + "quorum": 1, + "hysteresis": 5, + "address": "10.63.58.1", + "port": 10013 + } + }, + { + "id": "5944ef57-78ce-4ec3-8c69-2b6f5f8d3480", + "address": "10.63.38.234/32", + "port": 10013, + "healthcheck": { + "id": "9c4a18c0-58c0-4bed-a325-aabad999e978", + "hello_timer": 1000, + "response_timer": 800, + "alive_threshold": 5, + "dead_threshold": 3, + "quorum": 1, + "hysteresis": 5, + "address": "10.63.58.1", + "port": 10013 + } + } + ], + "id": "b533006f-a879-4948-b2e7-7e36933fd52b", + "protocol": "TCP", + "address": "10.63.58.1", + "port": 10013, + "routing_type": "TUN_IPIP", + "balancing_type": "MAGLEV_HASH_PORT" + } + ] +} +` + +var _ consumers.FacadeInterface = (*facadeMock)(nil) + +//ApplyNewConfig impl consumers.FacadeInterface +func (fm *facadeMock) ApplyNewConfig(a0 domain.ServiceInfoConf) error { + ret := fm.Called(a0) + type f = func(domain.ServiceInfoConf) error + if rf, ok := ret.Get(0).(f); ok { + return rf(a0) + } + return nil +} + +//RemoveAllConfigs impl consumers.FacadeInterface +func (fm *facadeMock) RemoveAllConfigs() error { + ret := fm.Called() + type f = func() error + if rf, ok := ret.Get(0).(f); ok { + return rf() + } + return nil +} + +//GetServices ... +func (srv *waddleServerMock) GetServices(_a0 context.Context, _a1 *waddleService.Node) (*waddleService.ServicesResponse, error) { + ret := srv.Called(_a0, _a1) + var ( + r0 *waddleService.ServicesResponse + r1 error + ) + type f = func(context.Context, *waddleService.Node) (*waddleService.ServicesResponse, error) + if rf, ok := ret.Get(0).(f); ok { + r0, r1 = rf(_a0, _a1) + } + return r0, r1 +} + +func (srv *waddleServerMock) Description() grpc.ServiceDesc { + return waddleService.NodeService_ServiceDesc +} + +func (srv *waddleServerMock) RegisterGRPC(_ context.Context, grpcServer *grpc.Server) error { + waddleService.RegisterNodeServiceServer(grpcServer, srv) + return nil +} + +func setupWaddleServer() (*server.APIServer, error) { + s := new(waddleServerMock) + s.On("GetServices", mock.Anything, mock.Anything). + Return(func(ctx context.Context, req *waddleService.Node) (*waddleService.ServicesResponse, error) { + res := new(waddleService.ServicesResponse) + err := jsonpb.UnmarshalString(payload, res) + return res, err + }) + return server.NewAPIServer(server.WithServices(s)) +} + +/*// +тестируем получения данных из нового источника "WADDLE" +1 -- запускаем CronJob которая каждую минуту получент данные из waddle +2 -- ловим данные из CronJon=b и перенаплавляем в фасад Orch +TODO: все что нижу нужно еще сделать +3 -- транслируем данные из waddle во внутреннюю модель фасада Orch +*/ +//Test_WaddleJobWorksGood ... +func Test_WaddleJobWorksGood(t *testing.T) { + logger.SetLevel(zap.InfoLevel) + err := os.Setenv("WADDLE_ADDRESS", "tcp://127.0.0.1:7001") + if !assert.NoError(t, err) { + return + } + err = os.Setenv("WADDLE_NODE_IP", "1.1.1.1") + if !assert.NoError(t, err) { + return + } + viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) + viper.AutomaticEnv() + + var endPoint *pkgNet.Endpoint + endPoint, err = pkgNet.ParseEndpoint(viper.GetString("waddle-address")) + if !assert.NoError(t, err) { + return + } + + //отводим на тест не более 30-ти секунд + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + //cron-job работает с 3-х секундным интервалом + jobRunsInConstInterval := scheduler.NewConstIntervalScheduler(3 * time.Second) + jc := &jobConstructor{ + ctx: ctx, + taskManger: tm.NewTaskManager(), + scheduler: jobRunsInConstInterval, + backoff: backoff.ExponentialBackoffBuilder(). + WithInitialInterval(500 * time.Millisecond). + WithMaxInterval(5 * time.Minute). + Build(), + } + + jc.observers = append(jc.observers, + observer.NewObserver( + func(evt observer.EventType) { //подключаем observer для логирования из cron-job + switch t := evt.(type) { + case appJobs.OnJobLog: + logger.Infof(ctx, "%s", t) + } + }, false, appJobs.OnJobLog{}, + ), + ) + + var job appJobs.JobScheduler + job, err = jc.constructWaddleJob() //создаем cron-job для получения данных из waddle + if !assert.NoError(t, err) { + return + } + defer job.Close() + + facade := new(facadeMock) + goodResult := make(chan struct{}, 1) + goodResultCount := 0 + facade.On("ApplyNewConfig", mock.Anything). + Return(func(_ domain.ServiceInfoConf) error { + goodResultCount++ + if goodResultCount == 3 { + select { + case goodResult <- struct{}{}: //после 3-х кратк=ного полученя наннхв фасадом - решаем что все хорошо - тест успешный + default: + } + } + return nil + }) + + //создаем consumer для того чтобы данные из cron-job попадали в фасад Orch + facadeConsumerCloser := consumers.NewFacadeConsumer(job, facade, nil) + defer facadeConsumerCloser.Close() + + var serv *server.APIServer + serv, err = setupWaddleServer() + if !assert.NoError(t, err) { + return + } + + job.Schedule() //запускаем cron-job + job.Enable(true) + go func() { + _ = serv.Run(ctx, endPoint) //запускаем waddle mock-сервер + }() + select { + case <-goodResult: + err = nil + case <-ctx.Done(): + err = ctx.Err() + } + assert.NoError(t, err) +} diff --git a/t1-orch/domain/ip-to-int.go b/t1-orch/domain/ip-to-int.go new file mode 100644 index 0000000..9fd7810 --- /dev/null +++ b/t1-orch/domain/ip-to-int.go @@ -0,0 +1,16 @@ +package domain + +import ( + "math/big" + "net" +) + +//IPType ... +type IPType net.IP + +//Int ... +func (ip IPType) Int() int64 { + ipv4Int := big.NewInt(0) + ipv4Int.SetBytes(net.IP(ip).To4()) + return ipv4Int.Int64() +} diff --git a/t1-orch/domain/service-conf-type.go b/t1-orch/domain/service-conf-type.go new file mode 100644 index 0000000..10dae5d --- /dev/null +++ b/t1-orch/domain/service-conf-type.go @@ -0,0 +1,4 @@ +package domain + +//ServiceInfoConf alias to +type ServiceInfoConf = map[string]*ServiceInfo diff --git a/t1-orch/domain/service-struct.go b/t1-orch/domain/service-struct.go index 3ec4157..d2b58b1 100644 --- a/t1-orch/domain/service-struct.go +++ b/t1-orch/domain/service-struct.go @@ -3,35 +3,39 @@ package domain import ( "fmt" "sync" + "sync/atomic" "time" ) // ServiceInfo ... type ServiceInfo struct { sync.RWMutex `json:"-"` - Address string `json:"address"` - IP string `json:"ip"` - Port string `json:"port"` - IsUp bool `json:"isUp"` - BalanceType string `json:"balanceType"` - RoutingType string `json:"routingType"` - Protocol string `json:"protocol"` - Quorum int `json:"quorum"` - HealthcheckType string `json:"healthcheckType"` - HelloTimer time.Duration `json:"helloTimer"` - ResponseTimer time.Duration `json:"responseTimer"` - HCNearFieldsMode bool `json:"hcNearFieldsMode,omitempty"` - HCUserDefinedData map[string]string `json:"hcUserDefinedData,omitempty"` - AliveThreshold int `json:"aliveThreshold"` - DeadThreshold int `json:"deadThreshold"` - ApplicationServers map[string]*ApplicationServer `json:"ApplicationServers"` - Uri string `json:"uri"` // only for http(s) hc types - ValidResponseCodes []int64 `json:"validResponseCodes"` // only for http(s) hc types - FailedApplicationServers *FailedApplicationServers `json:"-"` - HCStop chan struct{} `json:"-"` - HCStopped chan struct{} `json:"-"` + Address string `json:"address"` + IP string `json:"ip"` + Port string `json:"port"` + IsUp bool `json:"isUp"` + BalanceType string `json:"balanceType"` + RoutingType string `json:"routingType"` + Protocol string `json:"protocol"` + Quorum int `json:"quorum"` + HealthcheckType string `json:"healthcheckType"` + HelloTimer time.Duration `json:"helloTimer"` + ResponseTimer time.Duration `json:"responseTimer"` + HCNearFieldsMode bool `json:"hcNearFieldsMode,omitempty"` + HCUserDefinedData map[string]string `json:"hcUserDefinedData,omitempty"` + AliveThreshold int `json:"aliveThreshold"` + DeadThreshold int `json:"deadThreshold"` + ApplicationServers ApplicationServers `json:"ApplicationServers"` + Uri string `json:"uri"` // only for http(s) hc types + ValidResponseCodes []int64 `json:"validResponseCodes"` // only for http(s) hc types + FailedApplicationServers FailedApplicationServers `json:"-"` + HCStop chan struct{} `json:"-"` + HCStopped chan struct{} `json:"-"` } +//ApplicationServers alias +type ApplicationServers = map[string]*ApplicationServer + // ApplicationServer ... type ApplicationServer struct { sync.RWMutex `json:"-"` @@ -97,20 +101,17 @@ func (serviceInfo *ServiceInfo) String() string { } type FailedApplicationServers struct { - sync.Mutex - Wg *sync.WaitGroup - Count int + count int32 +} + +func (failedApplicationServers *FailedApplicationServers) Add(n int) { + atomic.AddInt32(&failedApplicationServers.count, int32(n)) } -func NewFailedApplicationServers() *FailedApplicationServers { - return &FailedApplicationServers{ - Wg: new(sync.WaitGroup), - Count: 0, - } +func (failedApplicationServers *FailedApplicationServers) Count() int { + return int(atomic.LoadInt32(&failedApplicationServers.count)) } -func (failedApplicationServers *FailedApplicationServers) SetFailedApplicationServersToZero() { - failedApplicationServers.Lock() - defer failedApplicationServers.Unlock() - failedApplicationServers.Count = 0 +func (failedApplicationServers *FailedApplicationServers) Set2Zero() { + atomic.StoreInt32(&failedApplicationServers.count, 0) } diff --git a/t1-orch/external-api/waddle/node-info-service.go b/t1-orch/external-api/waddle/node-info-service.go new file mode 100644 index 0000000..99402cd --- /dev/null +++ b/t1-orch/external-api/waddle/node-info-service.go @@ -0,0 +1,63 @@ +package waddle + +import ( + "context" + + "github.com/gradusp/protos/pkg/waddle" + "github.com/pkg/errors" + "google.golang.org/grpc" +) + +type ( + //Node alias + Node = waddle.Node + + //GetServicesRequest request + GetServicesRequest struct { + *Node + } + + //GetServicesResponse response + GetServicesResponse struct { + *waddle.ServicesResponse + } + + //NodeInfoServiceClient ... + NodeInfoServiceClient interface { + Close() error + GetServices(ctx context.Context, in GetServicesRequest, opts ...grpc.CallOption) (GetServicesResponse, error) + } +) + +//NewNodeInfoServiceClient ... +func NewNodeInfoServiceClient(_ context.Context, conn *grpc.ClientConn) (NodeInfoServiceClient, error) { + ret := &nodeInfoService{ + NodeServiceClient: waddle.NewNodeServiceClient(conn), + closer: func() error { + return conn.Close() + }, + } + return ret, nil +} + +var _ NodeInfoServiceClient = (*nodeInfoService)(nil) + +type nodeInfoService struct { + waddle.NodeServiceClient + closer func() error +} + +//Close io.Closer +func (client *nodeInfoService) Close() error { + return client.closer() +} + +func (client *nodeInfoService) GetServices(ctx context.Context, req GetServicesRequest, opts ...grpc.CallOption) (GetServicesResponse, error) { + const api = "NodeInfoClient/GetServices" + var resp GetServicesResponse + r, e := client.NodeServiceClient.GetServices(ctx, req.Node, opts...) + if e == nil { + resp.ServicesResponse = r + } + return resp, errors.Wrap(e, api) +} diff --git a/t1-orch/go.mod b/t1-orch/go.mod index 557a3e8..1c5f984 100644 --- a/t1-orch/go.mod +++ b/t1-orch/go.mod @@ -1,18 +1,40 @@ module github.com/khannz/crispy-palm-tree/t1-orch -go 1.15 +go 1.16 require ( - // github.com/go-playground/validator/v10 v10.2.0 // indirect + github.com/armon/go-metrics v0.3.8 // indirect github.com/gofrs/uuid v3.3.0+incompatible - github.com/golang/protobuf v1.4.2 - github.com/hashicorp/consul/api v1.1.0 + github.com/golang/protobuf v1.5.2 + github.com/gradusp/go-platform v0.0.4-dev + github.com/gradusp/protos v1.1.1 + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 + github.com/hashicorp/consul/api v1.10.0 + github.com/hashicorp/consul/sdk v0.8.0 // indirect + github.com/hashicorp/go-hclog v0.14.1 // indirect + github.com/hashicorp/go-immutable-radix v1.3.0 // indirect + github.com/hashicorp/go-msgpack v0.5.5 // indirect + github.com/hashicorp/go-sockaddr v1.0.2 // indirect + github.com/hashicorp/go-uuid v1.0.2 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/memberlist v0.2.4 // indirect github.com/matoous/go-nanoid v1.4.1 + github.com/miekg/dns v1.1.41 // indirect + github.com/mitchellh/go-testing-interface v1.14.0 // indirect + github.com/mitchellh/mapstructure v1.4.1-0.20210112042008-8ebf2d61a8b4 // indirect + github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.6.0 + github.com/spf13/afero v1.2.2 // indirect github.com/spf13/cobra v0.0.7 - github.com/spf13/pflag v1.0.5 + github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.7.1 + github.com/stretchr/testify v1.7.0 github.com/thevan4/logrus-wrapper v1.0.0 - google.golang.org/grpc v1.33.2 - google.golang.org/protobuf v1.25.0 + go.uber.org/zap v1.17.0 + golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1 // indirect + google.golang.org/grpc v1.40.0 + google.golang.org/protobuf v1.27.1 ) + +//replace github.com/gradusp/go-platform v0.0.1-dev => ./../../../gradusp/go-platform/ +// github.com/go-playground/validator/v10 v10.2.0 // indirect diff --git a/t1-orch/go.sum b/t1-orch/go.sum index 8d7a4d5..47ed3de 100644 --- a/t1-orch/go.sum +++ b/t1-orch/go.sum @@ -5,88 +5,159 @@ cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6A cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.3.8 h1:oOxq3KPj0WhCuy50EhzwiyMyG2ovRQZpZLXQuOh2a/M= +github.com/armon/go-metrics v0.3.8/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs= +github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/spec v0.20.3 h1:uH9RQ6vdyPSs2pSy9fL8QPspDF2AMIMPtmK5coSSjtQ= +github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= +github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= +github.com/golang/glog v0.0.0-20210429001901-424d2337a529 h1:2voWjNECnrZRbfwXxHB1/j8wa6xdKn85B5NzgVL/pTU= +github.com/golang/glog v0.0.0-20210429001901-424d2337a529/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -94,151 +165,242 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c= +github.com/gradusp/go-platform v0.0.4-dev h1:xUF6CGQgG6fnRjahhw+nm3uyYjIwCu4GOlViON/eFBc= +github.com/gradusp/go-platform v0.0.4-dev/go.mod h1:65Mf8T7hGn2g1avQMD04hqQAErXIWSydT/f34JtpwS0= +github.com/gradusp/protos v1.1.1 h1:C24BBhhYIPdbpWcbzkE/+AmDSlMgw3AWvDtOk5X61dQ= +github.com/gradusp/protos v1.1.1/go.mod h1:0XUy2NF3xyVljGExfgXpUBqDFYhZr5s/xZuRN9YgkVU= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/consul/api v1.1.0 h1:BNQPM9ytxj6jbjjdRPioQ94T6YXriSopn0i8COv6SRA= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0 h1:ajue7SzQMywqRjg2fK7dcpc0QhFGpTR2plWfV4EZWR4= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0/go.mod h1:r1hZAcvfFXuYmcKyCJI9wlyOPIZUJl6FCB8Cpca/NLE= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1 h1:LnuDWGNsoajlhGyHJvuWW6FVqRl8JOTPqS6CPTsYjhY= +github.com/hashicorp/consul/api v1.10.0 h1:r4nkRKOem378GREHlWdLDROSlDkQFf1VeLX+Ee02EdI= +github.com/hashicorp/consul/api v1.10.0/go.mod h1:sDjTOq0yUyv5G4h+BqSea7Fn6BU+XbolEz1952UB+mk= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/consul/sdk v0.7.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM= +github.com/hashicorp/consul/sdk v0.8.0 h1:OJtKBtEjboEZvG6AOUdh4Z1Zbyu0WcxQ0qatRrZHTVU= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU= +github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= +github.com/hashicorp/go-immutable-radix v1.3.0 h1:8exGP7ego3OmkfksihtSouGMZ+hQrhxx+FVELeXpVPE= +github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= +github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= +github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= +github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= +github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= +github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/memberlist v0.2.4 h1:OOhYzSvFnkFQXm1ysE8RjXTHsqSRDyP4emusC9K7DYg= +github.com/hashicorp/memberlist v0.2.4/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/serf v0.9.5 h1:EBWvyu9tcRszt3Bxp3KNssBMP1KuHWyO51lz9+786iM= +github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/khannz/crispy-palm-tree v0.0.0-20201120090958-f2f5940dfa73 h1:tldq0q/lncQoXjvkBmXkCjkDlN6Dv7HeUh2uyIzNnvk= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/matoous/go-nanoid v1.4.1 h1:Yag04X+qPMDtYbyJsMDhoe8rP5kRl293b2QK8KRp2SE= github.com/matoous/go-nanoid v1.4.1/go.mod h1:fvGBnhcQ+zcrB3qJIG32PAN11J/y1IYkGX2/VeHzuH0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.14.0 h1:/x0XQ6h+3U3nAyk1yx+bHPURrKa9sVVvYbuqZ7pIAtI= +github.com/mitchellh/go-testing-interface v1.14.0/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1-0.20210112042008-8ebf2d61a8b4 h1:MGwxzM4mdkhmCfDyEmSfng7tE1QRIUGbedKdaMksvjw= +github.com/mitchellh/mapstructure v1.4.1-0.20210112042008-8ebf2d61a8b4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= +github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.7 h1:FfTH+vuMXOas8jmfb5/M7dzEYx7LpcLb7a0LPe34uOU= @@ -252,45 +414,79 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/thevan4/logrus-graylog-http-hook v1.1.0 h1:/+oPJ/zaQZ2S3UQj557OZgHvle+869b2Z/i/2rKszlA= github.com/thevan4/logrus-graylog-http-hook v1.1.0/go.mod h1:pbIqCSdtVgRweLWcba2CtyWR+0iABe+vDU2FXY51KnI= github.com/thevan4/logrus-wrapper v1.0.0 h1:N1ooVyc69cWjpt+FEY8nqeic21DehkzjXlyDqXXpJoU= github.com/thevan4/logrus-wrapper v1.0.0/go.mod h1:VV93pSU1gooaxurJtU10tr+4u0LK2vqHTYDAWTQ7FNc= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/otel v1.0.0-RC3 h1:kvwiyEkiUT/JaadXzVLI/R1wDO934A7r3Bs2wEe6wqA= +go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ= +go.opentelemetry.io/otel/exporters/jaeger v1.0.0-RC3 h1:pKXuRvOc+5NgM0vv05PVIUetreuM57mcC6QQAKkcqZA= +go.opentelemetry.io/otel/exporters/jaeger v1.0.0-RC3/go.mod h1:UbP19Xlhk9tcRZ+A3PfvyN5ld4X4YrSnzXaYzx1yNLc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.0-RC3 h1:5gOhYk62x9f5NAGSQl9WBc6J5nCI0tuofzMZ/dAR01Q= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.0-RC3/go.mod h1:1tvDhRy/GCexiD9dQZzqwqGnI7/fnZOsi31DyvK3zyQ= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC3 h1:ewSzc2SagdOx0up5xZPigXh1n3SLsNEslc5edHRBVcs= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC3/go.mod h1:Oxmrmpdvm6lM3tkYmHKGWAhi9+9c2rrAEbwSDn0Bvv8= +go.opentelemetry.io/otel/sdk v1.0.0-RC3 h1:iRMkET+EmJUn5mW0hJzygBraXRmrUwzbOtNvTCh/oKs= +go.opentelemetry.io/otel/sdk v1.0.0-RC3/go.mod h1:78H6hyg2fka0NYT9fqGuFLvly2yCxiBXDJAgLKo/2Us= +go.opentelemetry.io/otel/trace v1.0.0-RC3 h1:9F0ayEvlxv8BmNmPbU005WK7hC+7KbOazCPZjNa1yME= +go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.9.0 h1:C0g6TWmQYvjKRnljRULLWUVJGy8Uvu0NEL/5frY2/t4= +go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -300,10 +496,19 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -316,20 +521,52 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1 h1:4qWs8cYYH6PoEFy4dfhDFgoMGkwAcETd+MmPdCPMzUc= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -337,23 +574,61 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -369,21 +644,65 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -393,17 +712,49 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced h1:c5geK1iMU3cDKtFrCVQIcjR3W+JOZMuhIyICMCTbtus= +google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -412,12 +763,18 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -425,11 +782,24 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/t1-orch/healthcheck/healthcheck-adapter.go b/t1-orch/healthcheck/healthcheck-adapter.go index 1b36167..3337d06 100644 --- a/t1-orch/healthcheck/healthcheck-adapter.go +++ b/t1-orch/healthcheck/healthcheck-adapter.go @@ -14,7 +14,7 @@ func PrepareDataForIPVS(rawIP, rawRoutingType, rawBalanceType, rawProtocol string, - rawApplicationServers map[string]*domain.ApplicationServer) (string, + rawApplicationServers domain.ApplicationServers) (string, uint16, uint32, string, @@ -91,7 +91,7 @@ func protocolToUINT16(protocol string) (uint16, error) { } } -func convertRawApplicationServers(rawApplicationServers map[string]*domain.ApplicationServer) (map[string]uint16, error) { +func convertRawApplicationServers(rawApplicationServers domain.ApplicationServers) (map[string]uint16, error) { applicationServers := map[string]uint16{} for _, applicationServer := range rawApplicationServers { diff --git a/t1-orch/healthcheck/healthcheck-cases.go b/t1-orch/healthcheck/healthcheck-cases.go index 1f3b961..3ae213f 100644 --- a/t1-orch/healthcheck/healthcheck-cases.go +++ b/t1-orch/healthcheck/healthcheck-cases.go @@ -14,7 +14,7 @@ const healthcheckName = "healthcheck" // HealthcheckEntity ... type HealthcheckEntity struct { sync.Mutex - runningHealthchecks map[string]*domain.ServiceInfo // TODO: map much better + runningHealthchecks domain.ServiceInfoConf // TODO: map much better // memoryWorker domain.MemoryWorker healthcheckChecker domain.HealthcheckChecker ipvsadm domain.IPVSWorker @@ -39,7 +39,7 @@ func NewHealthcheckEntity( // memoryWorker domain.MemoryWorker, logging *logrus.Logger) *HealthcheckEntity { return &HealthcheckEntity{ - runningHealthchecks: map[string]*domain.ServiceInfo{}, // need for append + runningHealthchecks: domain.ServiceInfoConf{}, // need for append // memoryWorker: memoryWorker, healthcheckChecker: healthcheckChecker, ipvsadm: ipvsadm, @@ -189,7 +189,7 @@ func (hc *HealthcheckEntity) UpdateServiceAtHealthchecks(updateHCService *domain return updateHCService, nil } -func (hc *HealthcheckEntity) enrichApplicationServersHealthchecks(newServiceHealthcheck *domain.ServiceInfo, oldApplicationServers map[string]*domain.ApplicationServer, oldIsUpState bool) { +func (hc *HealthcheckEntity) enrichApplicationServersHealthchecks(newServiceHealthcheck *domain.ServiceInfo, oldApplicationServers domain.ApplicationServers, oldIsUpState bool) { newServiceHealthcheck.Lock() defer newServiceHealthcheck.Unlock() newServiceHealthcheck.IsUp = oldIsUpState @@ -235,13 +235,13 @@ func (hc *HealthcheckEntity) GetServiceState(hcService *domain.ServiceInfo, id s return nil, fmt.Errorf("get service state fail: service %v not found in healthchecks", hcService.Address) } -func (hc *HealthcheckEntity) GetServicesState(id string) (map[string]*domain.ServiceInfo, error) { +func (hc *HealthcheckEntity) GetServicesState(id string) (domain.ServiceInfoConf, error) { hc.Lock() defer hc.Unlock() if len(hc.runningHealthchecks) == 0 { return nil, fmt.Errorf("active hc services: %v", len(hc.runningHealthchecks)) } - copyOfServiceInfos := make(map[string]*domain.ServiceInfo, len(hc.runningHealthchecks)) + copyOfServiceInfos := make(domain.ServiceInfoConf, len(hc.runningHealthchecks)) for i, runHC := range hc.runningHealthchecks { copyOfServiceInfos[i] = copyServiceInfo(runHC) } diff --git a/t1-orch/healthcheck/healthcheck-check-logic.go b/t1-orch/healthcheck/healthcheck-check-logic.go index 023bb49..55ce491 100644 --- a/t1-orch/healthcheck/healthcheck-check-logic.go +++ b/t1-orch/healthcheck/healthcheck-check-logic.go @@ -1,8 +1,10 @@ package healthcheck import ( + "reflect" "time" + "github.com/gradusp/go-platform/pkg/parallel" "github.com/khannz/crispy-palm-tree/t1-orch/domain" "github.com/sirupsen/logrus" ) @@ -36,22 +38,22 @@ func (hc *HealthcheckEntity) startFirstChecksForService(hcService *domain.Servic // FirstChecksForService ... func (hc *HealthcheckEntity) FirstChecksForService(hcService *domain.ServiceInfo) { - defer hcService.FailedApplicationServers.SetFailedApplicationServersToZero() + defer hcService.FailedApplicationServers.Set2Zero() newID := hc.idGenerator.NewID() - for k := range hcService.ApplicationServers { - hcService.FailedApplicationServers.Wg.Add(1) - go hc.checkApplicationServerInService(hcService, - k, - newID) // lock hcService - } - hcService.FailedApplicationServers.Wg.Wait() - percentageUp := percentageOfUp(len(hcService.ApplicationServers), hcService.FailedApplicationServers.Count) + + keys := reflect.ValueOf(hcService.ApplicationServers).MapKeys() + _ = parallel.ExecAbstract(len(keys), 10, func(i int) error { + k := keys[i].Interface().(string) + hc.checkApplicationServerInService(hcService, k, newID) // lock hcService + return nil + }) + percentageUp := percentageOfUp(len(hcService.ApplicationServers), hcService.FailedApplicationServers.Count()) hc.logging.WithFields(logrus.Fields{ "entity": healthcheckName, "event id": newID, }).Tracef("Healthcheck: in service %v failed services is %v of %v; %v up percent of %v max for this service", hcService.Address, - hcService.FailedApplicationServers.Count, + hcService.FailedApplicationServers.Count(), len(hcService.ApplicationServers), percentageUp, hcService.Quorum) @@ -95,22 +97,22 @@ func (hc *HealthcheckEntity) startNormalHealthchecksForService(hcService *domain // CheckService ... func (hc *HealthcheckEntity) CheckService(hcService *domain.ServiceInfo) { - defer hcService.FailedApplicationServers.SetFailedApplicationServersToZero() + defer hcService.FailedApplicationServers.Set2Zero() newID := hc.idGenerator.NewID() - for k := range hcService.ApplicationServers { - hcService.FailedApplicationServers.Wg.Add(1) - go hc.checkApplicationServerInService(hcService, - k, - newID) // lock hcService - } - hcService.FailedApplicationServers.Wg.Wait() - percentageUp := percentageOfUp(len(hcService.ApplicationServers), hcService.FailedApplicationServers.Count) + + keys := reflect.ValueOf(hcService.ApplicationServers).MapKeys() + _ = parallel.ExecAbstract(len(keys), 10, func(i int) error { + k := keys[i].Interface().(string) + hc.checkApplicationServerInService(hcService, k, newID) + return nil + }) + percentageUp := percentageOfUp(len(hcService.ApplicationServers), hcService.FailedApplicationServers.Count()) hc.logging.WithFields(logrus.Fields{ "entity": healthcheckName, "event id": newID, }).Tracef("Healthcheck: in service %v failed services is %v of %v; %v up percent of %v max for this service", hcService.Address, - hcService.FailedApplicationServers.Count, + hcService.FailedApplicationServers.Count(), len(hcService.ApplicationServers), percentageUp, hcService.Quorum) @@ -140,10 +142,8 @@ func (hc *HealthcheckEntity) CheckService(hcService *domain.ServiceInfo) { func (hc *HealthcheckEntity) checkApplicationServerInService(hcService *domain.ServiceInfo, applicationServerInfoKey string, id string) { - // TODO: still can be refactored - defer hcService.FailedApplicationServers.Wg.Done() - isCheckOk := hc.isApplicationServerOkNow(hcService, applicationServerInfoKey, id) + isCheckOk := hc.isApplicationServerOkNow(hcService, applicationServerInfoKey, id) hc.moveApplicationServerStateIndexes(hcService, applicationServerInfoKey, isCheckOk) // lock hcService isApplicationServerUp, isApplicationServerChangeState := hc.isApplicationServerUpAndStateChange(hcService, applicationServerInfoKey, id) // lock hcService hc.logging.WithFields(logrus.Fields{ @@ -160,9 +160,7 @@ func (hc *HealthcheckEntity) checkApplicationServerInService(hcService *domain.S isApplicationServerUp, isApplicationServerChangeState) if !isApplicationServerUp { - hcService.FailedApplicationServers.Lock() - hcService.FailedApplicationServers.Count++ - hcService.FailedApplicationServers.Unlock() + hcService.FailedApplicationServers.Add(1) if isApplicationServerChangeState { if err := hc.excludeApplicationServerFromIPVS(hcService, hcService.ApplicationServers[applicationServerInfoKey], id); err != nil { hc.logging.WithFields(logrus.Fields{ @@ -180,9 +178,7 @@ func (hc *HealthcheckEntity) checkApplicationServerInService(hcService *domain.S isApplicationServerUp, isApplicationServerChangeState) if !isApplicationServerUp { - hcService.FailedApplicationServers.Lock() - hcService.FailedApplicationServers.Count++ - hcService.FailedApplicationServers.Unlock() + hcService.FailedApplicationServers.Add(1) } if isApplicationServerUp && isApplicationServerChangeState { diff --git a/t1-orch/healthcheck/healthcheck-dummy-and-ipvs-calls.go b/t1-orch/healthcheck/healthcheck-dummy-and-ipvs-calls.go index 92e5b1f..6dc85aa 100644 --- a/t1-orch/healthcheck/healthcheck-dummy-and-ipvs-calls.go +++ b/t1-orch/healthcheck/healthcheck-dummy-and-ipvs-calls.go @@ -97,7 +97,7 @@ func (hc *HealthcheckEntity) removeServiceFromIPVS(hcService *domain.ServiceInfo func (hc *HealthcheckEntity) inclideApplicationServerInIPVS(hcService *domain.ServiceInfo, applicationServer *domain.ApplicationServer, id string) error { - aS := map[string]*domain.ApplicationServer{applicationServer.IP + ":" + applicationServer.Port: applicationServer} + aS := domain.ApplicationServers{applicationServer.IP + ":" + applicationServer.Port: applicationServer} vip, port, routingType, balanceType, protocol, applicationServers, err := PrepareDataForIPVS(hcService.IP, hcService.Port, hcService.RoutingType, @@ -139,7 +139,7 @@ func (hc *HealthcheckEntity) inclideApplicationServerInIPVS(hcService *domain.Se func (hc *HealthcheckEntity) excludeApplicationServerFromIPVS(hcService *domain.ServiceInfo, applicationServer *domain.ApplicationServer, id string) error { - aS := map[string]*domain.ApplicationServer{applicationServer.IP + ":" + applicationServer.Port: applicationServer} + aS := domain.ApplicationServers{applicationServer.IP + ":" + applicationServer.Port: applicationServer} vip, port, routingType, balanceType, protocol, applicationServers, err := PrepareDataForIPVS(hcService.IP, hcService.Port, hcService.RoutingType, diff --git a/t1-orch/healthcheck/healthcheck-utils.go b/t1-orch/healthcheck/healthcheck-utils.go index ad60734..94005d4 100644 --- a/t1-orch/healthcheck/healthcheck-utils.go +++ b/t1-orch/healthcheck/healthcheck-utils.go @@ -7,15 +7,10 @@ import ( ) func percentageOfUp(rawTotal, rawDown int) float32 { - total := float32(rawTotal) - down := float32(rawDown) - if down == total { + if rawTotal == 0 || rawTotal < rawDown { return 0 } - if down == 0 { - return 100 - } - return (total - down) * 100 / total + return float32(rawTotal-rawDown) * 100. / float32(rawTotal) } func percentageOfDownBelowMPercentOfAlivedForUp(pofUp float32, maxDownForUp int) bool { @@ -60,7 +55,7 @@ func reverceArray(ar []bool) { } } -func formDiffApplicationServers(newApplicationServers map[string]*domain.ApplicationServer, oldApplicationServers map[string]*domain.ApplicationServer) ([]string, []string, []string) { +func formDiffApplicationServers(newApplicationServers domain.ApplicationServers, oldApplicationServers domain.ApplicationServers) ([]string, []string, []string) { applicationServersForAdd := make([]string, 0) applicationServersForRemove := make([]string, 0) applicationServersAlreadyIN := make([]string, 0) @@ -81,8 +76,8 @@ func formDiffApplicationServers(newApplicationServers map[string]*domain.Applica return applicationServersAlreadyIN, applicationServersForAdd, applicationServersForRemove } -func getCopyOfApplicationServersFromService(serviceInfo *domain.ServiceInfo) map[string]*domain.ApplicationServer { - applicationServers := make(map[string]*domain.ApplicationServer, len(serviceInfo.ApplicationServers)) +func getCopyOfApplicationServersFromService(serviceInfo *domain.ServiceInfo) domain.ApplicationServers { + applicationServers := make(domain.ApplicationServers, len(serviceInfo.ApplicationServers)) for k, applicationServer := range serviceInfo.ApplicationServers { tmpApplicationServerInternal := domain.InternalHC{ HealthcheckType: applicationServer.InternalHC.HealthcheckType, @@ -111,24 +106,30 @@ func getCopyOfApplicationServersFromService(serviceInfo *domain.ServiceInfo) map func (hc *HealthcheckEntity) moveApplicationServerStateIndexes(hcService *domain.ServiceInfo, applicationServerInfoKey string, isUpNow bool) { hcService.Lock() defer hcService.Unlock() + appServer := hcService.ApplicationServers[applicationServerInfoKey] + if appServer == nil { + return + } + internalHC := &appServer.InternalHC + hc.logging.Tracef("moveApplicationServerStateIndexes: app srv index: %v,isUpNow: %v, total app srv at service: %v, AliveThreshold array len: %v, DeadThreshold array len: %v", applicationServerInfoKey, isUpNow, len(hcService.ApplicationServers), - len(hcService.ApplicationServers[applicationServerInfoKey].InternalHC.AliveThreshold), - len(hcService.ApplicationServers[applicationServerInfoKey].InternalHC.DeadThreshold)) + len(internalHC.AliveThreshold), + len(internalHC.DeadThreshold)) - if len(hcService.ApplicationServers[applicationServerInfoKey].InternalHC.AliveThreshold) < hcService.ApplicationServers[applicationServerInfoKey].InternalHC.LastIndexForAlive+1 { - hcService.ApplicationServers[applicationServerInfoKey].InternalHC.LastIndexForAlive = 0 + if len(internalHC.AliveThreshold) < internalHC.LastIndexForAlive+1 { + internalHC.LastIndexForAlive = 0 } - hcService.ApplicationServers[applicationServerInfoKey].InternalHC.AliveThreshold[hcService.ApplicationServers[applicationServerInfoKey].InternalHC.LastIndexForAlive] = isUpNow - hcService.ApplicationServers[applicationServerInfoKey].InternalHC.LastIndexForAlive++ + internalHC.AliveThreshold[internalHC.LastIndexForAlive] = isUpNow + internalHC.LastIndexForAlive++ - if len(hcService.ApplicationServers[applicationServerInfoKey].InternalHC.DeadThreshold) < hcService.ApplicationServers[applicationServerInfoKey].InternalHC.LastIndexForDead+1 { - hcService.ApplicationServers[applicationServerInfoKey].InternalHC.LastIndexForDead = 0 + if len(internalHC.DeadThreshold) < internalHC.LastIndexForDead+1 { + appServer.InternalHC.LastIndexForDead = 0 } - hcService.ApplicationServers[applicationServerInfoKey].InternalHC.DeadThreshold[hcService.ApplicationServers[applicationServerInfoKey].InternalHC.LastIndexForDead] = isUpNow - hcService.ApplicationServers[applicationServerInfoKey].InternalHC.LastIndexForDead++ + internalHC.DeadThreshold[internalHC.LastIndexForDead] = isUpNow + internalHC.LastIndexForDead++ } func copyServiceInfo(hcService *domain.ServiceInfo) *domain.ServiceInfo { diff --git a/t1-orch/portadapter/memory-config.go b/t1-orch/portadapter/memory-config.go index a80fee7..307e9ed 100644 --- a/t1-orch/portadapter/memory-config.go +++ b/t1-orch/portadapter/memory-config.go @@ -10,7 +10,8 @@ import ( // MemoryWorker ... type MemoryWorker struct { sync.Mutex - Services map[string]*domain.ServiceInfo + + Services domain.ServiceInfoConf ApplicationServersTunnelInfo map[string]int } @@ -50,10 +51,15 @@ func (memoryWorker *MemoryWorker) GetService(serviceAddress string) (*domain.Ser return findedServiceInfo, nil } -func (memoryWorker *MemoryWorker) GetServices() map[string]*domain.ServiceInfo { +func (memoryWorker *MemoryWorker) GetServices() domain.ServiceInfoConf { memoryWorker.Lock() defer memoryWorker.Unlock() - return memoryWorker.Services + + c := make(domain.ServiceInfoConf, len(memoryWorker.Services)) + for k, v := range memoryWorker.Services { + c[k] = v + } + return c } func (memoryWorker *MemoryWorker) RemoveService(serviceInfo *domain.ServiceInfo) error { diff --git a/t1-orch/providers/consul/errors.go b/t1-orch/providers/consul/errors.go new file mode 100644 index 0000000..118f7c0 --- /dev/null +++ b/t1-orch/providers/consul/errors.go @@ -0,0 +1,55 @@ +package consul + +import ( + "fmt" + + "github.com/pkg/errors" +) + +//OpConsul consul operation +type OpConsul int + +const ( + //OpKeys get keys + OpKeys OpConsul = 1 + + //OpGet get payload by key + OpGet OpConsul = 2 +) + +//ErrConsul error from consul +type ErrConsul struct { + error + Path string + Op OpConsul +} + +//errors +var ( + + //ErrNotFound entity is not fount by Consul + ErrNotFound = errors.New("not found") + + //ErrDataNotFit2Model when payload data from Consul are not fit to model struct + ErrDataNotFit2Model = errors.New("data are not fot to model") +) + +var op2s = map[OpConsul]string{ + OpKeys: "OpKeys", + OpGet: "OpGet", +} + +//String impl fmt.Stringer +func (op OpConsul) String() string { + return op2s[op] +} + +//Error impl error i-face +func (e ErrConsul) Error() string { + return fmt.Sprintf("Op:%s, Path:'%s', Err:%v", e.Op, e.Path, e.error) +} + +//Cause errors.Causer +func (e ErrConsul) Cause() error { + return e.error +} diff --git a/t1-orch/providers/consul/model.go b/t1-orch/providers/consul/model.go new file mode 100644 index 0000000..4a50b95 --- /dev/null +++ b/t1-orch/providers/consul/model.go @@ -0,0 +1,55 @@ +package consul + +import ( + consulAPI "github.com/hashicorp/consul/api" + "github.com/khannz/crispy-palm-tree/t1-orch/providers" +) + +type ( + //ServiceTransport main entity from Consul + ServiceTransport struct { + IP string `json:"ip"` + Port string `json:"port"` + BalanceType string `json:"balanceType"` + RoutingType string `json:"routingType"` + Protocol string `json:"protocol"` + HealthcheckType string `json:"healthcheckType"` + HelloTimer string `json:"helloTimer"` + ResponseTimer string `json:"responseTimer"` + AliveThreshold string `json:"aliveThreshold"` + DeadThreshold string `json:"deadThreshold"` + Quorum string `json:"quorum"` + // Hysteresis string `json:"hysteresis"` + ApplicationServersTransport []ApplicationServerTransport `json:"-"` + Uri string `json:"uri"` // only for http(s) hc types + ValidResponseCodes []int64 `json:"validResponseCodes"` // only for http(s) hc types + } + + //ApplicationServerTransport ... + ApplicationServerTransport struct { + IP string `json:"ip"` + Port string `json:"port"` + HealthcheckAddress string `json:"healthcheckAddress"` + } + + //ServiceTransportData ... + ServiceTransportData struct { + providers.ServicesConfig `json:"-"` + QueryMeta *consulAPI.QueryMeta `json:"-"` + Payload payload `json:"-"` + } + + payload interface { + isPayloadPrivate() + } + + //ServicesPayload services transport payload + ServicesPayload struct { + payload + Services []ServiceTransport `json:"-"` + } + //NonePayload no payload + NonePayload struct { + payload + } +) diff --git a/t1-orch/providers/consul/provider.go b/t1-orch/providers/consul/provider.go new file mode 100644 index 0000000..c7093ca --- /dev/null +++ b/t1-orch/providers/consul/provider.go @@ -0,0 +1,156 @@ +package consul + +import ( + "context" + "encoding/json" + "sync" + + "github.com/gradusp/go-platform/pkg/parallel" + consulAPI "github.com/hashicorp/consul/api" + "github.com/khannz/crispy-palm-tree/t1-orch/providers" + "github.com/pkg/errors" +) + +//ProviderConfig provider config +type ProviderConfig struct { + ConsulAddress string + ConsulSubscribePath string + ConsulAppServersPath string + ServiceManifest string +} + +//NewServiceConfigProvider new provider +func NewServiceConfigProvider(conf ProviderConfig) (providers.ServicesConfigProvider, error) { + const api = "consul/NewServiceConfigProvider" + + consulConf := consulAPI.DefaultConfig() + consulConf.Address = conf.ConsulAddress + client, err := consulAPI.NewClient(consulConf) + if err != nil { + return nil, errors.Wrap(err, api) + } + + return &providerImpl{ + dataAccessor: client.KV(), + subscribePath: conf.ConsulSubscribePath, + appServersPath: conf.ConsulAppServersPath, + serviceManifest: conf.ServiceManifest, + }, nil +} + +type WithWaitIndex struct { + providers.GetOption + WaitIndex uint64 +} + +var ( + _ providers.GetOption = WithWaitIndex{} +) + +//--------------------------------------------------- Impl --------------------------------------------------- + +type providerImpl struct { + dataAccessor *consulAPI.KV + subscribePath string + appServersPath string + serviceManifest string +} + +//Close impl io.Closer +func (impl *providerImpl) Close() error { + return nil +} + +//Get impl providers.BalancerConfigProvider +func (impl *providerImpl) Get(ctx context.Context, opts ...providers.GetOption) (providers.ServicesConfig, error) { + const api = "consul/ServiceConfigProvide/Get" + + var queryOptions consulAPI.QueryOptions + var index2check uint64 + for _, o := range opts { + switch t := o.(type) { + case WithWaitIndex: + index2check, queryOptions.WaitIndex = t.WaitIndex, t.WaitIndex + } + } + balancingServices, meta, err := impl.dataAccessor.Keys(impl.subscribePath, "/", &queryOptions) + if err != nil { + return nil, errors.Wrap(ErrConsul{error: err, Op: OpKeys, Path: impl.subscribePath}, api) + } + + if index2check != 0 && index2check == meta.LastIndex { + return ServiceTransportData{ + QueryMeta: meta, + Payload: NonePayload{}, + }, nil + } + + var mx sync.Mutex + var services []ServiceTransport + err = parallel.ExecAbstract(len(balancingServices), 10, func(i int) error { + bsPath := balancingServices[i] + if bsPath == impl.subscribePath { + return nil + } + service, e := impl.GetServiceTransport(ctx, bsPath) + if e != nil { + return e + } + mx.Lock() + services = append(services, service) + mx.Unlock() + return nil + }) + if err != nil { + return nil, errors.Wrap(err, api) + } + return ServiceTransportData{ + QueryMeta: meta, + Payload: ServicesPayload{Services: services}, + }, nil +} + +//GetServiceTransport ... +func (impl *providerImpl) GetServiceTransport(_ context.Context, bsPath string) (ServiceTransport, error) { + var ret ServiceTransport + + path := bsPath + impl.serviceManifest + serviceManifest, _, err := impl.dataAccessor.Get(path, nil) + if err != nil { + return ret, ErrConsul{error: err, Op: OpGet, Path: path} + } + if serviceManifest == nil { + return ret, ErrConsul{error: ErrNotFound} + } + if err = json.Unmarshal(serviceManifest.Value, &ret); err != nil { + return ret, errors.Wrapf(ErrDataNotFit2Model, "unmarshall 'ServiceTransport': %v", err) + } + + path = bsPath + impl.appServersPath + applicationServersPaths, _, err := impl.dataAccessor.Keys(path, "/", nil) + if err != nil { + return ret, ErrConsul{error: err, Op: OpKeys, Path: path} + } + + for _, applicationServersPath := range applicationServersPaths { + if applicationServersPath == path { + continue + } + var applicationServerPair *consulAPI.KVPair + applicationServerPair, _, err = impl.dataAccessor.Get(applicationServersPath, nil) + if err != nil { + return ret, ErrConsul{error: err, Op: OpKeys, Path: applicationServersPath} + } + if applicationServerPair == nil { + return ret, ErrConsul{error: ErrNotFound, Op: OpKeys, Path: applicationServersPath} + } + var applicationServerTransport ApplicationServerTransport + if err = json.Unmarshal(applicationServerPair.Value, &applicationServerTransport); err != nil { + return ret, errors.Wrapf(ErrDataNotFit2Model, "unmarshall 'ApplicationServerTransport': %v", err) + } + ret.ApplicationServersTransport = + append(ret.ApplicationServersTransport, applicationServerTransport) + } + + return ret, nil +} diff --git a/t1-orch/providers/service-info-prov.go b/t1-orch/providers/service-info-prov.go new file mode 100644 index 0000000..7d38462 --- /dev/null +++ b/t1-orch/providers/service-info-prov.go @@ -0,0 +1,20 @@ +package providers + +import ( + "context" +) + +//GetOption used for Get +type GetOption interface { + isGetOptionPrivate() //would never be implemented +} + +//ServicesConfig abstract data type +type ServicesConfig interface { + isBalancerDataPrivate() //would never be implemented +} + +type ServicesConfigProvider interface { + Get(ctx context.Context, opts ...GetOption) (ServicesConfig, error) + Close() error +} diff --git a/t1-orch/providers/waddle/provider.go b/t1-orch/providers/waddle/provider.go new file mode 100644 index 0000000..e004d2b --- /dev/null +++ b/t1-orch/providers/waddle/provider.go @@ -0,0 +1,70 @@ +package waddle + +import ( + "context" + + waddleService "github.com/khannz/crispy-palm-tree/t1-orch/external-api/waddle" + "github.com/khannz/crispy-palm-tree/t1-orch/providers" + "github.com/pkg/errors" + "google.golang.org/grpc" +) + +//WithCallOpts call opts +type WithCallOpts struct { + providers.GetOption + CallOptions []grpc.CallOption +} + +//WithNodeIP with node IP +type WithNodeIP struct { + providers.GetOption + NodeIp string +} + +//ServiceConfigData ... +type ServiceConfigData struct { + providers.ServicesConfig `json:"-"` + waddleService.GetServicesResponse +} + +//ProviderConfig ... +type ProviderConfig struct { + DefaultNodeIP string + WaddleServiceClient waddleService.NodeInfoServiceClient //owned +} + +//NewServiceConfigProvider new provider +func NewServiceConfigProvider(conf ProviderConfig) (providers.ServicesConfigProvider, error) { + return &providerImpl{ProviderConfig: conf}, nil +} + +//---------------------------------------------------- IMPL --------------------------------------------------- + +type providerImpl struct { + ProviderConfig +} + +//Close io.Closer +func (impl *providerImpl) Close() error { + return impl.WaddleServiceClient.Close() +} + +func (impl *providerImpl) Get(ctx context.Context, opts ...providers.GetOption) (providers.ServicesConfig, error) { + const api = "waddle/ServiceConfigProvide/Get" + + var callOpts []grpc.CallOption + var req waddleService.GetServicesRequest + req.Node = &waddleService.Node{ + NodeIp: impl.DefaultNodeIP, + } + for _, o := range opts { + switch t := o.(type) { + case WithNodeIP: + req.Node.NodeIp = t.NodeIp + case WithCallOpts: + callOpts = append(callOpts, t.CallOptions...) + } + } + resp, err := impl.WaddleServiceClient.GetServices(ctx, req, callOpts...) + return ServiceConfigData{GetServicesResponse: resp}, errors.Wrap(err, api) +} diff --git a/t1-orch/usecase/update-service.go b/t1-orch/usecase/update-service.go index dad9110..7b9a43b 100644 --- a/t1-orch/usecase/update-service.go +++ b/t1-orch/usecase/update-service.go @@ -110,12 +110,12 @@ func (updateService *UpdateServiceEntity) UpdateService(serviceInfo *domain.Serv } func (updateService *UpdateServiceEntity) formDiffForApplicationServersInfo(currentApplicationServers, - updatedApplicationServers map[string]*domain.ApplicationServer) (map[string]*domain.ApplicationServer, - map[string]*domain.ApplicationServer, - map[string]*domain.ApplicationServer) { - appServersForCreate := make(map[string]*domain.ApplicationServer) - appServersForUpdate := make(map[string]*domain.ApplicationServer) - appServersForRemove := make(map[string]*domain.ApplicationServer) + updatedApplicationServers domain.ApplicationServers) (domain.ApplicationServers, + domain.ApplicationServers, + domain.ApplicationServers) { + appServersForCreate := make(domain.ApplicationServers) + appServersForUpdate := make(domain.ApplicationServers) + appServersForRemove := make(domain.ApplicationServers) for updatedAppServerInfoAddress, updatedAppServerInfo := range updatedApplicationServers { if _, isAppSrvIn := currentApplicationServers[updatedAppServerInfoAddress]; isAppSrvIn {