Skip to content

Commit

Permalink
feat: gcp object storage implementation (#344)
Browse files Browse the repository at this point in the history
  • Loading branch information
goncalo-rodrigues authored Jul 11, 2022
1 parent bceb0d6 commit b2787f7
Show file tree
Hide file tree
Showing 16 changed files with 454 additions and 55 deletions.
190 changes: 141 additions & 49 deletions api/proto/resourcespb/object_storage.pb.go

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions api/proto/resourcespb/object_storage.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,22 @@ message DeleteObjectStorageRequest {
string resource_id = 1;
}

message ObjectStorageGcpOverride {
string project = 1;
}

message ObjectStorageArgs {
common.ResourceCommonArgs common_parameters = 1;
string name = 2;
bool versioning = 3;

ObjectStorageGcpOverride gcp_override = 4;
}

message ObjectStorageResource {
common.CommonResourceParameters common_parameters = 1;
string name = 2;
bool versioning = 3;

ObjectStorageGcpOverride gcp_override = 4;
}
9 changes: 8 additions & 1 deletion resources/common/cloud_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,13 @@ func NewGcpResource(resourceId string, name string, project string) *GcpResource
}
}

func NewGcpResourceWithNoProject(resourceId string, name string) *GcpResource {
return &GcpResource{
TerraformResource: output.TerraformResource{ResourceId: resourceId},
Name: name,
}
}

func (r *AwsResource) SetName(name string) {
//r.ResourceName = name
r.TerraformResource.ResourceName = name
Expand All @@ -213,5 +220,5 @@ type AwsResource struct {
type GcpResource struct {
output.TerraformResource `hcl:",squash"`
Name string `hcl:"name" hcle:"omitempty"`
Project string `hcl:"project"`
Project string `hcl:"project" hcle:"omitempty"`
}
14 changes: 14 additions & 0 deletions resources/output/object_storage/gcp_storage_bucket.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package object_storage

import "github.com/multycloud/multy/resources/common"

type GoogleStorageBucket struct {
*common.GcpResource `hcl:",squash" default:"name=google_storage_bucket"`
UniformBucketLevelAccess bool `hcl:"uniform_bucket_level_access"`
Versioning GoogleStorageBucketVersioning `hcl:"versioning" hcle:"omitempty"`
Location string `hcl:"location"`
}

type GoogleStorageBucketVersioning struct {
Enabled bool `hcl:"enabled"`
}
21 changes: 21 additions & 0 deletions resources/output/object_storage_object/gcp_storage_object.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package object_storage_object

import (
"github.com/multycloud/multy/resources/common"
"github.com/multycloud/multy/resources/output"
)

type GoogleStorageBucketObject struct {
*common.GcpResource `hcl:",squash" default:"name=google_storage_bucket_object"`
Bucket string `hcl:"bucket,expr" hcl:"Bucket"`
Content string `hcl:"content,expr"`
ContentType string `hcl:"content_type" hcle:"omitempty"`
}

type GoogleStorageObjectAccessControl struct {
*output.TerraformResource `hcl:",squash" default:"name=google_storage_object_access_control"`
Object string `hcl:"object,expr"`
Bucket string `hcl:"bucket,expr"`
Role string `hcl:"role"`
Entity string `hcl:"entity"`
}
5 changes: 3 additions & 2 deletions resources/types/aws/object_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ func (r AwsObjectStorage) FromState(state *output.TfState) (*resourcespb.ObjectS
CloudProvider: r.Args.CommonParameters.CloudProvider,
NeedsUpdate: false,
},
Name: r.Args.Name,
Versioning: r.Args.Versioning,
Name: r.Args.Name,
Versioning: r.Args.Versioning,
GcpOverride: r.Args.GcpOverride,
}, nil
}

Expand Down
5 changes: 3 additions & 2 deletions resources/types/azure/object_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ func (r AzureObjectStorage) FromState(state *output.TfState) (*resourcespb.Objec
CloudProvider: r.Args.CommonParameters.CloudProvider,
NeedsUpdate: false,
},
Name: r.Args.Name,
Versioning: r.Args.Versioning,
Name: r.Args.Name,
Versioning: r.Args.Versioning,
GcpOverride: r.Args.GcpOverride,
}, nil
}

Expand Down
50 changes: 50 additions & 0 deletions resources/types/gcp/object_storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package gcp_resources

import (
"github.com/multycloud/multy/api/proto/commonpb"
"github.com/multycloud/multy/api/proto/resourcespb"
"github.com/multycloud/multy/resources"
"github.com/multycloud/multy/resources/common"
"github.com/multycloud/multy/resources/output"
"github.com/multycloud/multy/resources/output/object_storage"
"github.com/multycloud/multy/resources/types"
)

type GcpObjectStorage struct {
*types.ObjectStorage
}

