diff --git a/cmd/import.go b/cmd/import.go index c7c107d..b924a9e 100755 --- a/cmd/import.go +++ b/cmd/import.go @@ -96,15 +96,14 @@ func runImport(cmd *cobra.Command, args []string) { } func getImportVersionProduct(path string) (string, string) { - var versionfile string - versionfile = path + "/version.txt" + versionfile := path + "/version.txt" version, err := utils.ScannerFunc(versionfile, "version") if err != nil { log.Error().Msg("Version not found.") } product, err := utils.ScannerFunc(versionfile, "product_name") if err != nil { - log.Fatal().Msg("Product not found") + log.Error().Msg("Product not found") } log.Debug().Msgf("Import Product: %s; Version: %s", product, version) return version, product @@ -195,20 +194,6 @@ func runImageFileSync(absImportDir string, serverConfig string) { if err != nil { log.Fatal().Err(err).Msg("Error importing image files") } - - pillarImportDir := path.Join(absImportDir, "images", "pillars") - err = utils.FolderExists(pillarImportDir) - if err != nil { - if os.IsNotExist(err) { - log.Debug().Msg("No pillar files to import") - return - } else { - log.Fatal().Err(err).Msg("Error reading import folder for pillars") - } - } - - log.Info().Msg("Copying image pillar files") - pillarDumper.ImportImagePillars(pillarImportDir, utils.GetCurrentServerFQDN(serverConfig)) } func importSqlFile(absImportDir string) { diff --git a/cmd/password_test.go b/cmd/password_test.go index ca68129..045828e 100644 --- a/cmd/password_test.go +++ b/cmd/password_test.go @@ -7,28 +7,15 @@ package cmd import ( "os" "testing" -) -// create a temp file with a dummy password -func createTempFile(t *testing.T) string { - t.Helper() - f, err := os.CreateTemp("", "passwordfile") - if err != nil { - t.Fatalf("failed to create temp file: %v", err) - } - _, err = f.WriteString("filepassword\n") - if err != nil { - t.Fatalf("failed to write to temp file: %v", err) - } - f.Close() - return f.Name() -} + "github.com/uyuni-project/inter-server-sync/tests" +) // TestGetXMLRPCPassword tests the getXMLRPCPassword function // Checks the priority of password sources: xmlRpcPasswordFile flag, stdin, and xmlRpcPassword flag. func TestGetXMLRPCPassword(t *testing.T) { // Create the temp file once - tmpFile := createTempFile(t) + tmpFile := tests.CreateTempFile(t, "filepassword\n") defer os.Remove(tmpFile) tests := []struct { diff --git a/dumper/pillarDumper/pillarDumper.go b/dumper/pillarDumper/pillarDumper.go index 255d5bb..280dd16 100644 --- a/dumper/pillarDumper/pillarDumper.go +++ b/dumper/pillarDumper/pillarDumper.go @@ -6,113 +6,21 @@ package pillarDumper import ( "fmt" - "os" - "os/exec" - "path" - "path/filepath" "github.com/rs/zerolog/log" - "github.com/uyuni-project/inter-server-sync/dumper" "github.com/uyuni-project/inter-server-sync/schemareader" "github.com/uyuni-project/inter-server-sync/utils" ) -var serverDataDir = "/srv/susemanager/pillar_data/" var replacePattern = "{SERVER_FQDN}" -func DumpImagePillars(outputDir string, orgIds []uint, serverConfig string) { - log.Debug().Msgf("Dumping pillars to %s", outputDir) - fqdn := utils.GetCurrentServerFQDN(serverConfig) - - sourceDir := filepath.Join(serverDataDir, "images") - orgDir, err := os.Open(sourceDir) - if err != nil { - log.Fatal().Err(err) - } - defer orgDir.Close() - orgDirInfo, err := orgDir.ReadDir(-1) - - // If orgIds is empty, set it to 0 so all orgs would be exported - if len(orgIds) == 0 { - orgIds = []uint{0} - } - - for _, org := range orgDirInfo { - for _, orgId := range orgIds { - if org.Type().IsDir() && (orgId == 0 || org.Name() == fmt.Sprintf("org%d", orgId)) { - DumpPillars(path.Join(sourceDir, org.Name()), path.Join(outputDir, org.Name()), fqdn, replacePattern) - } - } - - } -} - -func DumpPillars(sourceDir, outputDir, sourceFQDN, targetFQDN string) { - log.Trace().Msgf("Pillar dump for %s, replacing FQDN %s", sourceDir, sourceFQDN) - - pillarDir, err := os.Open(sourceDir) - if err != nil { - log.Fatal().Err(err) - } - defer pillarDir.Close() - pillarDirInfo, err := pillarDir.ReadDir(-1) - - for _, pillar := range pillarDirInfo { - if pillar.Type().IsRegular() { - pillarFilePath := path.Join(sourceDir, pillar.Name()) - pillarTargetPath := path.Join(outputDir, pillar.Name()) - log.Trace().Msgf("Parsing and copying pillar from %s to %s", pillarFilePath, pillarTargetPath) - - _, err := dumper.ModifyCopy(pillarFilePath, - pillarTargetPath, - sourceFQDN, targetFQDN) - if err != nil { - log.Fatal().Err(err) - } - os.Chmod(pillarTargetPath, 0640) - cmd := exec.Command("chown", "salt:susemanager", pillarTargetPath) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - err = cmd.Run() - if err != nil { - log.Fatal().Err(err).Msg("Error processing image pillar files") - } - } - } -} - -// 4.2 and older stores pillars in files // image export replaces hostnames in image pillars, we need to replace them to correct SUMA on import -func ImportImagePillars(sourceDir string, fqdn string) { - log.Debug().Msgf("Importing image pillars from %s", sourceDir) - orgDir, err := os.Open(sourceDir) +func UpdateImagePillars(serverConfig string) { + fqdn, err := utils.GetCurrentServerFQDN(serverConfig) if err != nil { - log.Fatal().Err(err) - } - defer orgDir.Close() - orgDirInfo, err := orgDir.ReadDir(-1) - - for _, org := range orgDirInfo { - if org.Type().IsDir() { - targetDir := path.Join(serverDataDir, "images", org.Name()) - DumpPillars(path.Join(sourceDir, org.Name()), targetDir, replacePattern, fqdn) - - cmd := exec.Command("chown", "salt:susemanager", targetDir) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - err = cmd.Run() - if err != nil { - log.Fatal().Err(err).Msg("Error importing image pillar files") - - } - } + log.Error().Msgf("FQDN of server not found, images pillar will not be updated") + return } -} - -// 4.3 and newer stores pillars in database -// image export replaces hostnames in image pillars, we need to replace them to correct SUMA on import -func UpdateImagePillars(serverConfig string) { - fqdn := utils.GetCurrentServerFQDN(serverConfig) checkQuery := "SELECT EXISTS (SELECT FROM pg_tables WHERE schemaname = 'public' AND tablename = 'susesaltpillar')" db := schemareader.GetDBconnection(serverConfig) @@ -137,7 +45,7 @@ func UpdateImagePillars(serverConfig string) { replacePattern, fqdn) log.Trace().Msgf("Updating pillar files using query '%s'", sqlQuery) log.Info().Msg("Updating image pillars if needed") - rows, err = db.Query(sqlQuery) + _, err = db.Query(sqlQuery) if err != nil { log.Fatal().Err(err).Msgf("Error updating image pillars") } diff --git a/entityDumper/imageDataDumper.go b/entityDumper/imageDataDumper.go index a1ca97c..86ef56b 100644 --- a/entityDumper/imageDataDumper.go +++ b/entityDumper/imageDataDumper.go @@ -14,7 +14,6 @@ import ( "github.com/rs/zerolog/log" "github.com/uyuni-project/inter-server-sync/dumper" "github.com/uyuni-project/inter-server-sync/dumper/osImageDumper" - "github.com/uyuni-project/inter-server-sync/dumper/pillarDumper" "github.com/uyuni-project/inter-server-sync/schemareader" "github.com/uyuni-project/inter-server-sync/sqlUtil" ) @@ -268,13 +267,9 @@ func dumpImageData(db *sql.DB, writer *bufio.Writer, options DumperOptions) { var outputFolderImagesAbs = filepath.Join(outputFolderAbs, "images") ValidateExportFolder(outputFolderImagesAbs) dumpImageStores(db, writer, schemaMetadata, options, "os_image") - if dumpOSImageTables(db, writer, schemaMetadata, options, outputFolderImagesAbs) { - var outputFolderPillarAbs = filepath.Join(outputFolderAbs, "images", "pillars") - ValidateExportFolder(outputFolderPillarAbs) - pillarDumper.DumpImagePillars(outputFolderPillarAbs, options.Orgs, options.ServerConfig) - if !options.MetadataOnly { - osImageDumper.DumpOsImages(outputFolderImagesAbs, options.Orgs) - } + if dumpOSImageTables(db, writer, schemaMetadata, options, outputFolderImagesAbs) && !options.MetadataOnly { + // Pillars are transfered as part of the sql export + osImageDumper.DumpOsImages(outputFolderImagesAbs, options.Orgs) } // This is needed for containers to be able to export their respective tables markAsUnexported(schemaMetadata, []string{"suseimagestore", "suseimageprofile"}) diff --git a/inter-server-sync.changes.oholecek.remove_42_support b/inter-server-sync.changes.oholecek.remove_42_support new file mode 100644 index 0000000..b236d1a --- /dev/null +++ b/inter-server-sync.changes.oholecek.remove_42_support @@ -0,0 +1 @@ +- remove support for 4.2 file based pillars diff --git a/inter-server-sync.changes.oholecek.use_correct_hostname_detection b/inter-server-sync.changes.oholecek.use_correct_hostname_detection new file mode 100644 index 0000000..f355dfc --- /dev/null +++ b/inter-server-sync.changes.oholecek.use_correct_hostname_detection @@ -0,0 +1,2 @@ +- use correct hostname detection for 5.x servers + (bsc#1253322) diff --git a/tests/utils.go b/tests/utils.go index c997b3d..b51bc18 100644 --- a/tests/utils.go +++ b/tests/utils.go @@ -9,6 +9,8 @@ import ( "database/sql" "database/sql/driver" "fmt" + "os" + "testing" "github.com/DATA-DOG/go-sqlmock" ) @@ -113,3 +115,18 @@ func checkErr(err error) { panic(err) } } + +// create a temp file with a dummy password +func CreateTempFile(t *testing.T, content string) string { + t.Helper() + f, err := os.CreateTemp("", "issv2") + if err != nil { + t.Fatalf("failed to create temp file: %v", err) + } + _, err = f.WriteString(content) + if err != nil { + t.Fatalf("failed to write to temp file: %v", err) + } + f.Close() + return f.Name() +} diff --git a/utils/utils.go b/utils/utils.go index 484937c..c5ff641 100755 --- a/utils/utils.go +++ b/utils/utils.go @@ -98,16 +98,21 @@ func GetCurrentServerVersion(serverConfig string) (string, string) { return version, product } -func GetCurrentServerFQDN(serverConfig string) string { +func GetCurrentServerFQDN(serverConfig string) (string, error) { files := []string{serverConfig} files = append(files, getDefaultConfigs()...) - property := []string{"cobbler.host"} + property := []string{"java.hostname"} p, err := getProperty(files, property) if err != nil { - log.Error().Msgf("FQDN of server not found, images pillar may not be processed correclty") - return "" + // This still might be 4.3 server, try cobbler.host + property = []string{"cobbler.host"} + p, err = getProperty(files, property) + if err != nil { + log.Error().Msgf(", images pillar may not be processed correctly") + return "", fmt.Errorf("FQDN of server not found") + } } - return p + return p, nil } func getProperty(filePaths []string, names []string) (string, error) { @@ -125,7 +130,8 @@ func getProperty(filePaths []string, names []string) (string, error) { func ScannerFunc(path string, search string) (string, error) { f, err := os.Open(path) if err != nil { - log.Fatal().Msgf("Couldn't open file: %s", path) + log.Error().Msgf("Couldn't open file: %s", path) + return "", err } defer f.Close() scanner := bufio.NewScanner(f) diff --git a/utils/utils_test.go b/utils/utils_test.go index 71d8492..308c693 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -5,7 +5,10 @@ package utils import ( + "os" "testing" + + "github.com/uyuni-project/inter-server-sync/tests" ) func TestArrayRevert(t *testing.T) { @@ -41,3 +44,101 @@ func TestValidateDateInvalid(t *testing.T) { t.Errorf("The date is not validated properly.") } } + +func TestGetCurrentServerFQDN43(t *testing.T) { + rhnconf := ` +# OSA configuration # + +server.jabber_server = myhostname.example.com +osa-dispatcher.jabber_server = myhostname.example.com + +# set up SSL on the dispatcher +osa-dispatcher.osa_ssl_cert = /srv/www/htdocs/pub/RHN-ORG-TRUSTED-SSL-CERT + +# system snapshots enabled +enable_snapshots = 1 + +#cobbler host name +cobbler.host = myhostname.example.com + +# Maximum Java Heap Size (in MB) +# taskomatic.java.maxmemory=4096 + +# Extended reposync filters to use the entire NEVRA +server.satellite.reposync_nevra_filter = 0 +#option generated from rhn-config-satellite.pl +disconnected=1 + +#option generated from rhn-config-satellite.pl +product_name=SUSE Manager + ` + tmpFile := tests.CreateTempFile(t, rhnconf) + defer os.Remove(tmpFile) + + fqdn, err := GetCurrentServerFQDN(tmpFile) + if err != nil { + t.Error("Error during hostname lookup") + } + if fqdn != "myhostname.example.com" { + t.Error("Wrong hostname found") + } +} + +func TestGetCurrentServerFQDN(t *testing.T) { + rhnconf := ` +# OSA configuration # + +java.hostname = myhostname.example.com +osa-dispatcher.jabber_server = myhostname.example.com + +# set up SSL on the dispatcher +osa-dispatcher.osa_ssl_cert = /srv/www/htdocs/pub/RHN-ORG-TRUSTED-SSL-CERT + +# system snapshots enabled +enable_snapshots = 1 + +#cobbler host name +cobbler.host = localhost + +# Maximum Java Heap Size (in MB) +# taskomatic.java.maxmemory=4096 + ` + tmpFile := tests.CreateTempFile(t, rhnconf) + defer os.Remove(tmpFile) + + fqdn, err := GetCurrentServerFQDN(tmpFile) + if err != nil { + t.Error("Error during hostname lookup") + } + if fqdn != "myhostname.example.com" { + t.Error("Wrong hostname found") + } +} + +func TestGetCurrentServerFQDNInvalid(t *testing.T) { + rhnconf := ` + # OSA configuration # + +server.jabber_server = myhostname.example.com +osa-dispatcher.jabber_server = myhostname.example.com + +# set up SSL on the dispatcher +osa-dispatcher.osa_ssl_cert = /srv/www/htdocs/pub/RHN-ORG-TRUSTED-SSL-CERT + +# system snapshots enabled +enable_snapshots = 1 + +# Maximum Java Heap Size (in MB) +# taskomatic.java.maxmemory=4096 + ` + tmpFile := tests.CreateTempFile(t, rhnconf) + defer os.Remove(tmpFile) + + fqdn, err := GetCurrentServerFQDN(tmpFile) + if err == nil { + t.Error("Unexpected success for FQDN lookup") + } + if fqdn != "" { + t.Error("Hostname found even when not supposed to") + } +}