From 5385d6fca82c9afcd098ab8edd3e9e63eda2fccd Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Sun, 6 Jul 2025 17:54:07 +0200 Subject: [PATCH] Cut a new release. Simplify Debian build rules, more similar to govpp-snmp-agentx --- Makefile | 1 + debian/changelog | 10 ++++++++ debian/rules | 12 ++++++++-- src/main.go | 2 +- src/ssh_test.go | 62 ++++++++++++++++++++++++------------------------ 5 files changed, 53 insertions(+), 34 deletions(-) diff --git a/Makefile b/Makefile index 5c50cf8..37860ba 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,7 @@ build: sync-version .PHONY: clean clean: @echo "Cleaning build artifacts..." + [ -d debian/go ] && chmod -R +w debian/go || true rm -rf debian/.debhelper debian/.gocache debian/go debian/$(BINARY_NAME) debian/files debian/*.substvars debian/debhelper-build-stamp rm -f ../$(BINARY_NAME)_*.deb ../$(BINARY_NAME)_*.changes ../$(BINARY_NAME)_*.buildinfo rm -f $(BUILD_DIR)/$(BINARY_NAME) diff --git a/debian/changelog b/debian/changelog index 867a8e8..daa078c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,13 @@ +ipng-router-backup (1.1.0) stable; urgency=low + + * Replace --config flag with --yaml flag supporting multiple files + * Switch from !include to mergo-based configuration merging + * Add SSH config integration for legacy device compatibility + * Refactor SSH functionality into separate module + * Add comprehensive test coverage + + -- Pim van Pelt Sun, 07 Jul 2025 15:30:00 +0100 + ipng-router-backup (1.0.2) stable; urgency=low * Add YAML !include directive support for configuration files diff --git a/debian/rules b/debian/rules index e677d85..641590a 100755 --- a/debian/rules +++ b/debian/rules @@ -1,23 +1,31 @@ #!/usr/bin/make -f +export GO111MODULE = on +export GOPROXY = https://proxy.golang.org,direct +export GOCACHE = $(CURDIR)/debian/.gocache +export GOPATH = $(CURDIR)/debian/go + %: dh $@ override_dh_auto_build: - cd src && go build -o ../ipng-router-backup main.go + mkdir -p $(GOCACHE) $(GOPATH) + cd src && go build -o ../ipng-router-backup . override_dh_auto_install: mkdir -p debian/ipng-router-backup/usr/bin mkdir -p debian/ipng-router-backup/etc/ipng-router-backup mkdir -p debian/ipng-router-backup/usr/share/man/man1 cp ipng-router-backup debian/ipng-router-backup/usr/bin/ - cp docs/config.yaml.example debian/ipng-router-backup/etc/ipng-router-backup/config.yaml.example cp etc/* debian/ipng-router-backup/etc/ipng-router-backup/ cp docs/router_backup.1 debian/ipng-router-backup/usr/share/man/man1/ipng-router-backup.1 gzip debian/ipng-router-backup/usr/share/man/man1/ipng-router-backup.1 override_dh_auto_clean: rm -f ipng-router-backup + [ -d debian/go ] && chmod -R +w debian/go || true + for dir in obj-*; do [ -d "$$dir" ] && chmod -R +w "$$dir" || true; done + rm -rf debian/.gocache debian/go obj-* override_dh_auto_test: # Skip tests for now diff --git a/src/main.go b/src/main.go index 9e0f64f..982a08f 100644 --- a/src/main.go +++ b/src/main.go @@ -10,7 +10,7 @@ import ( "github.com/spf13/cobra" ) -const Version = "1.0.2" +const Version = "1.1.0" // Config and SSH types are now in separate packages diff --git a/src/ssh_test.go b/src/ssh_test.go index 7ed06be..f99faa0 100644 --- a/src/ssh_test.go +++ b/src/ssh_test.go @@ -8,27 +8,27 @@ import ( func TestNewRouterBackup(t *testing.T) { rb := NewRouterBackup("testhost", "testuser", "testpass", "/path/to/key", 2222) - + if rb.hostname != "testhost" { t.Errorf("Expected hostname 'testhost', got '%s'", rb.hostname) } - + if rb.username != "testuser" { t.Errorf("Expected username 'testuser', got '%s'", rb.username) } - + if rb.password != "testpass" { t.Errorf("Expected password 'testpass', got '%s'", rb.password) } - + if rb.keyFile != "/path/to/key" { t.Errorf("Expected keyFile '/path/to/key', got '%s'", rb.keyFile) } - + if rb.port != 2222 { t.Errorf("Expected port 2222, got %d", rb.port) } - + if rb.client != nil { t.Error("Expected client to be nil initially") } @@ -36,12 +36,12 @@ func TestNewRouterBackup(t *testing.T) { func TestRunCommandWithoutConnection(t *testing.T) { rb := NewRouterBackup("testhost", "testuser", "testpass", "", 22) - + _, err := rb.RunCommand("show version") if err == nil { t.Error("Expected error when running command without connection") } - + if err.Error() != "no active connection" { t.Errorf("Expected 'no active connection' error, got '%s'", err.Error()) } @@ -50,18 +50,18 @@ func TestRunCommandWithoutConnection(t *testing.T) { func TestBackupCommandsDirectoryCreation(t *testing.T) { tempDir := t.TempDir() outputDir := filepath.Join(tempDir, "nonexistent", "backup") - + rb := NewRouterBackup("testhost", "testuser", "testpass", "", 22) - + // This should create the directory even without a connection // and fail gracefully when trying to run commands _ = rb.BackupCommands([]string{"show version"}, outputDir) - + // Should not error on directory creation if _, statErr := os.Stat(outputDir); os.IsNotExist(statErr) { t.Error("Expected output directory to be created") } - + // Should create the output file even if commands fail expectedFile := filepath.Join(outputDir, "testhost") if _, statErr := os.Stat(expectedFile); os.IsNotExist(statErr) { @@ -71,14 +71,14 @@ func TestBackupCommandsDirectoryCreation(t *testing.T) { func TestBackupCommandsEmptyCommands(t *testing.T) { tempDir := t.TempDir() - + rb := NewRouterBackup("testhost", "testuser", "testpass", "", 22) - + err := rb.BackupCommands([]string{}, tempDir) if err != nil { t.Errorf("Expected no error for empty commands list, got %v", err) } - + // Should still create the output file expectedFile := filepath.Join(tempDir, "testhost") if _, statErr := os.Stat(expectedFile); os.IsNotExist(statErr) { @@ -88,7 +88,7 @@ func TestBackupCommandsEmptyCommands(t *testing.T) { func TestDisconnectWithoutConnection(t *testing.T) { rb := NewRouterBackup("testhost", "testuser", "testpass", "", 22) - + // Should not panic or error when disconnecting without connection rb.Disconnect() } @@ -99,31 +99,31 @@ func TestFindDefaultSSHKey(t *testing.T) { tempDir := t.TempDir() os.Setenv("HOME", tempDir) defer os.Setenv("HOME", originalHome) - + keyPath := findDefaultSSHKey() if keyPath != "" { t.Errorf("Expected empty string when no SSH keys exist, got '%s'", keyPath) } - + // Create .ssh directory and a test key sshDir := filepath.Join(tempDir, ".ssh") err := os.MkdirAll(sshDir, 0700) if err != nil { t.Fatalf("Failed to create .ssh directory: %v", err) } - + // Create id_rsa key (should be found first) rsaKeyPath := filepath.Join(sshDir, "id_rsa") err = os.WriteFile(rsaKeyPath, []byte("fake rsa key"), 0600) if err != nil { t.Fatalf("Failed to create RSA key: %v", err) } - + keyPath = findDefaultSSHKey() if keyPath != rsaKeyPath { t.Errorf("Expected to find RSA key at '%s', got '%s'", rsaKeyPath, keyPath) } - + // Remove RSA key and create ed25519 key os.Remove(rsaKeyPath) ed25519KeyPath := filepath.Join(sshDir, "id_ed25519") @@ -131,7 +131,7 @@ func TestFindDefaultSSHKey(t *testing.T) { if err != nil { t.Fatalf("Failed to create ed25519 key: %v", err) } - + keyPath = findDefaultSSHKey() if keyPath != ed25519KeyPath { t.Errorf("Expected to find ed25519 key at '%s', got '%s'", ed25519KeyPath, keyPath) @@ -143,7 +143,7 @@ func TestFindDefaultSSHKeyHomeError(t *testing.T) { originalHome := os.Getenv("HOME") os.Unsetenv("HOME") defer os.Setenv("HOME", originalHome) - + keyPath := findDefaultSSHKey() if keyPath != "" { t.Errorf("Expected empty string when HOME is not set, got '%s'", keyPath) @@ -152,39 +152,39 @@ func TestFindDefaultSSHKeyHomeError(t *testing.T) { func TestBackupCommandsFileOperations(t *testing.T) { tempDir := t.TempDir() - + rb := NewRouterBackup("testhost", "testuser", "testpass", "", 22) - + // Create some fake commands (they will fail but we can test file operations) commands := []string{"show version", "show interfaces"} - + err := rb.BackupCommands(commands, tempDir) if err != nil { t.Errorf("Unexpected error: %v", err) } - + // Check that output file was created outputFile := filepath.Join(tempDir, "testhost") _, err = os.ReadFile(outputFile) if err != nil { t.Fatalf("Failed to read output file: %v", err) } - + // File should be created (it will be empty if all commands fail) // This test just verifies the file creation works } func TestRouterBackupConnectionState(t *testing.T) { rb := NewRouterBackup("testhost", "testuser", "testpass", "", 22) - + // Initially no client if rb.client != nil { t.Error("Expected client to be nil initially") } - + // After disconnect, should still be nil (safe to call multiple times) rb.Disconnect() if rb.client != nil { t.Error("Expected client to remain nil after disconnect") } -} \ No newline at end of file +}