github.com/jfrog/jfrog-cli-core/v2@v2.51.0/artifactory/commands/transferconfig/transferconfig_test.go (about)

     1  package transferconfig
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"io"
     7  	"net/http"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  	"testing"
    12  
    13  	commandUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils"
    14  	"github.com/jfrog/jfrog-cli-core/v2/artifactory/utils"
    15  	commonTests "github.com/jfrog/jfrog-cli-core/v2/common/tests"
    16  	"github.com/jfrog/jfrog-cli-core/v2/utils/config"
    17  	"github.com/jfrog/jfrog-cli-core/v2/utils/tests"
    18  	"github.com/jfrog/jfrog-client-go/artifactory/services"
    19  	"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  func TestExportSourceArtifactory(t *testing.T) {
    24  	// Create transfer config command
    25  	testServer, serverDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) {
    26  		w.WriteHeader(http.StatusOK)
    27  
    28  		// Read body
    29  		content, err := io.ReadAll(r.Body)
    30  		assert.NoError(t, err)
    31  		var actual services.ExportBody
    32  		assert.NoError(t, json.Unmarshal(content, &actual))
    33  
    34  		// Make sure all parameters as expected
    35  		assert.False(t, *actual.IncludeMetadata)
    36  		assert.False(t, *actual.Verbose)
    37  		assert.True(t, *actual.ExcludeContent)
    38  		assert.Nil(t, actual.CreateArchive)
    39  		assert.Nil(t, actual.M2)
    40  
    41  		// Create the export-dir in the export path
    42  		assert.NoError(t, os.Mkdir(filepath.Join(actual.ExportPath, "export-dir"), os.ModePerm))
    43  	})
    44  	defer testServer.Close()
    45  
    46  	// Create working dir
    47  	tmpDir, createTempDirCallback := tests.CreateTempDirWithCallbackAndAssert(t)
    48  	defer createTempDirCallback()
    49  
    50  	// Test export source artifactory
    51  	transferConfigCmd := createTransferConfigCommand(t, serverDetails, nil).SetSourceWorkingDir(tmpDir)
    52  	exportDir, cleanUp, err := transferConfigCmd.exportSourceArtifactory()
    53  	assert.NoError(t, err)
    54  	assert.DirExists(t, exportDir)
    55  	assert.NoError(t, cleanUp())
    56  	assert.NoDirExists(t, exportDir)
    57  	assert.True(t, strings.HasPrefix(exportDir, tmpDir))
    58  }
    59  
    60  func TestImportToTargetArtifactory(t *testing.T) {
    61  	// Create transfer config command
    62  	testServer, serverDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) {
    63  		w.WriteHeader(http.StatusOK)
    64  
    65  		content, err := io.ReadAll(r.Body)
    66  		assert.NoError(t, err)
    67  		if r.RequestURI == "/"+commandUtils.PluginsExecuteRestApi+"configImport" {
    68  			// Read body
    69  			assert.Equal(t, []byte("zip-content"), content)
    70  			_, err = w.Write([]byte("123456"))
    71  			assert.NoError(t, err)
    72  			return
    73  		}
    74  
    75  		assert.Equal(t, []byte("123456"), content)
    76  	})
    77  	defer testServer.Close()
    78  
    79  	// Test export source artifactory
    80  	transferConfigCmd := createTransferConfigCommand(t, nil, serverDetails)
    81  	err := transferConfigCmd.importToTargetArtifactory(bytes.NewBuffer([]byte("zip-content")))
    82  	assert.NoError(t, err)
    83  }
    84  
    85  func TestGetConfigXml(t *testing.T) {
    86  	// Create transfer config command
    87  	testServer, serverDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) {
    88  		w.WriteHeader(http.StatusOK)
    89  		if r.RequestURI == "/api/system/configuration" {
    90  			_, err := w.Write([]byte("<config></config>"))
    91  			assert.NoError(t, err)
    92  		}
    93  	})
    94  	defer testServer.Close()
    95  
    96  	// Test get config xml
    97  	transferConfigCmd := createTransferConfigCommand(t, serverDetails, nil)
    98  	configXml, _, err := transferConfigCmd.getEncryptedItems(make(map[utils.RepoType][]services.RepositoryDetails))
    99  	assert.NoError(t, err)
   100  	assert.Equal(t, "<config></config>", configXml)
   101  }
   102  
   103  func TestValidateTargetServer(t *testing.T) {
   104  	var users []services.User
   105  	// Create transfer config command
   106  	testServer, serverDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) {
   107  		switch r.RequestURI {
   108  		case "/" + commandUtils.PluginsExecuteRestApi + "checkPermissions":
   109  			w.WriteHeader(http.StatusOK)
   110  		case "/" + commandUtils.PluginsExecuteRestApi + "configImportVersion":
   111  			content, err := json.Marshal(commandUtils.VersionResponse{Version: "1.0.0"})
   112  			assert.NoError(t, err)
   113  			_, err = w.Write(content)
   114  			assert.NoError(t, err)
   115  		case "/api/system/version":
   116  			content, err := json.Marshal(commandUtils.VersionResponse{Version: "7.0.0"})
   117  			assert.NoError(t, err)
   118  			_, err = w.Write(content)
   119  			assert.NoError(t, err)
   120  		default:
   121  			content, err := json.Marshal(users)
   122  			assert.NoError(t, err)
   123  			_, err = w.Write(content)
   124  			assert.NoError(t, err)
   125  			users = append(users, services.User{})
   126  		}
   127  	})
   128  	defer testServer.Close()
   129  
   130  	transferConfigCmd := createTransferConfigCommand(t, &config.ServerDetails{Url: "dummy-url"}, serverDetails)
   131  	// Test no users
   132  	err := transferConfigCmd.validateTargetServer()
   133  	assert.NoError(t, err)
   134  
   135  	// Test 1 users
   136  	err = transferConfigCmd.validateTargetServer()
   137  	assert.NoError(t, err)
   138  
   139  	// Test 2 users
   140  	err = transferConfigCmd.validateTargetServer()
   141  	assert.NoError(t, err)
   142  
   143  	// Test 3 users
   144  	err = transferConfigCmd.validateTargetServer()
   145  	assert.ErrorContains(t, err, "cowardly refusing to import the config to the target server, because it contains more than 2 users.")
   146  
   147  	// Assert force = true
   148  	transferConfigCmd.force = true
   149  	err = transferConfigCmd.validateTargetServer()
   150  	assert.NoError(t, err)
   151  }
   152  
   153  func TestVerifyConfigImportPluginNotInstalled(t *testing.T) {
   154  	// Create transfer config command
   155  	testServer, serverDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, _ *http.Request) {
   156  		w.WriteHeader(http.StatusNotFound)
   157  		_, err := w.Write([]byte("Not found"))
   158  		assert.NoError(t, err)
   159  	})
   160  	defer testServer.Close()
   161  
   162  	transferConfigCmd := createTransferConfigCommand(t, &config.ServerDetails{Url: "dummy-url"}, serverDetails)
   163  	err := transferConfigCmd.verifyConfigImportPlugin()
   164  	assert.ErrorContains(t, err, "Response from Artifactory: 404 Not Found.")
   165  }
   166  
   167  func TestVerifyConfigImportPluginForbidden(t *testing.T) {
   168  	// Create transfer config command
   169  	testServer, serverDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, _ *http.Request) {
   170  		w.WriteHeader(http.StatusForbidden)
   171  		_, err := w.Write([]byte("An admin user is required"))
   172  		assert.NoError(t, err)
   173  	})
   174  	defer testServer.Close()
   175  
   176  	transferConfigCmd := createTransferConfigCommand(t, &config.ServerDetails{Url: "dummy-url"}, serverDetails)
   177  	err := transferConfigCmd.verifyConfigImportPlugin()
   178  	assert.ErrorContains(t, err, "Response from Artifactory: 403 Forbidden.")
   179  }
   180  
   181  func TestCreateExportPath(t *testing.T) {
   182  	transferConfigBase := NewTransferConfigCommand(nil, nil)
   183  
   184  	// Create export path and check results
   185  	exportPath, unsetTempDir, err := transferConfigBase.createExportPath()
   186  	unsetTempDir()
   187  	assert.NoError(t, err)
   188  	assert.NotEmpty(t, exportPath)
   189  	assert.DirExists(t, exportPath)
   190  
   191  	// Create working dir
   192  	const testExportDir = "test-export-dir"
   193  	tmpDir, createTempDirCallback := tests.CreateTempDirWithCallbackAndAssert(t)
   194  	defer createTempDirCallback()
   195  	tmpDir = filepath.Join(tmpDir, testExportDir)
   196  	assert.NoError(t, os.MkdirAll(tmpDir, 0700))
   197  	transferConfigBase.sourceWorkingDir = tmpDir
   198  
   199  	// Create export path with custom working dir
   200  	exportPath, unsetTempDir, err = transferConfigBase.createExportPath()
   201  	unsetTempDir()
   202  	assert.NoError(t, err)
   203  	assert.True(t, strings.HasPrefix(exportPath, tmpDir))
   204  	assert.DirExists(t, exportPath)
   205  
   206  	// Ensure unsetTempDir did work
   207  	assert.NotContains(t, fileutils.GetTempDirBase(), testExportDir)
   208  }
   209  
   210  func createTransferConfigCommand(t *testing.T, sourceServerDetails, targetServerDetails *config.ServerDetails) *TransferConfigCommand {
   211  	transferConfigBase := NewTransferConfigCommand(sourceServerDetails, targetServerDetails)
   212  	var err error
   213  	if sourceServerDetails != nil {
   214  		transferConfigBase.SourceArtifactoryManager, err = utils.CreateServiceManager(sourceServerDetails, -1, 0, false)
   215  		assert.NoError(t, err)
   216  	}
   217  	if targetServerDetails != nil {
   218  		transferConfigBase.TargetArtifactoryManager, err = utils.CreateServiceManager(targetServerDetails, -1, 0, false)
   219  		assert.NoError(t, err)
   220  	}
   221  	return transferConfigBase
   222  }
   223  
   224  var validateMinVersionAndDifferentServersCases = []struct {
   225  	testName      string
   226  	sourceVersion string
   227  	targetVersion string
   228  	expectedError string
   229  }{
   230  	{testName: "Same version", sourceVersion: minTransferConfigArtifactoryVersion, targetVersion: minTransferConfigArtifactoryVersion, expectedError: ""},
   231  	{testName: "Different versions", sourceVersion: "7.0.0", targetVersion: "7.0.1", expectedError: ""},
   232  	{testName: "Low Artifactory version", sourceVersion: "6.0.0", targetVersion: "7.0.0", expectedError: "while this operation requires version"},
   233  	{testName: "Source newer than target", sourceVersion: "7.0.1", targetVersion: "7.0.0", expectedError: "can't be higher than the target Artifactory version"},
   234  }
   235  
   236  func TestValidateMinVersion(t *testing.T) {
   237  	var sourceRtVersion, targetRtVersion string
   238  	// Create transfer config command
   239  	sourceTestServer, sourceServerDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, _ *http.Request) {
   240  		content, err := json.Marshal(commandUtils.VersionResponse{Version: sourceRtVersion})
   241  		assert.NoError(t, err)
   242  		_, err = w.Write(content)
   243  		assert.NoError(t, err)
   244  	})
   245  	defer sourceTestServer.Close()
   246  	targetTestServer, targetServerDetails, _ := commonTests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, _ *http.Request) {
   247  		content, err := json.Marshal(commandUtils.VersionResponse{Version: targetRtVersion})
   248  		assert.NoError(t, err)
   249  		_, err = w.Write(content)
   250  		assert.NoError(t, err)
   251  	})
   252  	defer targetTestServer.Close()
   253  
   254  	for _, testCase := range validateMinVersionAndDifferentServersCases {
   255  		t.Run(testCase.testName, func(t *testing.T) {
   256  			sourceRtVersion = testCase.sourceVersion
   257  			targetRtVersion = testCase.targetVersion
   258  			actualSourceRtVersion, err := createTransferConfigCommand(t, sourceServerDetails, targetServerDetails).validateMinVersion()
   259  			if testCase.expectedError == "" {
   260  				assert.NoError(t, err)
   261  				assert.Equal(t, sourceRtVersion, actualSourceRtVersion)
   262  			} else {
   263  				assert.ErrorContains(t, err, testCase.expectedError)
   264  			}
   265  		})
   266  	}
   267  }
   268  
   269  func TestValidateAccessServerConnection(t *testing.T) {
   270  	// Create transfer config command
   271  	testServer, serverDetails, accessManager := commonTests.CreateAccessRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) {
   272  		switch r.RequestURI {
   273  		case "/access/api/v1/system/ping":
   274  			w.WriteHeader(http.StatusOK)
   275  		default:
   276  			assert.Fail(t, "Unexpected request URI: "+r.RequestURI)
   277  		}
   278  	})
   279  	defer testServer.Close()
   280  
   281  	transferConfigCmd := createTransferConfigCommand(t, nil, nil)
   282  	err := transferConfigCmd.ValidateAccessServerConnection(serverDetails, accessManager)
   283  	assert.NoError(t, err)
   284  }
   285  
   286  func TestValidateAccessServerConnectionForbidden(t *testing.T) {
   287  	// Create transfer config command
   288  	testServer, serverDetails, accessManager := commonTests.CreateAccessRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) {
   289  		switch r.RequestURI {
   290  		case "/access/api/v1/system/ping":
   291  			w.WriteHeader(http.StatusForbidden)
   292  		default:
   293  			assert.Fail(t, "Unexpected request URI: "+r.RequestURI)
   294  		}
   295  	})
   296  	defer testServer.Close()
   297  
   298  	transferConfigCmd := createTransferConfigCommand(t, nil, nil)
   299  	// Assert access token invalid error
   300  	err := transferConfigCmd.ValidateAccessServerConnection(serverDetails, accessManager)
   301  	assert.ErrorContains(t, err, "the 'test-server' instance Access Token is not valid. Please provide a valid access token by running the 'jf c edit test-server'")
   302  }