diff --git a/changelogs/unreleased/1405-skriss b/changelogs/unreleased/1405-skriss
new file mode 100644
index 000000000..62f954430
--- /dev/null
+++ b/changelogs/unreleased/1405-skriss
@@ -0,0 +1 @@
+GCP: add optional 'project' config to volume snapshot location for if snapshots are in a different project than the IAM account
diff --git a/docs/api-types/volumesnapshotlocation.md b/docs/api-types/volumesnapshotlocation.md
index 7d287dc73..10cc61735 100644
--- a/docs/api-types/volumesnapshotlocation.md
+++ b/docs/api-types/volumesnapshotlocation.md
@@ -57,6 +57,7 @@ The configurable parameters are as follows:
| Key | Type | Default | Meaning |
| --- | --- | --- | --- |
| `snapshotLocation` | string | Empty | *Example*: "us-central1"
See [GCP documentation][4] for the full list.
If not specified the snapshots are stored in the [default location][5]. |
+| `project` | string | Empty | The project ID where snapshots should be stored, if different than the project that your IAM account is in. Optional. |
[0]: #aws
[1]: #gcp
diff --git a/pkg/cloudprovider/gcp/volume_snapshotter.go b/pkg/cloudprovider/gcp/volume_snapshotter.go
index 8a1c5dc63..0cb9cf5e6 100644
--- a/pkg/cloudprovider/gcp/volume_snapshotter.go
+++ b/pkg/cloudprovider/gcp/volume_snapshotter.go
@@ -38,16 +38,17 @@ import (
)
const (
- projectKey = "project"
zoneSeparator = "__"
+ projectKey = "project"
snapshotLocationKey = "snapshotLocation"
)
type VolumeSnapshotter struct {
- gce *compute.Service
- project string
log logrus.FieldLogger
+ gce *compute.Service
snapshotLocation string
+ volumeProject string
+ snapshotProject string
}
func NewVolumeSnapshotter(logger logrus.FieldLogger) *VolumeSnapshotter {
@@ -55,7 +56,7 @@ func NewVolumeSnapshotter(logger logrus.FieldLogger) *VolumeSnapshotter {
}
func (b *VolumeSnapshotter) Init(config map[string]string) error {
- if err := cloudprovider.ValidateVolumeSnapshotterConfigKeys(config, snapshotLocationKey); err != nil {
+ if err := cloudprovider.ValidateVolumeSnapshotterConfigKeys(config, snapshotLocationKey, projectKey); err != nil {
return err
}
@@ -65,6 +66,14 @@ func (b *VolumeSnapshotter) Init(config map[string]string) error {
if err != nil {
return err
}
+ b.volumeProject = project
+
+ // get snapshot project from 'project' config key if specified,
+ // otherwise from the credentials file
+ b.snapshotProject = config[projectKey]
+ if b.snapshotProject == "" {
+ b.snapshotProject = b.volumeProject
+ }
client, err := google.DefaultClient(oauth2.NoContext, compute.ComputeScope)
if err != nil {
@@ -77,7 +86,6 @@ func (b *VolumeSnapshotter) Init(config map[string]string) error {
}
b.gce = gce
- b.project = project
return nil
}
@@ -139,7 +147,7 @@ func (b *VolumeSnapshotter) getZoneURLs(volumeAZ string) ([]string, error) {
zones := strings.Split(volumeAZ, zoneSeparator)
var zoneURLs []string
for _, z := range zones {
- zone, err := b.gce.Zones.Get(b.project, z).Do()
+ zone, err := b.gce.Zones.Get(b.volumeProject, z).Do()
if err != nil {
return nil, errors.WithStack(err)
}
@@ -152,7 +160,7 @@ func (b *VolumeSnapshotter) getZoneURLs(volumeAZ string) ([]string, error) {
func (b *VolumeSnapshotter) CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ string, iops *int64) (volumeID string, err error) {
// get the snapshot so we can apply its tags to the volume
- res, err := b.gce.Snapshots.Get(b.project, snapshotID).Do()
+ res, err := b.gce.Snapshots.Get(b.snapshotProject, snapshotID).Do()
if err != nil {
return "", errors.WithStack(err)
}
@@ -183,11 +191,11 @@ func (b *VolumeSnapshotter) CreateVolumeFromSnapshot(snapshotID, volumeType, vol
disk.ReplicaZones = zoneURLs
- if _, err = b.gce.RegionDisks.Insert(b.project, volumeRegion, disk).Do(); err != nil {
+ if _, err = b.gce.RegionDisks.Insert(b.volumeProject, volumeRegion, disk).Do(); err != nil {
return "", errors.WithStack(err)
}
} else {
- if _, err = b.gce.Disks.Insert(b.project, volumeAZ, disk).Do(); err != nil {
+ if _, err = b.gce.Disks.Insert(b.volumeProject, volumeAZ, disk).Do(); err != nil {
return "", errors.WithStack(err)
}
}
@@ -206,12 +214,12 @@ func (b *VolumeSnapshotter) GetVolumeInfo(volumeID, volumeAZ string) (string, *i
if err != nil {
return "", nil, errors.WithStack(err)
}
- res, err = b.gce.RegionDisks.Get(b.project, volumeRegion, volumeID).Do()
+ res, err = b.gce.RegionDisks.Get(b.volumeProject, volumeRegion, volumeID).Do()
if err != nil {
return "", nil, errors.WithStack(err)
}
} else {
- res, err = b.gce.Disks.Get(b.project, volumeAZ, volumeID).Do()
+ res, err = b.gce.Disks.Get(b.volumeProject, volumeAZ, volumeID).Do()
if err != nil {
return "", nil, errors.WithStack(err)
}
@@ -243,7 +251,7 @@ func (b *VolumeSnapshotter) CreateSnapshot(volumeID, volumeAZ string, tags map[s
}
func (b *VolumeSnapshotter) createSnapshot(snapshotName, volumeID, volumeAZ string, tags map[string]string) (string, error) {
- disk, err := b.gce.Disks.Get(b.project, volumeAZ, volumeID).Do()
+ disk, err := b.gce.Disks.Get(b.volumeProject, volumeAZ, volumeID).Do()
if err != nil {
return "", errors.WithStack(err)
}
@@ -257,7 +265,7 @@ func (b *VolumeSnapshotter) createSnapshot(snapshotName, volumeID, volumeAZ stri
gceSnap.StorageLocations = []string{b.snapshotLocation}
}
- _, err = b.gce.Disks.CreateSnapshot(b.project, volumeAZ, volumeID, &gceSnap).Do()
+ _, err = b.gce.Disks.CreateSnapshot(b.snapshotProject, volumeAZ, volumeID, &gceSnap).Do()
if err != nil {
return "", errors.WithStack(err)
}
@@ -266,7 +274,7 @@ func (b *VolumeSnapshotter) createSnapshot(snapshotName, volumeID, volumeAZ stri
}
func (b *VolumeSnapshotter) createRegionSnapshot(snapshotName, volumeID, volumeRegion string, tags map[string]string) (string, error) {
- disk, err := b.gce.RegionDisks.Get(b.project, volumeRegion, volumeID).Do()
+ disk, err := b.gce.RegionDisks.Get(b.volumeProject, volumeRegion, volumeID).Do()
if err != nil {
return "", errors.WithStack(err)
}
@@ -280,7 +288,7 @@ func (b *VolumeSnapshotter) createRegionSnapshot(snapshotName, volumeID, volumeR
gceSnap.StorageLocations = []string{b.snapshotLocation}
}
- _, err = b.gce.RegionDisks.CreateSnapshot(b.project, volumeRegion, volumeID, &gceSnap).Do()
+ _, err = b.gce.RegionDisks.CreateSnapshot(b.snapshotProject, volumeRegion, volumeID, &gceSnap).Do()
if err != nil {
return "", errors.WithStack(err)
}
@@ -323,7 +331,7 @@ func getSnapshotTags(veleroTags map[string]string, diskDescription string, log l
}
func (b *VolumeSnapshotter) DeleteSnapshot(snapshotID string) error {
- _, err := b.gce.Snapshots.Delete(b.project, snapshotID).Do()
+ _, err := b.gce.Snapshots.Delete(b.snapshotProject, snapshotID).Do()
// if it's a 404 (not found) error, we don't need to return an error
// since the snapshot is not there.