func InitObjectStorage(o *types.ObjectStorage) resources.ResourceTranslator[*resourcespb.ObjectStorageResource] {
return GcpObjectStorage{o}
}

func (r GcpObjectStorage) FromState(state *output.TfState) (*resourcespb.ObjectStorageResource, error) {
return &resourcespb.ObjectStorageResource{
CommonParameters: &commonpb.CommonResourceParameters{
ResourceId: r.ResourceId,
ResourceGroupId: r.Args.CommonParameters.ResourceGroupId,
Location: r.Args.CommonParameters.Location,
CloudProvider: r.Args.CommonParameters.CloudProvider,
NeedsUpdate: false,
},
Name: r.Args.Name,
Versioning: r.Args.Versioning,
GcpOverride: r.Args.GcpOverride,
}, nil
}

func (r GcpObjectStorage) Translate(resources.MultyContext) ([]output.TfBlock, error) {
o := &object_storage.GoogleStorageBucket{
GcpResource: common.NewGcpResource(r.ResourceId, r.Args.Name, r.Args.GetGcpOverride().GetProject()),
UniformBucketLevelAccess: false,
Location: r.GetCloudSpecificLocation(),
}
if r.Args.Versioning {
o.Versioning = object_storage.GoogleStorageBucketVersioning{Enabled: true}
}
return []output.TfBlock{o}, nil
}

func (r GcpObjectStorage) GetMainResourceName() (string, error) {
return output.GetResourceName(object_storage.GoogleStorageBucket{}), nil
}
84 changes: 84 additions & 0 deletions resources/types/gcp/object_storage_object.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package gcp_resources

import (
"fmt"
"github.com/multycloud/multy/api/proto/commonpb"
"github.com/multycloud/multy/api/proto/resourcespb"
"github.com/multycloud/multy/flags"
"github.com/multycloud/multy/resources"
"github.com/multycloud/multy/resources/common"
"github.com/multycloud/multy/resources/output"
"github.com/multycloud/multy/resources/output/object_storage"
"github.com/multycloud/multy/resources/output/object_storage_object"
"github.com/multycloud/multy/resources/types"
)

type GcpObjectStorageObject struct {
*types.ObjectStorageObject
}

func InitObjectStorageObject(vn *types.ObjectStorageObject) resources.ResourceTranslator[*resourcespb.ObjectStorageObjectResource] {
return GcpObjectStorageObject{vn}
}

func (r GcpObjectStorageObject) FromState(state *output.TfState) (*resourcespb.ObjectStorageObjectResource, error) {
out := new(resourcespb.ObjectStorageObjectResource)
out.CommonParameters = &commonpb.CommonChildResourceParameters{
ResourceId: r.ResourceId,
NeedsUpdate: false,
}

id, err := resources.GetMainOutputRef(r)
if err != nil {
return nil, err
}

out.Name = r.Args.Name
out.ContentBase64 = r.Args.ContentBase64
out.ContentType = r.Args.ContentType
out.ObjectStorageId = r.Args.ObjectStorageId
out.Acl = r.Args.Acl
out.Source = r.Args.Source

if !flags.DryRun {
stateResource, err := output.GetParsed[object_storage_object.GoogleStorageBucketObject](state, id)
if err != nil {
return nil, err
}
out.Url = fmt.Sprintf("https://storage.googleapis.com/%s/%s", stateResource.Bucket, r.Args.Name)
} else {
out.Url = "dryrun"
}

return out, nil
}

func (r GcpObjectStorageObject) Translate(resources.MultyContext) ([]output.TfBlock, error) {
var result []output.TfBlock
bucketName := fmt.Sprintf("%s.%s.name", output.GetResourceName(object_storage.GoogleStorageBucket{}), r.ObjectStorage.ResourceId)
result = append(result, &object_storage_object.GoogleStorageBucketObject{
GcpResource: common.NewGcpResourceWithNoProject(r.ResourceId, r.Args.Name),
Bucket: bucketName,
Content: fmt.Sprintf("base64decode(\"%s\")", r.Args.ContentBase64),
ContentType: r.Args.ContentType,
})

if r.Args.Acl == resourcespb.ObjectStorageObjectAcl_PUBLIC_READ {
objectName := fmt.Sprintf("%s.%s.output_name", output.GetResourceName(object_storage_object.GoogleStorageBucketObject{}), r.ResourceId)
result = append(result, &object_storage_object.GoogleStorageObjectAccessControl{
TerraformResource: &output.TerraformResource{
ResourceId: r.ResourceId,
},
Object: objectName,
Bucket: bucketName,
Role: "READER",
Entity: "allUsers",
})
}
return result, nil

}

