Repository: cloudnative-pg/cloudnative-pg

Issue:
[Feature]: allow additionalCommandArgs to be passed to `barman-cloud-wal-restore`
### Is there an existing issue already for this feature request/idea?

- [X] I have searched for an existing issue, and could not find anything. I believe this is a new feature request to be evaluated.

### What problem is this feature going to solve? Why should it be added?

The operator currently supports `additionalCommandArgs` for `barman-cloud-backup` and `barman-cloud-wal-archive`. To ensure completeness, we should also add support for additional arguments to `barman-cloud-wal-restore`.

### Describe the solution you'd like

Since the `additionalCommandArgs` for archiving has not yet been released, I suggest renaming it to `archiveAdditionalCommandArgs` and introducing `restoreAdditionalCommandArgs`.

The `restoreAdditionalCommandArgs` parameter would affect replicas within the same cluster when specified in the backup stanza. Additionally, it would impact the restore process from remote locations when specified in the externalCluster stanza.

### Describe alternatives you've considered

An alternative could be to leave the field driving the WAL archiving as it is and only add the new parameter, but I wouldn't say I like the solution because it is not symmetrical.

### Additional context

_No response_

### Backport?

No

### Are you willing to actively contribute to this feature?

Yes

### Code of Conduct

- [X] I agree to follow this project's Code of Conduct

Discussion:
@gbartolini: Related to #4357 @maxpain: Please fix the docs. There is `wal.additionalCommandArgs`.

<img width="373" alt="Image" src="https://github.com/user-attachments/assets/a19a74d4-d9a7-436c-b6c1-2415966710de" />

```
Cluster/gameflare/gf-pg dry-run failed: failed to create typed patch object (gameflare/gf-pg; postgresql.cnpg.io/v1, Kind=Cluster): .spec.backup.barmanObjectStore.wal.additionalCommandArgs: field not declared in schema
```

Solution patch:
diff --git a/.wordlist-en-custom.txt b/.wordlist-en-custom.txt
index fdc7253c..6b9e6621 100644
--- a/.wordlist-en-custom.txt
+++ b/.wordlist-en-custom.txt
@@ -497,6 +497,7 @@ applicationCredentials
 applicationSecretVersion
 appsv
 appuser
+archiveAdditionalCommandArgs
 archiver
 args
 armru
@@ -1063,6 +1064,7 @@ resizeInUseVolumes
 resizingPVC
 resourceVersion
 resourcerequirements
+restoreAdditionalCommandArgs
 resync
 retentionPolicy
 reusePVC
