blob: b2cb9778cb6149e7a956148a45e3154927e2e562 [file] [log] [blame]
// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package clusterboot
import (
"fmt"
)
import (
"github.com/hashicorp/go-multierror"
)
import (
"github.com/apache/dubbo-go-pixiu/pkg/test/framework/components/cluster"
_ "github.com/apache/dubbo-go-pixiu/pkg/test/framework/components/cluster/kube"
_ "github.com/apache/dubbo-go-pixiu/pkg/test/framework/components/cluster/staticvm"
"github.com/apache/dubbo-go-pixiu/pkg/test/framework/config"
"github.com/apache/dubbo-go-pixiu/pkg/test/scopes"
)
var _ cluster.Factory = factory{}
func NewFactory() cluster.Factory {
return factory{}
}
type factory struct {
configs []cluster.Config
}
func (a factory) Kind() cluster.Kind {
return cluster.Aggregate
}
func (a factory) With(configs ...cluster.Config) cluster.Factory {
return factory{configs: append(a.configs, configs...)}
}
func (a factory) Build() (cluster.Clusters, error) {
scopes.Framework.Infof("=== BEGIN: Building clusters ===")
// use multierror to give as much detail as possible if the config is bad
var errs error
defer func() {
if errs != nil {
scopes.Framework.Infof("=== FAILED: Building clusters ===")
}
}()
allClusters := make(cluster.Map)
var clusters cluster.Clusters
for i, cfg := range a.configs {
c, err := buildCluster(cfg, allClusters)
if err != nil {
errs = multierror.Append(errs, fmt.Errorf("failed building cluster from config %d: %v", i, err))
continue
}
if _, ok := allClusters[c.Name()]; ok {
errs = multierror.Append(errs, fmt.Errorf("more than one cluster named %s", c.Name()))
continue
}
allClusters[c.Name()] = c
clusters = append(clusters, c)
}
if errs != nil {
return nil, errs
}
// validate the topology has no open edges
for _, c := range allClusters {
if primary, ok := allClusters[c.PrimaryName()]; !ok {
errs = multierror.Append(errs, fmt.Errorf("primary %s for %s is not in the topology", c.PrimaryName(), c.Name()))
continue
} else if !validPrimaryOrConfig(primary) {
errs = multierror.Append(errs, fmt.Errorf("primary %s for %s is of kind %s, primaries must be Kubernetes", primary.Name(), c.Name(), primary.Kind()))
continue
}
if cfg, ok := allClusters[c.ConfigName()]; !ok {
errs = multierror.Append(errs, fmt.Errorf("config %s for %s is not in the topology", c.ConfigName(), c.Name()))
continue
} else if !validPrimaryOrConfig(cfg) {
errs = multierror.Append(errs, fmt.Errorf("config %s for %s is of kind %s, primaries must be Kubernetes", cfg.Name(), c.Name(), cfg.Kind()))
continue
}
}
if errs != nil {
return nil, errs
}
for _, c := range clusters {
scopes.Framework.Infof("Built Cluster:\n%s", c.String())
}
scopes.Framework.Infof("=== DONE: Building clusters ===")
return clusters, errs
}
func validPrimaryOrConfig(c cluster.Cluster) bool {
return c.Kind() == cluster.Kubernetes || c.Kind() == cluster.Fake
}
func buildCluster(cfg cluster.Config, allClusters cluster.Map) (cluster.Cluster, error) {
cfg, err := validConfig(cfg)
if err != nil {
return nil, err
}
f, err := cluster.GetFactory(cfg)
if err != nil {
return nil, err
}
return f(cfg, cluster.NewTopology(cfg, allClusters))
}
func validConfig(cfg cluster.Config) (cluster.Config, error) {
if cfg.Name == "" {
return cfg, fmt.Errorf("empty cluster name")
}
if cfg.Kind == "" {
return cfg, fmt.Errorf("unspecified Kind for %s", cfg.Name)
}
if cfg.PrimaryClusterName == "" {
cfg.PrimaryClusterName = cfg.Name
}
if cfg.ConfigClusterName == "" {
cfg.ConfigClusterName = cfg.PrimaryClusterName
}
if cfg.Meta == nil {
cfg.Meta = config.Map{}
}
return cfg, nil
}