github.com/polarismesh/polaris@v1.17.8/config/config_file_test.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 config_test
    19  
    20  import (
    21  	"context"
    22  	"encoding/base64"
    23  	"encoding/hex"
    24  	"errors"
    25  	"fmt"
    26  	"reflect"
    27  	"testing"
    28  
    29  	. "github.com/agiledragon/gomonkey/v2"
    30  	"github.com/golang/mock/gomock"
    31  	"github.com/golang/protobuf/ptypes/wrappers"
    32  	apiconfig "github.com/polarismesh/specification/source/go/api/v1/config_manage"
    33  	apimodel "github.com/polarismesh/specification/source/go/api/v1/model"
    34  	"github.com/stretchr/testify/assert"
    35  	"google.golang.org/protobuf/types/known/wrapperspb"
    36  
    37  	api "github.com/polarismesh/polaris/common/api/v1"
    38  	"github.com/polarismesh/polaris/common/model"
    39  	"github.com/polarismesh/polaris/common/utils"
    40  	"github.com/polarismesh/polaris/plugin"
    41  	"github.com/polarismesh/polaris/plugin/crypto/aes"
    42  	storemock "github.com/polarismesh/polaris/store/mock"
    43  )
    44  
    45  var (
    46  	testNamespace = "testNamespace123qwe"
    47  	testGroup     = "testGroup"
    48  	testFile      = "testFile"
    49  	testContent   = "testContent"
    50  	operator      = "polaris"
    51  	size          = 7
    52  )
    53  
    54  // TestConfigFileCRUD 测试配置文件增删改查
    55  func TestConfigFileCRUD(t *testing.T) {
    56  	testSuit := &ConfigCenterTest{}
    57  	if err := testSuit.Initialize(); err != nil {
    58  		t.Fatal(err)
    59  	}
    60  	t.Cleanup(func() {
    61  		if err := testSuit.clearTestData(); err != nil {
    62  			t.Fatal(err)
    63  		}
    64  		testSuit.Destroy()
    65  	})
    66  
    67  	t.Run("step1-query", func(t *testing.T) {
    68  		rsp := testSuit.ConfigServer().GetConfigFileRichInfo(testSuit.DefaultCtx, &apiconfig.ConfigFile{
    69  			Namespace: utils.NewStringValue(testNamespace),
    70  			Group:     utils.NewStringValue(testGroup),
    71  			Name:      utils.NewStringValue(testFile),
    72  		})
    73  		assert.Equal(t, uint32(api.NotFoundResource), rsp.Code.GetValue())
    74  		assert.Nil(t, rsp.ConfigFile)
    75  	})
    76  
    77  	t.Run("step2-create", func(t *testing.T) {
    78  		configFile := assembleConfigFile()
    79  		rsp := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, configFile)
    80  		assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
    81  
    82  		// 重复创建
    83  		rsp2 := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, configFile)
    84  		assert.Equal(t, uint32(api.ExistedResource), rsp2.Code.GetValue())
    85  
    86  		// 创建完之后再查询
    87  		rsp3 := testSuit.ConfigServer().GetConfigFileRichInfo(testSuit.DefaultCtx, &apiconfig.ConfigFile{
    88  			Namespace: utils.NewStringValue(testNamespace),
    89  			Group:     utils.NewStringValue(testGroup),
    90  			Name:      utils.NewStringValue(testFile),
    91  		})
    92  		assert.Equal(t, api.ExecuteSuccess, rsp3.Code.GetValue())
    93  		assert.NotNil(t, rsp3.ConfigFile)
    94  		assert.Equal(t, testNamespace, rsp3.ConfigFile.Namespace.GetValue())
    95  		assert.Equal(t, testGroup, rsp3.ConfigFile.Group.GetValue())
    96  		assert.Equal(t, testFile, rsp3.ConfigFile.Name.GetValue())
    97  		assert.Equal(t, configFile.Content.GetValue(), rsp3.ConfigFile.Content.GetValue())
    98  		assert.Equal(t, configFile.Format.GetValue(), rsp3.ConfigFile.Format.GetValue())
    99  	})
   100  
   101  	t.Run("step3-update", func(t *testing.T) {
   102  		testSuit.DefaultCtx = context.WithValue(testSuit.DefaultCtx, utils.ContextUserNameKey, "polaris")
   103  
   104  		rsp := testSuit.ConfigServer().GetConfigFileRichInfo(testSuit.DefaultCtx, &apiconfig.ConfigFile{
   105  			Namespace: utils.NewStringValue(testNamespace),
   106  			Group:     utils.NewStringValue(testGroup),
   107  			Name:      utils.NewStringValue(testFile),
   108  		})
   109  		assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   110  
   111  		configFile := rsp.ConfigFile
   112  		newContent := "k1=v1"
   113  		modifyBy := "polaris"
   114  		configFile.Content = utils.NewStringValue(newContent)
   115  		configFile.ModifyBy = utils.NewStringValue(modifyBy)
   116  
   117  		rsp2 := testSuit.ConfigServer().UpdateConfigFile(testSuit.DefaultCtx, configFile)
   118  		assert.Equal(t, api.ExecuteSuccess, rsp2.Code.GetValue())
   119  		assert.Equal(t, newContent, rsp2.ConfigFile.Content.GetValue())
   120  
   121  		// 更新完之后再查询
   122  		rsp3 := testSuit.ConfigServer().GetConfigFileRichInfo(testSuit.DefaultCtx, &apiconfig.ConfigFile{
   123  			Namespace: utils.NewStringValue(testNamespace),
   124  			Group:     utils.NewStringValue(testGroup),
   125  			Name:      utils.NewStringValue(testFile),
   126  		})
   127  		assert.Equal(t, api.ExecuteSuccess, rsp3.Code.GetValue())
   128  		assert.NotNil(t, rsp.ConfigFile)
   129  		assert.Equal(t, testNamespace, rsp.ConfigFile.Namespace.GetValue())
   130  		assert.Equal(t, testGroup, rsp.ConfigFile.Group.GetValue())
   131  		assert.Equal(t, testFile, rsp.ConfigFile.Name.GetValue())
   132  		assert.Equal(t, configFile.Content.GetValue(), rsp.ConfigFile.Content.GetValue())
   133  		assert.Equal(t, configFile.Format.GetValue(), rsp.ConfigFile.Format.GetValue())
   134  		assert.Equal(t, operator, rsp.ConfigFile.CreateBy.GetValue())
   135  		assert.Equal(t, modifyBy, rsp.ConfigFile.ModifyBy.GetValue())
   136  	})
   137  
   138  	t.Run("step4-delete", func(t *testing.T) {
   139  		// 删除前先发布一次
   140  		configFile := assembleConfigFile()
   141  		configFileRelease := assembleConfigFileRelease(configFile)
   142  		rsp := testSuit.ConfigServer().PublishConfigFile(testSuit.DefaultCtx, configFileRelease)
   143  		assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   144  
   145  		rsp2 := testSuit.ConfigServer().DeleteConfigFile(testSuit.DefaultCtx, &apiconfig.ConfigFile{
   146  			Namespace: utils.NewStringValue(testNamespace),
   147  			Group:     utils.NewStringValue(testGroup),
   148  			Name:      utils.NewStringValue(testFile),
   149  		})
   150  		assert.Equal(t, api.ExecuteSuccess, rsp2.Code.GetValue())
   151  
   152  		// 删除后,查询不到
   153  		rsp3 := testSuit.ConfigServer().GetConfigFileRichInfo(testSuit.DefaultCtx, &apiconfig.ConfigFile{
   154  			Namespace: utils.NewStringValue(testNamespace),
   155  			Group:     utils.NewStringValue(testGroup),
   156  			Name:      utils.NewStringValue(testFile),
   157  		})
   158  		assert.Equal(t, uint32(api.NotFoundResource), rsp3.Code.GetValue())
   159  		assert.Nil(t, rsp2.ConfigFile)
   160  	})
   161  
   162  	t.Run("step5-search-by-group", func(t *testing.T) {
   163  		group := "group11"
   164  		for i := 0; i < size; i++ {
   165  			rsp := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, assembleConfigFileWithFixedGroupAndRandomFileName(group))
   166  			assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   167  		}
   168  
   169  		// 第一页
   170  		rsp2 := testSuit.ConfigServer().SearchConfigFile(testSuit.DefaultCtx, map[string]string{
   171  			"namespace": testNamespace,
   172  			"group":     group,
   173  			"offset":    "0",
   174  			"limit":     "3",
   175  		})
   176  		assert.Equal(t, api.ExecuteSuccess, rsp2.Code.GetValue())
   177  		assert.Equal(t, uint32(size), rsp2.Total.GetValue())
   178  		assert.Equal(t, 3, len(rsp2.ConfigFiles))
   179  
   180  		// 最后一页
   181  		rsp3 := testSuit.ConfigServer().SearchConfigFile(testSuit.DefaultCtx, map[string]string{
   182  			"namespace": testNamespace,
   183  			"group":     group,
   184  			"offset":    "6",
   185  			"limit":     "3",
   186  		})
   187  		assert.Equal(t, api.ExecuteSuccess, rsp3.Code.GetValue())
   188  		assert.Equal(t, uint32(size), rsp3.Total.GetValue())
   189  		assert.Equal(t, 1, len(rsp3.ConfigFiles))
   190  
   191  		// group为空
   192  		rsp4 := testSuit.ConfigServer().SearchConfigFile(testSuit.DefaultCtx, map[string]string{
   193  			"namespace": testNamespace,
   194  			"group":     "",
   195  			"offset":    "0",
   196  			"limit":     "3",
   197  		})
   198  		assert.Equal(t, api.ExecuteSuccess, rsp4.Code.GetValue())
   199  		assert.Equal(t, uint32(size), rsp4.Total.GetValue())
   200  		assert.Equal(t, 3, len(rsp4.ConfigFiles))
   201  
   202  		// group 模糊搜索
   203  		rsp5 := testSuit.ConfigServer().SearchConfigFile(testSuit.DefaultCtx, map[string]string{
   204  			"namespace": testNamespace,
   205  			"group":     "group1*",
   206  			"offset":    "0",
   207  			"limit":     "3",
   208  		})
   209  		assert.Equal(t, api.ExecuteSuccess, rsp5.Code.GetValue())
   210  		assert.Equal(t, uint32(size), rsp5.Total.GetValue())
   211  		assert.Equal(t, 3, len(rsp5.ConfigFiles))
   212  	})
   213  
   214  	t.Run("step5-find-by-group", func(t *testing.T) {
   215  		group := "group12"
   216  		for i := 0; i < size; i++ {
   217  			rsp := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, assembleConfigFileWithFixedGroupAndRandomFileName(group))
   218  			assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   219  		}
   220  
   221  		// 第一页
   222  		rsp2 := testSuit.ConfigServer().SearchConfigFile(testSuit.DefaultCtx, map[string]string{
   223  			"namespace": testNamespace,
   224  			"group":     group,
   225  			"offset":    "0",
   226  			"limit":     "3",
   227  		})
   228  		assert.Equal(t, api.ExecuteSuccess, rsp2.Code.GetValue())
   229  		assert.Equal(t, uint32(size), rsp2.Total.GetValue())
   230  		assert.Equal(t, 3, len(rsp2.ConfigFiles))
   231  
   232  		// 最后一页
   233  		rsp3 := testSuit.ConfigServer().SearchConfigFile(testSuit.DefaultCtx, map[string]string{
   234  			"namespace": testNamespace,
   235  			"group":     group,
   236  			"offset":    "6",
   237  			"limit":     "3",
   238  		})
   239  		assert.Equal(t, api.ExecuteSuccess, rsp3.Code.GetValue())
   240  		assert.Equal(t, uint32(size), rsp3.Total.GetValue())
   241  		assert.Equal(t, 1, len(rsp3.ConfigFiles))
   242  	})
   243  
   244  	t.Run("step6-search-by-file", func(t *testing.T) {
   245  		file := "file1.txt"
   246  		for i := 0; i < size; i++ {
   247  			rsp := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, assembleConfigFileWithRandomGroupAndFixedFileName(file))
   248  			assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   249  		}
   250  
   251  		// 第一页
   252  		rsp2 := testSuit.ConfigServer().SearchConfigFile(testSuit.DefaultCtx, map[string]string{
   253  			"namespace": testNamespace,
   254  			"name":      file,
   255  			"offset":    "0",
   256  			"limit":     "3",
   257  		})
   258  		assert.Equal(t, api.ExecuteSuccess, rsp2.Code.GetValue())
   259  		assert.Equal(t, uint32(size), rsp2.Total.GetValue())
   260  		assert.Equal(t, 3, len(rsp2.ConfigFiles))
   261  
   262  		// 最后一页
   263  		rsp3 := testSuit.ConfigServer().SearchConfigFile(testSuit.DefaultCtx, map[string]string{
   264  			"namespace": testNamespace,
   265  			"name":      file,
   266  			"offset":    "6",
   267  			"limit":     "3",
   268  		})
   269  		assert.Equal(t, api.ExecuteSuccess, rsp3.Code.GetValue())
   270  		assert.Equal(t, uint32(size), rsp3.Total.GetValue())
   271  		assert.Equal(t, 1, len(rsp3.ConfigFiles))
   272  
   273  		// group,name都为空
   274  		rsp4 := testSuit.ConfigServer().SearchConfigFile(testSuit.DefaultCtx, map[string]string{
   275  			"namespace": testNamespace,
   276  			"offset":    "0",
   277  			"limit":     "3",
   278  		})
   279  		assert.Equal(t, api.ExecuteSuccess, rsp4.Code.GetValue())
   280  		assert.Equal(t, uint32(size*3), rsp4.Total.GetValue()) // 总数为随机 group 和随机 fileName 总和
   281  		assert.Equal(t, 3, len(rsp4.ConfigFiles))
   282  
   283  		// fileName 模糊搜索
   284  		rsp5 := testSuit.ConfigServer().SearchConfigFile(testSuit.DefaultCtx, map[string]string{
   285  			"namespace": testNamespace,
   286  			"name":      "file1*",
   287  			"offset":    "0",
   288  			"limit":     "3",
   289  		})
   290  		assert.Equal(t, api.ExecuteSuccess, rsp5.Code.GetValue())
   291  		assert.Equal(t, uint32(size), rsp5.Total.GetValue())
   292  		assert.Equal(t, 3, len(rsp5.ConfigFiles))
   293  	})
   294  
   295  	t.Run("step7-search-by-tag", func(t *testing.T) {
   296  		t.Skip()
   297  		// 按 tag k1=v1 搜索
   298  		rsp := testSuit.ConfigServer().SearchConfigFile(testSuit.DefaultCtx, map[string]string{
   299  			"namespace": testNamespace,
   300  			"tags":      "k1,v1",
   301  			"offset":    "0",
   302  			"limit":     "3",
   303  		})
   304  		assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   305  		assert.Equal(t, uint32(size*3), rsp.Total.GetValue())
   306  		assert.Equal(t, 3, len(rsp.ConfigFiles))
   307  	})
   308  
   309  	t.Run("step8-export", func(t *testing.T) {
   310  		namespace := "namespace_0"
   311  		for i := 0; i < 3; i++ {
   312  			group := fmt.Sprintf("group_%d", i)
   313  			for j := 0; j < 3; j++ {
   314  				name := fmt.Sprintf("file_%d", j)
   315  				configFile := assembleConfigFileWithNamespaceAndGroupAndName(namespace, group, name)
   316  				rsp := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, configFile)
   317  				assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   318  			}
   319  		}
   320  		// 导出 group
   321  		configFileExport := &apiconfig.ConfigFileExportRequest{
   322  			Namespace: utils.NewStringValue("namespace_0"),
   323  			Groups: []*wrappers.StringValue{
   324  				utils.NewStringValue("group_0"),
   325  				utils.NewStringValue("group_1"),
   326  			},
   327  		}
   328  		rsp := testSuit.ConfigServer().ExportConfigFile(testSuit.DefaultCtx, configFileExport)
   329  		assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   330  		// 导出 file
   331  		configFileExport = &apiconfig.ConfigFileExportRequest{
   332  			Namespace: utils.NewStringValue("namespace_0"),
   333  			Groups: []*wrappers.StringValue{
   334  				utils.NewStringValue("group_0"),
   335  			},
   336  			Names: []*wrappers.StringValue{
   337  				utils.NewStringValue("file_0"),
   338  				utils.NewStringValue("file_1"),
   339  				utils.NewStringValue("file_2"),
   340  			},
   341  		}
   342  		rsp = testSuit.ConfigServer().ExportConfigFile(testSuit.DefaultCtx, configFileExport)
   343  		assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   344  		// 导出参数错误:无效的命名空间
   345  		configFileExport = &apiconfig.ConfigFileExportRequest{
   346  			Namespace: utils.NewStringValue(""),
   347  		}
   348  		rsp = testSuit.ConfigServer().ExportConfigFile(testSuit.DefaultCtx, configFileExport)
   349  		assert.Equal(t, api.InvalidNamespaceName, rsp.Code.GetValue())
   350  		// 导出参数错误:无效的组和文件
   351  		configFileExport = &apiconfig.ConfigFileExportRequest{
   352  			Namespace: utils.NewStringValue("namespace_0"),
   353  			Groups: []*wrappers.StringValue{
   354  				utils.NewStringValue("group_0"),
   355  				utils.NewStringValue("group_1"),
   356  			},
   357  			Names: []*wrappers.StringValue{
   358  				utils.NewStringValue("file_0"),
   359  			},
   360  		}
   361  		rsp = testSuit.ConfigServer().ExportConfigFile(testSuit.DefaultCtx, configFileExport)
   362  		assert.Equal(t, api.InvalidParameter, rsp.Code.GetValue())
   363  		// 导出配置不存在
   364  		configFileExport = &apiconfig.ConfigFileExportRequest{
   365  			Namespace: utils.NewStringValue("namespace_0"),
   366  			Groups: []*wrappers.StringValue{
   367  				utils.NewStringValue("group_10"),
   368  			},
   369  		}
   370  		rsp = testSuit.ConfigServer().ExportConfigFile(testSuit.DefaultCtx, configFileExport)
   371  		assert.Equal(t, api.NotFoundResourceConfigFile, rsp.Code.GetValue())
   372  	})
   373  
   374  	t.Run("step9-import", func(t *testing.T) {
   375  		// 导入配置文件错误
   376  		namespace := "namespace_0"
   377  		var configFiles []*apiconfig.ConfigFile
   378  		for i := 0; i < 2; i++ {
   379  			group := fmt.Sprintf("group_%d", i)
   380  			for j := 1; j < 4; j++ {
   381  				name := ""
   382  				configFile := assembleConfigFileWithNamespaceAndGroupAndName(namespace, group, name)
   383  				configFiles = append(configFiles, configFile)
   384  			}
   385  		}
   386  		rsp := testSuit.ConfigServer().ImportConfigFile(testSuit.DefaultCtx, configFiles, utils.ConfigFileImportConflictSkip)
   387  		assert.Equal(t, api.InvalidConfigFileName, rsp.Code.GetValue(), rsp.GetInfo().GetValue())
   388  	})
   389  	t.Run("step10-import-conflict-skip", func(t *testing.T) {
   390  		namespace := "namespace_import_skip"
   391  		group := fmt.Sprintf("group_0")
   392  		for j := 0; j < 3; j++ {
   393  			name := fmt.Sprintf("file_%d", j)
   394  			configFile := assembleConfigFileWithNamespaceAndGroupAndName(namespace, group, name)
   395  			rsp := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, configFile)
   396  			assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   397  		}
   398  
   399  		var configFiles []*apiconfig.ConfigFile
   400  		for i := 0; i < 2; i++ {
   401  			group := fmt.Sprintf("group_%d", i)
   402  			for j := 1; j < 4; j++ {
   403  				name := fmt.Sprintf("file_%d", j)
   404  				configFile := assembleConfigFileWithNamespaceAndGroupAndName(namespace, group, name)
   405  				configFiles = append(configFiles, configFile)
   406  			}
   407  		}
   408  		rsp := testSuit.ConfigServer().ImportConfigFile(testSuit.DefaultCtx, configFiles, utils.ConfigFileImportConflictSkip)
   409  		t.Log(rsp.Code.GetValue())
   410  		assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   411  		assert.Equal(t, 4, len(rsp.CreateConfigFiles))
   412  		assert.Equal(t, 2, len(rsp.SkipConfigFiles))
   413  		assert.Equal(t, 0, len(rsp.OverwriteConfigFiles))
   414  	})
   415  
   416  	t.Run("step11-import-conflict-overwrite", func(t *testing.T) {
   417  		namespace := "namespace_import_overwrite"
   418  		group := fmt.Sprintf("group_0")
   419  		for j := 0; j < 3; j++ {
   420  			name := fmt.Sprintf("file_%d", j)
   421  			configFile := assembleConfigFileWithNamespaceAndGroupAndName(namespace, group, name)
   422  			rsp := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, configFile)
   423  			assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   424  		}
   425  
   426  		var configFiles []*apiconfig.ConfigFile
   427  		for i := 0; i < 2; i++ {
   428  			group := fmt.Sprintf("group_%d", i)
   429  			for j := 1; j < 4; j++ {
   430  				name := fmt.Sprintf("file_%d", j)
   431  				configFile := assembleConfigFileWithNamespaceAndGroupAndName(namespace, group, name)
   432  				configFiles = append(configFiles, configFile)
   433  			}
   434  		}
   435  		rsp := testSuit.ConfigServer().ImportConfigFile(testSuit.DefaultCtx, configFiles, utils.ConfigFileImportConflictOverwrite)
   436  		t.Log(rsp.Code.GetValue())
   437  		assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   438  		assert.Equal(t, 4, len(rsp.CreateConfigFiles))
   439  		assert.Equal(t, 0, len(rsp.SkipConfigFiles))
   440  		assert.Equal(t, 2, len(rsp.OverwriteConfigFiles))
   441  	})
   442  
   443  	t.Run("step12-create-entrypted", func(t *testing.T) {
   444  		configFile := assembleConfigFile()
   445  		configFile.Encrypted = utils.NewBoolValue(true)
   446  		configFile.EncryptAlgo = utils.NewStringValue("AES")
   447  		rsp := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, configFile)
   448  		assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue(), rsp.GetInfo().GetValue())
   449  
   450  		// 重复创建
   451  		rsp2 := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, configFile)
   452  		assert.Equal(t, uint32(api.ExistedResource), rsp2.Code.GetValue(), rsp2.GetInfo().GetValue())
   453  
   454  		// 创建完之后再查询
   455  		rsp3 := testSuit.ConfigServer().GetConfigFileRichInfo(testSuit.DefaultCtx, &apiconfig.ConfigFile{
   456  			Namespace: utils.NewStringValue(testNamespace),
   457  			Group:     utils.NewStringValue(testGroup),
   458  			Name:      utils.NewStringValue(testFile),
   459  		})
   460  		assert.Equal(t, api.ExecuteSuccess, rsp3.Code.GetValue(), rsp3.GetInfo().GetValue())
   461  		assert.NotNil(t, rsp3.ConfigFile)
   462  		assert.Equal(t, testNamespace, rsp3.ConfigFile.Namespace.GetValue())
   463  		assert.Equal(t, testGroup, rsp3.ConfigFile.Group.GetValue())
   464  		assert.Equal(t, testFile, rsp3.ConfigFile.Name.GetValue())
   465  		assert.Equal(t, configFile.Content.GetValue(), rsp3.ConfigFile.Content.GetValue())
   466  		assert.Equal(t, configFile.Format.GetValue(), rsp3.ConfigFile.Format.GetValue())
   467  	})
   468  }
   469  
   470  // TestPublishConfigFile 测试配置文件发布相关的用例
   471  func TestPublishConfigFile(t *testing.T) {
   472  	testSuit := &ConfigCenterTest{}
   473  	if err := testSuit.Initialize(); err != nil {
   474  		t.Fatal(err)
   475  	}
   476  	t.Cleanup(func() {
   477  		if err := testSuit.clearTestData(); err != nil {
   478  			t.Fatal(err)
   479  		}
   480  		testSuit.Destroy()
   481  	})
   482  
   483  	configFile := assembleConfigFile()
   484  	rsp := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, configFile)
   485  	assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   486  
   487  	configFileRelease := assembleConfigFileRelease(configFile)
   488  	rsp2 := testSuit.ConfigServer().PublishConfigFile(testSuit.DefaultCtx, configFileRelease)
   489  	assert.Equal(t, api.ExecuteSuccess, rsp2.Code.GetValue())
   490  
   491  	rsp3 := testSuit.ConfigServer().GetConfigFileRelease(testSuit.DefaultCtx, &apiconfig.ConfigFileRelease{
   492  		Namespace: utils.NewStringValue(testNamespace),
   493  		Group:     utils.NewStringValue(testGroup),
   494  		FileName:  utils.NewStringValue(testFile),
   495  	})
   496  	assert.Equal(t, api.ExecuteSuccess, rsp3.Code.GetValue(), rsp3.GetInfo().GetValue())
   497  	assert.Equal(t, uint64(1), rsp3.ConfigFileRelease.Version.GetValue())
   498  	assert.Equal(t, configFileRelease.Name.GetValue(), rsp3.ConfigFileRelease.Name.GetValue())
   499  	assert.Equal(t, configFileRelease.CreateBy.GetValue(), rsp3.ConfigFileRelease.CreateBy.GetValue())
   500  	assert.Equal(t, configFileRelease.CreateBy.GetValue(), rsp3.ConfigFileRelease.ModifyBy.GetValue())
   501  	assert.Equal(t, configFile.Content.GetValue(), rsp3.ConfigFileRelease.Content.GetValue())
   502  
   503  	rsp5 := testSuit.ConfigServer().GetConfigFileRichInfo(testSuit.DefaultCtx, &apiconfig.ConfigFile{
   504  		Namespace: utils.NewStringValue(testNamespace),
   505  		Group:     utils.NewStringValue(testGroup),
   506  		Name:      utils.NewStringValue(testFile),
   507  	})
   508  	assert.Equal(t, uint32(apimodel.Code_ExecuteSuccess), rsp5.GetCode().GetValue())
   509  
   510  	// 第二次修改发布
   511  	secondReleaseContent := "k3=v3"
   512  	secondReleaseFormat := utils.FileFormatHtml
   513  	configFile.Content = utils.NewStringValue(secondReleaseContent)
   514  	configFile.Format = utils.NewStringValue(secondReleaseFormat)
   515  
   516  	rsp6 := testSuit.ConfigServer().UpdateConfigFile(testSuit.DefaultCtx, configFile)
   517  	assert.Equal(t, api.ExecuteSuccess, rsp6.Code.GetValue())
   518  
   519  	configFileRelease.Name = utils.NewStringValue("")
   520  	configFileRelease.CreateBy = utils.NewStringValue("ledou3")
   521  	rsp7 := testSuit.ConfigServer().PublishConfigFile(testSuit.DefaultCtx, configFileRelease)
   522  	assert.Equal(t, api.ExecuteSuccess, rsp7.Code.GetValue(), rsp7.GetInfo().GetValue())
   523  
   524  	rsp9 := testSuit.ConfigServer().GetConfigFileReleaseHistories(testSuit.DefaultCtx, map[string]string{
   525  		"namespace": testNamespace,
   526  		"group":     testGroup,
   527  		"name":      testFile,
   528  		"offset":    "0",
   529  		"limit":     "10",
   530  		"endId":     "0",
   531  	})
   532  	assert.Equal(t, api.ExecuteSuccess, rsp9.Code.GetValue())
   533  	assert.Equal(t, 2, len(rsp9.ConfigFileReleaseHistories))
   534  
   535  }
   536  
   537  func Test_encryptConfigFile(t *testing.T) {
   538  	testSuit := &ConfigCenterTest{}
   539  	if err := testSuit.Initialize(); err != nil {
   540  		t.Fatal(err)
   541  	}
   542  	t.Cleanup(func() {
   543  		testSuit.Destroy()
   544  	})
   545  
   546  	defer func() {
   547  		if err := testSuit.clearTestData(); err != nil {
   548  			t.Fatal(err)
   549  		}
   550  	}()
   551  	type args struct {
   552  		ctx        context.Context
   553  		algorithm  string
   554  		configFile *model.ConfigFile
   555  		dataKey    string
   556  	}
   557  	dataKey, _ := hex.DecodeString("777b162a185673cb1b72b467a78221cd")
   558  	fmt.Println(base64.StdEncoding.EncodeToString(dataKey))
   559  
   560  	tests := []struct {
   561  		name    string
   562  		args    args
   563  		want    string
   564  		wantErr error
   565  	}{
   566  		{
   567  			name: "encrypt config file",
   568  			args: args{
   569  				ctx:       context.Background(),
   570  				algorithm: "AES",
   571  				configFile: &model.ConfigFile{
   572  					Content: "polaris",
   573  				},
   574  				dataKey: "",
   575  			},
   576  			wantErr: nil,
   577  		},
   578  		{
   579  			name: "encrypt config file with dataKey",
   580  			args: args{
   581  				ctx:       context.Background(),
   582  				algorithm: "AES",
   583  				configFile: &model.ConfigFile{
   584  					Content: "polaris",
   585  				},
   586  				dataKey: base64.StdEncoding.EncodeToString(dataKey),
   587  			},
   588  			want:    "YnLZ0SYuujFBHjYHAZVN5A==",
   589  			wantErr: nil,
   590  		},
   591  	}
   592  	for _, tt := range tests {
   593  		t.Run(tt.name, func(t *testing.T) {
   594  			s := testSuit.OriginConfigServer()
   595  			err := s.TestEncryptConfigFile(tt.args.ctx, tt.args.configFile, tt.args.algorithm, tt.args.dataKey)
   596  			assert.Equal(t, tt.wantErr, err)
   597  			if tt.want != "" {
   598  				assert.Equal(t, tt.want, tt.args.configFile.Content)
   599  			}
   600  			hasDataKeyTag := false
   601  			hasAlgoTag := false
   602  			for tagKey, tagVal := range tt.args.configFile.Metadata {
   603  				if tagKey == utils.ConfigFileTagKeyDataKey {
   604  					hasDataKeyTag = true
   605  					if tt.args.dataKey != "" {
   606  						assert.Equal(t, tt.args.dataKey, tagVal)
   607  					}
   608  				}
   609  				if tagKey == utils.ConfigFileTagKeyEncryptAlgo {
   610  					hasAlgoTag = true
   611  					assert.Equal(t, tt.args.algorithm, tagVal)
   612  				}
   613  			}
   614  			assert.True(t, hasDataKeyTag)
   615  			assert.True(t, hasAlgoTag)
   616  		})
   617  	}
   618  }
   619  
   620  func Test_decryptConfigFile(t *testing.T) {
   621  	testSuit := &ConfigCenterTest{}
   622  	if err := testSuit.Initialize(); err != nil {
   623  		t.Fatal(err)
   624  	}
   625  	t.Cleanup(func() {
   626  		testSuit.Destroy()
   627  	})
   628  	defer func() {
   629  		if err := testSuit.clearTestData(); err != nil {
   630  			t.Fatal(err)
   631  		}
   632  	}()
   633  	type args struct {
   634  		ctx        context.Context
   635  		configFile *model.ConfigFile
   636  	}
   637  
   638  	dataKey, _ := hex.DecodeString("777b162a185673cb1b72b467a78221cd")
   639  
   640  	tests := []struct {
   641  		name    string
   642  		args    args
   643  		want    string
   644  		wantErr error
   645  	}{
   646  		{
   647  			name: "decrypt config file",
   648  			args: args{
   649  				ctx: context.WithValue(context.Background(), utils.ContextUserNameKey, "polaris"),
   650  				configFile: &model.ConfigFile{
   651  					Content: "YnLZ0SYuujFBHjYHAZVN5A==",
   652  					Metadata: map[string]string{
   653  						utils.ConfigFileTagKeyDataKey:     base64.StdEncoding.EncodeToString(dataKey),
   654  						utils.ConfigFileTagKeyEncryptAlgo: "AES",
   655  					},
   656  					CreateBy: "polaris",
   657  				},
   658  			},
   659  			want:    "polaris",
   660  			wantErr: nil,
   661  		},
   662  		{
   663  			name: "non creator can decrypt config file",
   664  			args: args{
   665  				ctx: context.WithValue(context.Background(), utils.ContextUserNameKey, "test"),
   666  				configFile: &model.ConfigFile{
   667  					Content: "YnLZ0SYuujFBHjYHAZVN5A==",
   668  					Metadata: map[string]string{
   669  						utils.ConfigFileTagKeyDataKey:     base64.StdEncoding.EncodeToString(dataKey),
   670  						utils.ConfigFileTagKeyEncryptAlgo: "AES",
   671  					},
   672  					CreateBy: "polaris",
   673  				},
   674  			},
   675  			want:    "polaris",
   676  			wantErr: nil,
   677  		},
   678  	}
   679  	for _, tt := range tests {
   680  		t.Run(tt.name, func(t *testing.T) {
   681  			s := testSuit.OriginConfigServer()
   682  			err := s.TestDecryptConfigFile(tt.args.ctx, tt.args.configFile)
   683  			assert.Equal(t, tt.wantErr, err, tt.name)
   684  			assert.Equal(t, tt.want, tt.args.configFile.Content, tt.name)
   685  			for tagKey := range tt.args.configFile.Metadata {
   686  				if tagKey == utils.ConfigFileTagKeyDataKey {
   687  					t.Fatal("config tags has data key")
   688  				}
   689  			}
   690  		})
   691  	}
   692  }
   693  
   694  func Test_GetConfigEncryptAlgorithm(t *testing.T) {
   695  	testSuit := &ConfigCenterTest{}
   696  	if err := testSuit.Initialize(); err != nil {
   697  		t.Fatal(err)
   698  	}
   699  	t.Cleanup(func() {
   700  		testSuit.Destroy()
   701  	})
   702  	defer func() {
   703  		if err := testSuit.clearTestData(); err != nil {
   704  			t.Fatal(err)
   705  		}
   706  	}()
   707  	tests := []struct {
   708  		name string
   709  		want []*wrapperspb.StringValue
   710  	}{
   711  		{
   712  			name: "get config encrypt algorithm",
   713  			want: []*wrapperspb.StringValue{
   714  				utils.NewStringValue("AES"),
   715  			},
   716  		},
   717  	}
   718  	for _, tt := range tests {
   719  		t.Run(tt.name, func(t *testing.T) {
   720  			rsp := testSuit.OriginConfigServer().GetAllConfigEncryptAlgorithms(testSuit.DefaultCtx)
   721  			assert.Equal(t, api.ExecuteSuccess, rsp.Code.GetValue())
   722  			assert.Equal(t, tt.want, rsp.GetAlgorithms())
   723  		})
   724  	}
   725  }
   726  
   727  func Test_CreateConfigFile(t *testing.T) {
   728  	testSuit := &ConfigCenterTest{}
   729  	if err := testSuit.Initialize(); err != nil {
   730  		t.Fatal(err)
   731  	}
   732  	t.Cleanup(func() {
   733  		if err := testSuit.clearTestData(); err != nil {
   734  			t.Fatal(err)
   735  		}
   736  		testSuit.Destroy()
   737  	})
   738  	ctrl := gomock.NewController(t)
   739  	defer ctrl.Finish()
   740  
   741  	t.Run("加密配置文件-返回error", func(t *testing.T) {
   742  		crypto := &MockCrypto{}
   743  		testSuit.OriginConfigServer().TestMockCryptoManager(&MockCryptoManager{
   744  			repos: map[string]plugin.Crypto{
   745  				crypto.Name(): crypto,
   746  			},
   747  		})
   748  
   749  		configFile := assembleEncryptConfigFile()
   750  		got := testSuit.ConfigServer().CreateConfigFile(testSuit.DefaultCtx, configFile)
   751  		assert.Equal(t, apimodel.Code_EncryptConfigFileException, apimodel.Code(got.GetCode().GetValue()))
   752  	})
   753  }
   754  
   755  func Test_GetConfigFileRichInfo(t *testing.T) {
   756  	testSuit := &ConfigCenterTest{}
   757  	if err := testSuit.Initialize(); err != nil {
   758  		t.Fatal(err)
   759  	}
   760  	t.Cleanup(func() {
   761  		if err := testSuit.clearTestData(); err != nil {
   762  			t.Fatal(err)
   763  		}
   764  		testSuit.Destroy()
   765  	})
   766  	ctrl := gomock.NewController(t)
   767  	defer ctrl.Finish()
   768  
   769  	t.Run("获取配置文件基本信息-解密配置文件-返回error", func(t *testing.T) {
   770  		crypto := &aes.AESCrypto{}
   771  		encryptFunc := ApplyMethod(reflect.TypeOf(crypto), "Decrypt", func(_ *aes.AESCrypto, plaintext string, key []byte) (string, error) {
   772  			return "", errors.New("mock encrypt error")
   773  		})
   774  		defer encryptFunc.Reset()
   775  
   776  		configFile := assembleConfigFile()
   777  
   778  		storage := storemock.NewMockStore(ctrl)
   779  		storage.EXPECT().GetConfigFile(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(&model.ConfigFile{
   780  			Namespace: configFile.Namespace.Value,
   781  			Group:     configFile.Group.Value,
   782  			Name:      configFile.Name.Value,
   783  			CreateBy:  operator,
   784  		}, nil)
   785  
   786  		svr := testSuit.OriginConfigServer()
   787  		svr.TestMockStore(storage)
   788  		svr.TestMockCryptoManager(&MockCryptoManager{
   789  			repos: map[string]plugin.Crypto{
   790  				crypto.Name(): crypto,
   791  			},
   792  		})
   793  		got := testSuit.ConfigServer().GetConfigFileRichInfo(testSuit.DefaultCtx, configFile)
   794  		assert.Equal(t, apimodel.Code_ExecuteSuccess, apimodel.Code(got.GetCode().GetValue()), got.GetInfo().GetValue())
   795  	})
   796  }
   797  
   798  type MockCryptoManager struct {
   799  	repos map[string]plugin.Crypto
   800  }
   801  
   802  func (m *MockCryptoManager) Name() string {
   803  	return ""
   804  }
   805  
   806  func (m *MockCryptoManager) Initialize() error {
   807  	return nil
   808  }
   809  
   810  func (m *MockCryptoManager) Destroy() error {
   811  	return nil
   812  }
   813  
   814  func (m *MockCryptoManager) GetCryptoAlgoNames() []string {
   815  	return []string{}
   816  }
   817  
   818  func (m *MockCryptoManager) GetCrypto(algo string) (plugin.Crypto, error) {
   819  	val, ok := m.repos[algo]
   820  	if !ok {
   821  		return nil, errors.New("Not Exist")
   822  	}
   823  	return val, nil
   824  }
   825  
   826  type MockCrypto struct {
   827  }
   828  
   829  func (m *MockCrypto) Name() string {
   830  	return (&aes.AESCrypto{}).Name()
   831  }
   832  
   833  func (m *MockCrypto) Initialize(c *plugin.ConfigEntry) error {
   834  	return nil
   835  }
   836  
   837  func (m *MockCrypto) Destroy() error {
   838  	return nil
   839  }
   840  
   841  func (m *MockCrypto) GenerateKey() ([]byte, error) {
   842  	return nil, errors.New("Not Support")
   843  }
   844  
   845  func (m *MockCrypto) Encrypt(plaintext string, key []byte) (string, error) {
   846  	return "", errors.New("Not Support")
   847  }
   848  
   849  func (m *MockCrypto) Decrypt(cryptotext string, key []byte) (string, error) {
   850  	return "", errors.New("Not Support")
   851  }