diff --git a/api/v1/cluster_types.go b/api/v1/cluster_types.go
index 69036d88..e7b08408 100644
--- a/api/v1/cluster_types.go
+++ b/api/v1/cluster_types.go
@@ -2193,10 +2193,9 @@ type WalBackupConfiguration struct {
 	// +kubebuilder:validation:Minimum=1
 	// +optional
 	MaxParallel int `json:"maxParallel,omitempty"`
-	// AdditionalCommandArgs represents additional arguments that can be appended
-	// to the 'barman-cloud-wal-archive' command-line invocation. These arguments
-	// provide flexibility to customize the backup process further according to
-	// specific requirements or configurations.
+	// Additional arguments that can be appended to the 'barman-cloud-wal-archive'
+	// command-line invocation. These arguments provide flexibility to customize
+	// the WAL archive process further, according to specific requirements or configurations.
 	//
 	// Example:
 	// In a scenario where specialized backup options are required, such as setting
@@ -2207,7 +2206,22 @@ type WalBackupConfiguration struct {
 	// It's essential to ensure that the provided arguments are valid and supported
 	// by the 'barman-cloud-wal-archive' command, to avoid potential errors or unintended
 	// behavior during execution.
-	AdditionalCommandArgs []string `json:"additionalCommandArgs,omitempty"`
+	ArchiveAdditionalCommandArgs []string `json:"archiveAdditionalCommandArgs,omitempty"`
+
+	// Additional arguments that can be appended to the 'barman-cloud-wal-restore'
+	// command-line invocation. These arguments provide flexibility to customize
+	// the WAL restore process further, according to specific requirements or configurations.
+	//
+	// Example:
+	// In a scenario where specialized backup options are required, such as setting
+	// a specific timeout or defining custom behavior, users can use this field
+	// to specify additional command arguments.
+	//
+	// Note:
+	// It's essential to ensure that the provided arguments are valid and supported
+	// by the 'barman-cloud-wal-restore' command, to avoid potential errors or unintended
+	// behavior during execution.
+	RestoreAdditionalCommandArgs []string `json:"restoreAdditionalCommandArgs,omitempty"`
 }
 
 // DataBackupConfiguration is the configuration of the backup of
@@ -2418,12 +2432,20 @@ func (cfg *DataBackupConfiguration) AppendAdditionalCommandArgs(options []string
 	return appendAdditionalCommandArgs(cfg.AdditionalCommandArgs, options)
 }
 
-// AppendAdditionalCommandArgs adds custom arguments as barman-cloud-wal-archive command-line options
-func (cfg *WalBackupConfiguration) AppendAdditionalCommandArgs(options []string) []string {
-	if cfg == nil || len(cfg.AdditionalCommandArgs) == 0 {
+// AppendArchiveAdditionalCommandArgs adds custom arguments as barman-cloud-wal-archive command-line options
+func (cfg *WalBackupConfiguration) AppendArchiveAdditionalCommandArgs(options []string) []string {
+	if cfg == nil || len(cfg.ArchiveAdditionalCommandArgs) == 0 {
 		return options
 	}
-	return appendAdditionalCommandArgs(cfg.AdditionalCommandArgs, options)
+	return appendAdditionalCommandArgs(cfg.ArchiveAdditionalCommandArgs, options)
+}
+
+// AppendRestoreAdditionalCommandArgs adds custom arguments as barman-cloud-wal-restore command-line options
+func (cfg *WalBackupConfiguration) AppendRestoreAdditionalCommandArgs(options []string) []string {
+	if cfg == nil || len(cfg.RestoreAdditionalCommandArgs) == 0 {
+		return options
+	}
+	return appendAdditionalCommandArgs(cfg.RestoreAdditionalCommandArgs, options)
 }
 
 func appendAdditionalCommandArgs(additionalCommandArgs []string, options []string) []string {
diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go
index 78df42c0..bcf10fa4 100644
--- a/api/v1/zz_generated.deepcopy.go
+++ b/api/v1/zz_generated.deepcopy.go
@@ -2826,8 +2826,13 @@ func (in *VolumeSnapshotConfiguration) DeepCopy() *VolumeSnapshotConfiguration {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *WalBackupConfiguration) DeepCopyInto(out *WalBackupConfiguration) {
 	*out = *in
-	if in.AdditionalCommandArgs != nil {
-		in, out := &in.AdditionalCommandArgs, &out.AdditionalCommandArgs
+	if in.ArchiveAdditionalCommandArgs != nil {
+		in, out := &in.ArchiveAdditionalCommandArgs, &out.ArchiveAdditionalCommandArgs
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.RestoreAdditionalCommandArgs != nil {
+		in, out := &in.RestoreAdditionalCommandArgs, &out.RestoreAdditionalCommandArgs
 		*out = make([]string, len(*in))
 		copy(*out, *in)
 	}
diff --git a/config/crd/bases/postgresql.cnpg.io_clusters.yaml b/config/crd/bases/postgresql.cnpg.io_clusters.yaml
index 8b8245bc..bd3b5f58 100644
--- a/config/crd/bases/postgresql.cnpg.io_clusters.yaml
+++ b/config/crd/bases/postgresql.cnpg.io_clusters.yaml
@@ -1324,12 +1324,11 @@ spec:
                           When not defined, WAL files will be stored uncompressed and may be
                           unencrypted in the object store, according to the bucket default policy.
                         properties:
-                          additionalCommandArgs:
+                          archiveAdditionalCommandArgs:
                             description: |-
-                              AdditionalCommandArgs represents additional arguments that can be appended
-                              to the 'barman-cloud-wal-archive' command-line invocation. These arguments
-                              provide flexibility to customize the backup process further according to
-                              specific requirements or configurations.
+                              Additional arguments that can be appended to the 'barman-cloud-wal-archive'
+                              command-line invocation. These arguments provide flexibility to customize
+                              the WAL archive process further, according to specific requirements or configurations.
 
 
                               Example:
@@ -1374,6 +1373,26 @@ spec:
                               value - with 1 being the minimum accepted value.
                             minimum: 1
                             type: integer
+                          restoreAdditionalCommandArgs:
+                            description: |-
+                              Additional arguments that can be appended to the 'barman-cloud-wal-restore'
+                              command-line invocation. These arguments provide flexibility to customize
+                              the WAL restore process further, according to specific requirements or configurations.
+
+
+                              Example:
+                              In a scenario where specialized backup options are required, such as setting
+                              a specific timeout or defining custom behavior, users can use this field
+                              to specify additional command arguments.
+
+
+                              Note:
+                              It's essential to ensure that the provided arguments are valid and supported
+                              by the 'barman-cloud-wal-restore' command, to avoid potential errors or unintended
+                              behavior during execution.
+                            items:
+                              type: string
+                            type: array
                         type: object
                     required:
                     - destinationPath
@@ -2669,12 +2688,11 @@ spec:
                             When not defined, WAL files will be stored uncompressed and may be
                             unencrypted in the object store, according to the bucket default policy.
                           properties:
-                            additionalCommandArgs:
+                            archiveAdditionalCommandArgs:
                               description: |-
-                                AdditionalCommandArgs represents additional arguments that can be appended
-                                to the 'barman-cloud-wal-archive' command-line invocation. These arguments
-                                provide flexibility to customize the backup process further according to
-                                specific requirements or configurations.
+                                Additional arguments that can be appended to the 'barman-cloud-wal-archive'
+                                command-line invocation. These arguments provide flexibility to customize
+                                the WAL archive process further, according to specific requirements or configurations.
 
 
                                 Example:
@@ -2719,6 +2737,26 @@ spec:
                                 value - with 1 being the minimum accepted value.
                               minimum: 1
                               type: integer
+                            restoreAdditionalCommandArgs:
+                              description: |-
+                                Additional arguments that can be appended to the 'barman-cloud-wal-restore'
+                                command-line invocation. These arguments provide flexibility to customize
+                                the WAL restore process further, according to specific requirements or configurations.
+
+
+                                Example:
+                                In a scenario where specialized backup options are required, such as setting
+                                a specific timeout or defining custom behavior, users can use this field
+                                to specify additional command arguments.
+
+
+                                Note:
+                                It's essential to ensure that the provided arguments are valid and supported
+                                by the 'barman-cloud-wal-restore' command, to avoid potential errors or unintended
+                                behavior during execution.
+                              items:
+                                type: string
+                              type: array
                           type: object
                       required:
                       - destinationPath
diff --git a/docs/src/cloudnative-pg.v1.md b/docs/src/cloudnative-pg.v1.md
index c0c27487..48473dd1 100644
--- a/docs/src/cloudnative-pg.v1.md
+++ b/docs/src/cloudnative-pg.v1.md
@@ -5384,14 +5384,13 @@ will be processed one at a time. It accepts a positive integer as a
 value - with 1 being the minimum accepted value.</p>
 </td>
 </tr>
-<tr><td><code>additionalCommandArgs</code> <B>[Required]</B><br/>
+<tr><td><code>archiveAdditionalCommandArgs</code> <B>[Required]</B><br/>
 <i>[]string</i>
 </td>
 <td>
-   <p>AdditionalCommandArgs represents additional arguments that can be appended
-to the 'barman-cloud-wal-archive' command-line invocation. These arguments
-provide flexibility to customize the backup process further according to
-specific requirements or configurations.</p>
+   <p>Additional arguments that can be appended to the 'barman-cloud-wal-archive'
+command-line invocation. These arguments provide flexibility to customize
+the WAL archive process further, according to specific requirements or configurations.</p>
 <p>Example:
 In a scenario where specialized backup options are required, such as setting
 a specific timeout or defining custom behavior, users can use this field
@@ -5402,5 +5401,22 @@ by the 'barman-cloud-wal-archive' command, to avoid potential errors or unintend
 behavior during execution.</p>
 </td>
 </tr>
+<tr><td><code>restoreAdditionalCommandArgs</code> <B>[Required]</B><br/>
+<i>[]string</i>
+</td>
+<td>
+   <p>Additional arguments that can be appended to the 'barman-cloud-wal-restore'
+command-line invocation. These arguments provide flexibility to customize
+the WAL restore process further, according to specific requirements or configurations.</p>
+<p>Example:
+In a scenario where specialized backup options are required, such as setting
+a specific timeout or defining custom behavior, users can use this field
+to specify additional command arguments.</p>
+<p>Note:
+It's essential to ensure that the provided arguments are valid and supported
+by the 'barman-cloud-wal-restore' command, to avoid potential errors or unintended
+behavior during execution.</p>
+</td>
+</tr>
 </tbody>
 </table>
\ No newline at end of file
diff --git a/internal/cmd/manager/walarchive/cmd.go b/internal/cmd/manager/walarchive/cmd.go
index 4e5958b6..2658d484 100644
--- a/internal/cmd/manager/walarchive/cmd.go
+++ b/internal/cmd/manager/walarchive/cmd.go
@@ -368,7 +368,7 @@ func barmanCloudWalArchiveOptions(
 				"-e",
 				string(configuration.Wal.Encryption))
 		}
-		options = configuration.Wal.AppendAdditionalCommandArgs(options)
+		options = configuration.Wal.AppendArchiveAdditionalCommandArgs(options)
 	}
 	if len(configuration.EndpointURL) > 0 {
 		options = append(
diff --git a/pkg/management/barman/commandbuilder.go b/pkg/management/barman/commandbuilder.go
index 360200bf..95207f20 100644
--- a/pkg/management/barman/commandbuilder.go
+++ b/pkg/management/barman/commandbuilder.go
@@ -48,6 +48,8 @@ func CloudWalRestoreOptions(
 	}
 
 	options = append(options, configuration.DestinationPath, serverName)
+	options = configuration.Wal.AppendRestoreAdditionalCommandArgs(options)
+
 	return options, nil
 }
 



Test patch:
diff --git a/internal/cmd/manager/walarchive/cmd_test.go b/internal/cmd/manager/walarchive/cmd_test.go
index 202591fe..dfa06c25 100644
--- a/internal/cmd/manager/walarchive/cmd_test.go
+++ b/internal/cmd/manager/walarchive/cmd_test.go
@@ -29,24 +29,28 @@ import (
 
 var _ = Describe("barmanCloudWalArchiveOptions", func() {
 	const namespace = "test"
-	cluster := &apiv1.Cluster{
-		ObjectMeta: metav1.ObjectMeta{Name: "test-cluster", Namespace: namespace},
-		Spec: apiv1.ClusterSpec{
-			Backup: &apiv1.BackupConfiguration{
-				BarmanObjectStore: &apiv1.BarmanObjectStoreConfiguration{
-					DestinationPath: "s3://bucket-name/",
-					Wal: &apiv1.WalBackupConfiguration{
-						Compression: "gzip",
-						Encryption:  "aes256",
+	var cluster *apiv1.Cluster
+
+	BeforeEach(func() {
+		cluster = &apiv1.Cluster{
+			ObjectMeta: metav1.ObjectMeta{Name: "test-cluster", Namespace: namespace},
+			Spec: apiv1.ClusterSpec{
+				Backup: &apiv1.BackupConfiguration{
+					BarmanObjectStore: &apiv1.BarmanObjectStoreConfiguration{
+						DestinationPath: "s3://bucket-name/",
+						Wal: &apiv1.WalBackupConfiguration{
+							Compression: "gzip",
+							Encryption:  "aes256",
+						},
 					},
 				},
 			},
-		},
-	}
+		}
+	})
 
 	It("should generate correct arguments", func() {
 		extraOptions := []string{"--min-chunk-size=5MB", "--read-timeout=60", "-vv"}
-		cluster.Spec.Backup.BarmanObjectStore.Wal.AdditionalCommandArgs = extraOptions
+		cluster.Spec.Backup.BarmanObjectStore.Wal.ArchiveAdditionalCommandArgs = extraOptions
 		options, err := barmanCloudWalArchiveOptions(cluster, "test-cluster")
 		Expect(err).ToNot(HaveOccurred())
 		Expect(strings.Join(options, " ")).
@@ -66,7 +70,7 @@ var _ = Describe("barmanCloudWalArchiveOptions", func() {
 			"-e",
 			"aes256",
 		}
-		cluster.Spec.Backup.BarmanObjectStore.Wal.AdditionalCommandArgs = extraOptions
+		cluster.Spec.Backup.BarmanObjectStore.Wal.ArchiveAdditionalCommandArgs = extraOptions
 		options, err := barmanCloudWalArchiveOptions(cluster, "test-cluster")
 		Expect(err).ToNot(HaveOccurred())
 
diff --git a/pkg/management/barman/commandbuilder_test.go b/pkg/management/barman/commandbuilder_test.go
new file mode 100644
index 00000000..4b16cb52
--- /dev/null
+++ b/pkg/management/barman/commandbuilder_test.go
@@ -0,0 +1,70 @@
+/*
+Copyright The CloudNativePG Contributors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package barman
+
+import (
+	"strings"
+
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	apiv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
+
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
+)
+
+var _ = Describe("barmanCloudWalRestoreOptions", func() {
+	const namespace = "test"
+	var cluster *apiv1.Cluster
+
+	BeforeEach(func() {
+		cluster = &apiv1.Cluster{
+			ObjectMeta: metav1.ObjectMeta{Name: "test-cluster", Namespace: namespace},
+			Spec: apiv1.ClusterSpec{
+				Backup: &apiv1.BackupConfiguration{
+					BarmanObjectStore: &apiv1.BarmanObjectStoreConfiguration{
+						DestinationPath: "s3://bucket-name/",
+					},
+				},
+			},
+		}
+	})
+
+	It("should generate correct arguments without the wal stanza", func() {
+		options, err := CloudWalRestoreOptions(cluster.Spec.Backup.BarmanObjectStore, "test-cluster")
+		Expect(err).ToNot(HaveOccurred())
+		Expect(strings.Join(options, " ")).
+			To(
+				Equal(
+					"s3://bucket-name/ test-cluster",
+				))
+	})
+
+	It("should generate correct arguments", func() {
+		extraOptions := []string{"--read-timeout=60", "-vv"}
+		cluster.Spec.Backup.BarmanObjectStore.Wal = &apiv1.WalBackupConfiguration{
+			RestoreAdditionalCommandArgs: extraOptions,
+		}
+		options, err := CloudWalRestoreOptions(cluster.Spec.Backup.BarmanObjectStore, "test-cluster")
+		Expect(err).ToNot(HaveOccurred())
+		Expect(strings.Join(options, " ")).
+			To(
+				Equal(
+					"s3://bucket-name/ test-cluster --read-timeout=60 -vv",
+				))
+	})
+})