Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for File Share (NFS as a Service) #187

Merged
merged 8 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ require (
github.com/aws/aws-sdk-go-v2/service/ec2 v1.74.1
github.com/aws/aws-sdk-go-v2/service/s3 v1.29.5
github.com/briandowns/spinner v1.15.0
github.com/dave/dst v0.27.2
github.com/dustin/go-humanize v1.0.0
github.com/fatih/color v1.13.0
github.com/fatih/color v1.16.0
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.6.0
github.com/huandu/xstrings v1.3.2 // indirect
Expand Down Expand Up @@ -68,11 +67,11 @@ require (
github.com/hashicorp/hcl v1.0.1-vault // indirect
github.com/hashicorp/hcl/v2 v2.15.0
github.com/imdario/mergo v0.3.13
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
Expand All @@ -94,6 +93,7 @@ require (
require (
github.com/alecthomas/jsonschema v0.0.0-20211209230136-e2b41affa5c1
github.com/awslabs/goformation/v7 v7.2.5
github.com/dave/dst v0.27.3
github.com/go-git/go-billy/v5 v5.5.0
github.com/go-git/go-git/v5 v5.11.0
github.com/google/go-github/v41 v41.0.0
Expand Down Expand Up @@ -143,7 +143,7 @@ require (
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/frankban/quicktest v1.11.3 // indirect
github.com/frankban/quicktest v1.14.5 // indirect
github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
Expand All @@ -156,7 +156,7 @@ require (
github.com/goware/prefixer v0.0.0-20160118172347-395022866408 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
github.com/hashicorp/terraform v0.15.3 // indirect
Expand All @@ -169,7 +169,7 @@ require (
github.com/lithammer/fuzzysearch v1.1.5 // indirect
github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/mapstructure v1.3.3 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/opencontainers/runc v1.1.5 // indirect
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
Expand Down Expand Up @@ -203,7 +203,7 @@ require (
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/apparentlymart/go-cidr v1.1.0
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/aws/aws-sdk-go v1.43.16 // indirect
github.com/aws/aws-sdk-go v1.44.122 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/bmatcuk/doublestar v1.3.4
github.com/ghodss/yaml v1.0.0 // indirect
Expand All @@ -212,7 +212,7 @@ require (
github.com/google/go-querystring v1.1.0 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2
github.com/hashicorp/go-getter v1.6.2
github.com/hashicorp/go-getter v1.7.0
github.com/hashicorp/go-safetemp v1.0.0
github.com/hashicorp/go-uuid v1.0.3
github.com/hashicorp/go-version v1.6.0
Expand All @@ -238,3 +238,5 @@ require (
replace github.com/jedib0t/go-pretty/v6 => github.com/aliscott/go-pretty/v6 v6.1.1-0.20210226104003-408905a61c8e

replace github.com/spf13/cobra => github.com/spf13/cobra v1.4.0

replace github.com/zclconf/go-cty-yaml => github.ibm.com/dataops/go-cty-yaml v1.0.0
334 changes: 310 additions & 24 deletions go.sum

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions infracost-usage-example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ resource_type_default_usage:
elasticsearch_database_disk_mb: 131072
elasticsearch_database_core: 3
elasticsearch_database_members: 4
ibm_is_share:
is-share_monthly_instance_hours: 730
ibm_is_vpc_server:
is.vpn-server_CONNECTION_HOURS: 730
is.vpn-server_INSTANCE_HOURS: 730
Expand Down Expand Up @@ -1396,6 +1398,10 @@ resource_usage:
elasticsearch_database_core: 3 # Allocated dedicated CPU per-member
elasticsearch_database_members: 4 # Allocated number of members in the cluster

ibm_is_share.nfs:
is-share_monthly_instance_hours: 730 # Monthly number of instance hours
is-share_monthly_transmitted_gb: 1 # Data transmitted between two file shares for replication

ibm_is_vpc_server:
is.vpn-server_CONNECTION_HOURS: 730
is.vpn-server_INSTANCE_HOURS: 730
3 changes: 2 additions & 1 deletion internal/providers/terraform/ibm/ibm.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ type catalogMetadata struct {
// Map between terraform type and global catalog id. For ibm_resource_instance, the service
// field already matches the global catalog id, so they do not need to be mapped. eg: "kms"
var globalCatalogServiceId = map[string]catalogMetadata{
"ibm_is_vpc": {"is.vpc", []string{"ibm_is_flow_log"}, nil, "https://cloud.ibm.com/vpc-ext/provision/vpc"},
"ibm_is_vpc": {"is.vpc", []string{"ibm_is_flow_log", "ibm_is_share"}, nil, "https://cloud.ibm.com/vpc-ext/provision/vpc"},
"ibm_container_vpc_cluster": {"containers-kubernetes", []string{}, nil, "https://cloud.ibm.com/kubernetes/catalog/about#pricing"},
"ibm_container_vpc_worker_pool": {"containers-kubernetes", []string{}, nil, "https://cloud.ibm.com/kubernetes/catalog/about#pricing"},
"ibm_is_instance": {"is.instance", []string{"ibm_is_ssh_key", "ibm_is_floating_ip"}, nil, "https://cloud.ibm.com/vpc-ext/provision/vs"},
Expand Down Expand Up @@ -88,6 +88,7 @@ var globalCatalogServiceId = map[string]catalogMetadata{
"compliance": {"compliance", []string{}, nil, "https://cloud.ibm.com/catalog/services/security-and-compliance-center"},
"dns-svcs": {"b4ed8a30-936f-11e9-b289-1d079699cbe5", []string{}, nil, "https://cloud.ibm.com/catalog/services/dns-services"},
"messagehub": {"6a7f4e38-f218-48ef-9dd2-df408747568e", []string{}, nil, "https://cloud.ibm.com/eventstreams-provisioning/6a7f4e38-f218-48ef-9dd2-df408747568e/create"},
"ibm_is_share": {"is.share", []string{}, nil, "https://cloud.ibm.com/docs/vpc?topic=vpc-file-storage-vpc-faqs&interface=ui#faq-fs-billing"},
"ibm_is_vpn_server": {"is.vpn-server", []string{}, nil, "https://cloud.ibm.com/vpc-ext/provision/vpnserver"},
}

Expand Down
67 changes: 67 additions & 0 deletions internal/providers/terraform/ibm/is_share.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package ibm

import (
"github.com/infracost/infracost/internal/resources/ibm"
"github.com/infracost/infracost/internal/schema"
)

func getIsShareRegistryItem() *schema.RegistryItem {
return &schema.RegistryItem{
Name: "ibm_is_share",
RFunc: newIsShare,
ReferenceAttributes: []string{
"source_share",
"source_share.0.size",
}}
}

func newIsShare(d *schema.ResourceData, u *schema.UsageData) *schema.Resource {
region := d.Get("region").String()
size := d.Get("size").Int()
profile := d.Get("profile").String()
iops := d.Get("iops").Int()
zone := d.Get("zone").String()
name := d.Get("name").String()

// if the reference to a source share can
// be resolved, then the share is a replica and the size is specified by the source
sourceShareRef := d.References("source_share")
isReplicaShare := len(sourceShareRef) > 0
if isReplicaShare {
sourceShare := sourceShareRef[0]
size = sourceShare.Get("size").Int()
}

// if an inline replica share can be found, then
// estimate for 2 shares @TODO get the zone info from the replica_zone section in the TF
var replicaZone = ""
var replicaName = ""
if !d.IsEmpty("replica_share") {
replicaZone = d.Get("replica_share.0.zone").String()
replicaName = d.Get("replica_share.0.name").String()
}

r := &ibm.IsShare{
Address: d.Address,
Region: region,
Profile: profile,
IOPS: iops,
Size: size,
Zone: zone,
IsReplica: isReplicaShare,
InlineReplicaZone: replicaZone,
InlineReplicaName: replicaName,
}
r.PopulateUsage(u)

configuration := make(map[string]any)
configuration["region"] = region
configuration["profile"] = profile
configuration["size"] = size
configuration["iops"] = iops
configuration["zone"] = zone
configuration["name"] = name
SetCatalogMetadata(d, d.Type, configuration)

return r.BuildResource()
}
16 changes: 16 additions & 0 deletions internal/providers/terraform/ibm/is_share_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ibm_test

import (
"testing"

"github.com/infracost/infracost/internal/providers/terraform/tftest"
)

func TestIsShare(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip("skipping test in short mode")
}

tftest.GoldenFileResourceTests(t, "is_share_test")
}
4 changes: 4 additions & 0 deletions internal/providers/terraform/ibm/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ var ResourceRegistry []*schema.RegistryItem = []*schema.RegistryItem{
getIsLbRegistryItem(),
getIbmPiVolumeRegistryItem(),
getDatabaseRegistryItem(),
getIsShareRegistryItem(),
getIsVpnServerRegistryItem(),
}

Expand Down Expand Up @@ -109,6 +110,9 @@ var FreeResources = []string{
"ibm_is_security_group",
"ibm_is_security_group_rule",
"ibm_is_security_group_target",
"ibm_is_share_delete_accessor_binding",
"ibm_is_share_mount_target",
"ibm_is_share_replica_operations",
"ibm_is_ssh_key",
"ibm_is_subnet",
"ibm_is_subnet_public_gateway_attachment",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@

Name Monthly Qty Unit Monthly Cost

ibm_is_share.testNFS
├─ 100 GB file storage share for VPC - us-south-2 73,000 GB Hours $15.00
luisarojas marked this conversation as resolved.
Show resolved Hide resolved
└─ 100 Max IOPS (first 5000 IOPS Hours) 5,000 IOPS Hours $0.69
└─ 100 Max IOPS (next 15000 IOPS Hours) 15,000 IOPS Hours $1.03
└─ 100 Max IOPS (next 20000 IOPS Hours) 20,000 IOPS Hours $0.55
└─ 100 Max IOPS (over 40000 IOPS Hours) 33,000 IOPS Hours $0.45

ibm_is_share.testNFS2withInlineReplica
├─ 200 GB file storage share for VPC - us-south-2 146,000 GB Hours $30.00
├─ 100 Max IOPS (first 5000 IOPS Hours) 5,000 IOPS Hours $0.69
├─ 100 Max IOPS (next 15000 IOPS Hours) 15,000 IOPS Hours $1.03
├─ 100 Max IOPS (next 20000 IOPS Hours) 20,000 IOPS Hours $0.55
├─ 100 Max IOPS (over 40000 IOPS Hours) 33,000 IOPS Hours $0.45
├─ 200 GB Replica file storage share for VPC - us-south-3 146,000 GB Hours $30.00
├─ 100 Max IOPS (first 5000 IOPS Hours) 5,000 IOPS Hours $0.69
├─ 100 Max IOPS (next 15000 IOPS Hours) 15,000 IOPS Hours $1.03
├─ 100 Max IOPS (next 20000 IOPS Hours) 20,000 IOPS Hours $0.55
├─ 100 Max IOPS (over 40000 IOPS Hours) 33,000 IOPS Hours $0.45
└─ Transmitted data 1 GB $0.02

ibm_is_share.testReplica
├─ 100 GB Replica file storage share for VPC - us-south-3 Monthly cost depends on usage: $0.0002055 per GB Hours
├─ 100 Max IOPS (first 5000 IOPS Hours) Monthly cost depends on usage: $0.000137 per IOPS Hours
├─ 100 Max IOPS (next 15000 IOPS Hours) Monthly cost depends on usage: $0.0000685 per IOPS Hours
├─ 100 Max IOPS (next 20000 IOPS Hours) Monthly cost depends on usage: $0.0000274 per IOPS Hours
├─ 100 Max IOPS (over 40000 IOPS Hours) Monthly cost depends on usage: $0.0000137 per IOPS Hours
└─ Transmitted data Monthly cost depends on usage: $0.02 per GB

ibm_is_vpc.testVpc
├─ VPC instance 1 Instance $0.00
├─ VPC egress free allowance (first 5GB) Monthly cost depends on usage: $0.00 per GB
└─ VPC egress us-south (first 9995 GB) Monthly cost depends on usage: $0.090915 per GB
└─ VPC egress us-south (next 40000 GB) Monthly cost depends on usage: $0.086735 per GB
└─ VPC egress us-south (next 100000 GB) Monthly cost depends on usage: $0.07315 per GB
└─ VPC egress us-south (over 149995 GB) Monthly cost depends on usage: $0.05225 per GB

OVERALL TOTAL $83.17
──────────────────────────────────
5 cloud resources were detected:
∙ 4 were estimated, all of which include usage-based costs, see https://infracost.io/usage-file
∙ 1 was free:
∙ 1 x ibm_is_share_mount_target
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
terraform {
required_providers {
ibm = {
source = "IBM-Cloud/ibm"
version = "1.63.0"
}
}
}

provider "ibm" {
region = "us-south"
}

resource "ibm_is_vpc" "testVpc" {
name = "test-vpc"
}

resource "ibm_is_share" "testNFS" {
name = "test-share"
size = 100
profile = "dp2"
zone = "us-south-2"
iops = 100
}

resource "ibm_is_share" "testReplica" {
zone = "us-south-3"
source_share = ibm_is_share.testNFS.id
name = "test-replica-share"
profile = "dp2"
replication_cron_spec = "0 */5 * * *"
}

resource "ibm_is_share_mount_target" "testNFSMount" {
share = ibm_is_share.testNFS.id
vpc = ibm_is_vpc.testVpc.id
name = "test-share-target"
}

resource "ibm_is_share" "testNFS2withInlineReplica" {
name = "test-share-2"
size = 200
profile = "dp2"
zone = "us-south-2"

replica_share {
name = "test-replica-share-2"
replication_cron_spec = "0 */5 * * *"
profile = "dp2"
zone = "us-south-3"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: 0.1
resource_usage:
ibm_is_share.testNFS:
is-share_monthly_instance_hours: 730 # Monthly number of instance hours

ibm_is_share.testNFS2withInlineReplica:
is-share_monthly_instance_hours: 730 # Monthly number of instance hours
is-share_monthly_transmitted_gb: 1 # Data transmitted to the instance
Loading
Loading