github.com/polarismesh/polaris@v1.17.8/store/boltdb/namespace.go (about)

     1  /**
     2   * Tencent is pleased to support the open source community by making Polaris available.
     3   *
     4   * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
     5   *
     6   * Licensed under the BSD 3-Clause License (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   * https://opensource.org/licenses/BSD-3-Clause
    11   *
    12   * Unless required by applicable law or agreed to in writing, software distributed
    13   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    14   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
    15   * specific language governing permissions and limitations under the License.
    16   */
    17  
    18  package boltdb
    19  
    20  import (
    21  	"errors"
    22  	"fmt"
    23  	"sort"
    24  	"time"
    25  
    26  	"github.com/polarismesh/polaris/common/model"
    27  	"github.com/polarismesh/polaris/common/utils"
    28  )
    29  
    30  const (
    31  	tblNameNamespace string = "namespace"
    32  	OwnerAttribute   string = "owner"
    33  	NameAttribute    string = "name"
    34  )
    35  
    36  type namespaceStore struct {
    37  	handler BoltHandler
    38  }
    39  
    40  const (
    41  	defaultNamespace = "default"
    42  	polarisNamespace = "Polaris"
    43  )
    44  
    45  var (
    46  	namespaceToToken = map[string]string{
    47  		defaultNamespace: "e2e473081d3d4306b52264e49f7ce227",
    48  		polarisNamespace: "2d1bfe5d12e04d54b8ee69e62494c7fd",
    49  	}
    50  	namespaceToComment = map[string]string{
    51  		defaultNamespace: "Default Environment",
    52  		polarisNamespace: "Polaris-server",
    53  	}
    54  )
    55  
    56  // InitData initialize the namespace data
    57  func (n *namespaceStore) InitData() error {
    58  	namespaces := []string{defaultNamespace, polarisNamespace}
    59  	for _, namespace := range namespaces {
    60  		ns, err := n.GetNamespace(namespace)
    61  		if err != nil {
    62  			return err
    63  		}
    64  		if ns == nil {
    65  			err = n.AddNamespace(&model.Namespace{
    66  				Name:       namespace,
    67  				Comment:    namespaceToComment[namespace],
    68  				Token:      namespaceToToken[namespace],
    69  				Owner:      "polaris",
    70  				Valid:      true,
    71  				CreateTime: time.Now(),
    72  				ModifyTime: time.Now(),
    73  			})
    74  			if err != nil {
    75  				return err
    76  			}
    77  		}
    78  	}
    79  	return nil
    80  }
    81  
    82  // AddNamespace add a namespace
    83  func (n *namespaceStore) AddNamespace(namespace *model.Namespace) error {
    84  	if namespace.Name == "" {
    85  		return errors.New("store add namespace name is empty")
    86  	}
    87  
    88  	// 先删除无效数据,再添加新数据
    89  	if err := n.cleanNamespace(namespace.Name); err != nil {
    90  		return err
    91  	}
    92  
    93  	tn := time.Now()
    94  
    95  	namespace.CreateTime = tn
    96  	namespace.ModifyTime = tn
    97  	namespace.Valid = true
    98  	return n.handler.SaveValue(tblNameNamespace, namespace.Name, namespace)
    99  }
   100  
   101  func (n *namespaceStore) cleanNamespace(name string) error {
   102  	if err := n.handler.DeleteValues(tblNameNamespace, []string{name}); err != nil {
   103  		log.Errorf("[Store][boltdb] delete invalid namespace error, %+v", err)
   104  		return err
   105  	}
   106  
   107  	return nil
   108  }
   109  
   110  // UpdateNamespace update a namespace
   111  func (n *namespaceStore) UpdateNamespace(namespace *model.Namespace) error {
   112  	if namespace.Name == "" {
   113  		return errors.New("store update namespace name is empty")
   114  	}
   115  	properties := make(map[string]interface{})
   116  	properties["Owner"] = namespace.Owner
   117  	properties["Comment"] = namespace.Comment
   118  	properties["ModifyTime"] = time.Now()
   119  	return n.handler.UpdateValue(tblNameNamespace, namespace.Name, properties)
   120  }
   121  
   122  // UpdateNamespaceToken update the token of a namespace
   123  func (n *namespaceStore) UpdateNamespaceToken(name string, token string) error {
   124  	if name == "" || token == "" {
   125  		return fmt.Errorf(
   126  			"store update namespace token some param are empty, name is %s, token is %s", name, token)
   127  	}
   128  	properties := make(map[string]interface{})
   129  	properties["Token"] = token
   130  	properties["ModifyTime"] = time.Now()
   131  	return n.handler.UpdateValue(tblNameNamespace, name, properties)
   132  }
   133  
   134  // GetNamespace query namespace by name
   135  func (n *namespaceStore) GetNamespace(name string) (*model.Namespace, error) {
   136  	values, err := n.handler.LoadValues(tblNameNamespace, []string{name}, &model.Namespace{})
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  	nsValue, ok := values[name]
   141  	if !ok {
   142  		return nil, nil
   143  	}
   144  	ns := nsValue.(*model.Namespace)
   145  	return ns, nil
   146  }
   147  
   148  type NamespaceSlice []*model.Namespace
   149  
   150  // Len length of namespace slice
   151  func (ns NamespaceSlice) Len() int {
   152  	return len(ns)
   153  }
   154  
   155  // Less compare namespace
   156  func (ns NamespaceSlice) Less(i, j int) bool {
   157  	return ns[i].ModifyTime.Before(ns[j].ModifyTime)
   158  }
   159  
   160  // Swap swap elements
   161  func (ns NamespaceSlice) Swap(i, j int) {
   162  	ns[i], ns[j] = ns[j], ns[i]
   163  }
   164  
   165  func matchFieldValue(value string, pattern string) bool {
   166  	if utils.IsWildName(pattern) {
   167  		return utils.IsWildMatch(value, pattern)
   168  	}
   169  	return pattern == value
   170  }
   171  
   172  func matchFieldValueByPatterns(value string, patterns []string) bool {
   173  	for _, p := range patterns {
   174  		if matchFieldValue(value, p) {
   175  			return true
   176  		}
   177  	}
   178  	return false
   179  }
   180  
   181  // GetNamespaces get namespaces by offset and limit
   182  func (n *namespaceStore) GetNamespaces(
   183  	filter map[string][]string, offset, limit int) ([]*model.Namespace, uint32, error) {
   184  	values, err := n.handler.LoadValuesAll(tblNameNamespace, &model.Namespace{})
   185  	if err != nil {
   186  		return nil, 0, err
   187  	}
   188  	namespaces := NamespaceSlice(toNamespaces(values))
   189  
   190  	ret := make([]*model.Namespace, 0)
   191  	for i := range namespaces {
   192  		ns := namespaces[i]
   193  		if !ns.Valid {
   194  			continue
   195  		}
   196  		matched := true
   197  		for index, patterns := range filter {
   198  			if index == OwnerAttribute {
   199  				if matched = matchFieldValueByPatterns(ns.Owner, patterns); !matched {
   200  					break
   201  				}
   202  			}
   203  			if index == NameAttribute {
   204  				if matched = matchFieldValueByPatterns(ns.Name, patterns); !matched {
   205  					break
   206  				}
   207  			}
   208  		}
   209  		if matched {
   210  			ret = append(ret, ns)
   211  		}
   212  	}
   213  	namespaces = ret
   214  
   215  	sort.Sort(sort.Reverse(namespaces))
   216  	startIdx := offset
   217  	if startIdx >= len(namespaces) {
   218  		return nil, uint32(len(namespaces)), nil
   219  	}
   220  	endIdx := startIdx + limit
   221  	if endIdx > len(namespaces) {
   222  		endIdx = len(namespaces)
   223  	}
   224  	ret = namespaces[startIdx:endIdx]
   225  	return ret, uint32(len(namespaces)), nil
   226  }
   227  
   228  func toNamespaces(values map[string]interface{}) []*model.Namespace {
   229  	namespaces := make([]*model.Namespace, 0, len(values))
   230  	for _, nsValue := range values {
   231  		namespaces = append(namespaces, nsValue.(*model.Namespace))
   232  	}
   233  	return namespaces
   234  }
   235  
   236  // GetMoreNamespaces get the latest updated namespaces
   237  func (n *namespaceStore) GetMoreNamespaces(mtime time.Time) ([]*model.Namespace, error) {
   238  	values, err := n.handler.LoadValuesByFilter(
   239  		tblNameNamespace, []string{"ModifyTime"}, &model.Namespace{}, func(value map[string]interface{}) bool {
   240  			mTimeValue, ok := value["ModifyTime"]
   241  			if !ok {
   242  				return false
   243  			}
   244  			return mTimeValue.(time.Time).After(mtime)
   245  		})
   246  	if err != nil {
   247  		return nil, err
   248  	}
   249  	return toNamespaces(values), nil
   250  }