func (r GcpObjectStorageObject) GetMainResourceName() (string, error) {
return output.GetResourceName(object_storage_object.GoogleStorageBucketObject{}), nil
}
2 changes: 2 additions & 0 deletions resources/types/metadata/all_resources_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ var Metadatas = map[proto.Message]resources.ResourceMetadataInterface{
Translators: map[commonpb.CloudProvider]func(*types.ObjectStorage) resources.ResourceTranslator[*resourcespb.ObjectStorageResource]{
commonpb.CloudProvider_AWS: aws_resources.InitObjectStorage,
commonpb.CloudProvider_AZURE: azure_resources.InitObjectStorage,
commonpb.CloudProvider_GCP: gcp_resources.InitObjectStorage,
},
},
&resourcespb.ObjectStorageObjectArgs{}: &resources.ResourceMetadata[*resourcespb.ObjectStorageObjectArgs, *types.ObjectStorageObject, *resourcespb.ObjectStorageObjectResource]{
Expand All @@ -122,6 +123,7 @@ var Metadatas = map[proto.Message]resources.ResourceMetadataInterface{
Translators: map[commonpb.CloudProvider]func(*types.ObjectStorageObject) resources.ResourceTranslator[*resourcespb.ObjectStorageObjectResource]{
commonpb.CloudProvider_AWS: aws_resources.InitObjectStorageObject,
commonpb.CloudProvider_AZURE: azure_resources.InitObjectStorageObject,
commonpb.CloudProvider_GCP: gcp_resources.InitObjectStorageObject,
},
},
&resourcespb.VaultArgs{}: &resources.ResourceMetadata[*resourcespb.VaultArgs, *types.Vault, *resourcespb.VaultResource]{
Expand Down
6 changes: 5 additions & 1 deletion resources/types/object_storage_object.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package types

import (
"encoding/base64"
"fmt"
"github.com/multycloud/multy/api/errors"
"github.com/multycloud/multy/api/proto/resourcespb"
Expand Down Expand Up @@ -46,7 +47,10 @@ func NewObjectStorageObject(r *ObjectStorageObject, resourceId string, args *res

func (r *ObjectStorageObject) Validate(ctx resources.MultyContext) (errs []validate.ValidationError) {
if len(r.Args.ContentBase64) == 0 {
errs = append(errs, r.NewValidationError(fmt.Errorf("content_base64 must be set"), ""))
errs = append(errs, r.NewValidationError(fmt.Errorf("content_base64 must be set"), "content_base64"))
}
if _, err := base64.StdEncoding.DecodeString(r.Args.ContentBase64); err != nil {
errs = append(errs, r.NewValidationError(fmt.Errorf("content_base64 is not a valid base64 string: %s", err), "content_base64"))
}
return errs
}
19 changes: 19 additions & 0 deletions test/_configs/object_storage/object_storage/config.textproto
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,25 @@ resources: {
}
}
}
resources: {
resource_id: "object_storage_gcp"
resource_args: {
resource_args: {
[type.googleapis.com/dev.multy.resources.ObjectStorageArgs]: {
common_parameters: {
resource_group_id: "rg1"
location: EU_WEST_1
cloud_provider: GCP
}
name: "test-storage-12384761234"
versioning: true
gcp_override: {
project: "multy-project"
}
}
}
}
}
resources: {
resource_id: "rg1"
resource_args: {
Expand Down
14 changes: 14 additions & 0 deletions test/_configs/object_storage/object_storage/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,17 @@ provider "azurerm" {
features {
}
}
resource "google_storage_bucket" "object_storage_gcp" {
name = "test-storage-12384761234"
project = "multy-project"
uniform_bucket_level_access = false
versioning {
enabled = true
}
location = "europe-west1"
provider = "google.europe-west1"
}
provider "google" {
region = "europe-west1"
alias = "europe-west1"
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,52 @@ resources: {
}
}
}
resources: {
resource_id: "obj_storage_GCP"
resource_args: {
resource_args: {
[type.googleapis.com/dev.multy.resources.ObjectStorageArgs]: {
common_parameters: {
resource_group_id: "rg1"
location: EU_WEST_1
cloud_provider: GCP
}
name: "test-storage-9999919"
gcp_override: {
project: "multy-project"
}
}
}
}
}
resources: {
resource_id: "file2_private_GCP"
resource_args: {
resource_args: {
[type.googleapis.com/dev.multy.resources.ObjectStorageObjectArgs]: {
name: "index_private.html"
object_storage_id: "obj_storage_GCP"
content_base64: "PGgxPkhpPC9oMT4="
content_type: "text/html"
}
}
}
}
resources: {
resource_id: "file1_public_GCP"
resource_args: {
resource_args: {
[type.googleapis.com/dev.multy.resources.ObjectStorageObjectArgs]: {
name: "index.html"
acl: PUBLIC_READ
object_storage_id: "obj_storage_GCP"
content_base64: "PGgxPkhpPC9oMT4="
content_type: "text/html"
}
}
}
}



# proto-file: api/proto/configpb/config.proto
Expand Down
Loading

0 comments on commit b2787f7

Please sign in to comment.