Skip to content

Commit

Permalink
Add CCI Resource (#294)
Browse files Browse the repository at this point in the history
  • Loading branch information
niuzhenguo authored Apr 3, 2020
1 parent 3004ec9 commit 8e2d084
Show file tree
Hide file tree
Showing 11 changed files with 588 additions and 0 deletions.
7 changes: 7 additions & 0 deletions huaweicloud/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,13 @@ func (c *Config) cceV3Client(region string) (*golangsdk.ServiceClient, error) {
})
}

func (c *Config) cciV1Client(region string) (*golangsdk.ServiceClient, error) {
return huaweisdk.CCIV1(c.HwClient, golangsdk.EndpointOpts{
Region: c.determineRegion(region),
Availability: c.getHwEndpointType(),
})
}

func (c *Config) objectStorageV1Client(region string) (*golangsdk.ServiceClient, error) {
// If Swift Authentication is being used, return a swauth client.
if c.Swauth {
Expand Down
1 change: 1 addition & 0 deletions huaweicloud/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ func Provider() terraform.ResourceProvider {
"huaweicloud_vpc_subnet_v1": resourceVpcSubnetV1(),
"huaweicloud_cce_cluster_v3": resourceCCEClusterV3(),
"huaweicloud_cce_node_v3": resourceCCENodeV3(),
"huaweicloud_cci_network_v1": resourceCCINetworkV1(),
"huaweicloud_rts_software_config_v1": resourceSoftwareConfigV1(),
"huaweicloud_ces_alarmrule": resourceAlarmRule(),
"huaweicloud_as_configuration_v1": resourceASConfiguration(),
Expand Down
10 changes: 10 additions & 0 deletions huaweicloud/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ var (
OS_SRC_SECRET_KEY = os.Getenv("OS_SRC_SECRET_KEY")
OS_VPC_ID = os.Getenv("OS_VPC_ID")
OS_TENANT_ID = os.Getenv("OS_TENANT_ID")
OS_DOMAIN_ID = os.Getenv("OS_DOMAIN_ID")
OS_SSH_KEY = os.Getenv("OS_SSH_KEY")
OS_DWS_ENVIRONMENT = os.Getenv("OS_DWS_ENVIRONMENT")
OS_MRS_ENVIRONMENT = os.Getenv("OS_MRS_ENVIRONMENT")
OS_DMS_ENVIRONMENT = os.Getenv("OS_DMS_ENVIRONMENT")
OS_NAT_ENVIRONMENT = os.Getenv("OS_NAT_ENVIRONMENT")
OS_KMS_ENVIRONMENT = os.Getenv("OS_KMS_ENVIRONMENT")
OS_CCI_ENVIRONMENT = os.Getenv("OS_CCI_ENVIRONMENT")
OS_CDN_DOMAIN_NAME = os.Getenv("OS_CDN_DOMAIN_NAME")
)

Expand Down Expand Up @@ -207,6 +209,14 @@ func testAccPreCheckCDN(t *testing.T) {
}
}

func testAccPreCheckCCI(t *testing.T) {
testAccPreCheckRequiredEnvVars(t)

if OS_CCI_ENVIRONMENT == "" {
t.Skip("This environment does not support CCI tests")
}
}

func TestProvider(t *testing.T) {
if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
t.Fatalf("err: %s", err)
Expand Down
230 changes: 230 additions & 0 deletions huaweicloud/resource_huaweicloud_cci_network_v1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
package huaweicloud

import (
"fmt"
"log"
"time"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/huaweicloud/golangsdk"
"github.com/huaweicloud/golangsdk/openstack/cci/v1/networks"
)

func resourceCCINetworkV1() *schema.Resource {
return &schema.Resource{
Create: resourceCCINetworkV1Create,
Read: resourceCCINetworkV1Read,
Delete: resourceCCINetworkV1Delete,

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(10 * time.Minute),
Delete: schema.DefaultTimeout(10 * time.Minute),
},

//request and response parameters
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"namespace": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"security_group": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"project_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"domain_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"vpc_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"network_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"subnet_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"available_zone": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"cidr": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
},
}
}

func resourceNetworkAnnotationsV1(d *schema.ResourceData) map[string]string {
m := map[string]string{
"network.alpha.kubernetes.io/default-security-group": d.Get("security_group").(string),
"network.alpha.kubernetes.io/domain_id": d.Get("domain_id").(string),
"network.alpha.kubernetes.io/project_id": d.Get("project_id").(string),
}
return m
}

func resourceCCINetworkV1Create(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
cciClient, err := config.cciV1Client(GetRegion(d, config))

if err != nil {
return fmt.Errorf("Unable to create HuaweiCloud CCI client : %s", err)
}

createOpts := networks.CreateOpts{
Kind: "Network",
ApiVersion: "networking.cci.io/v1beta1",
Metadata: networks.CreateMetaData{
Name: d.Get("name").(string),
Annotations: resourceNetworkAnnotationsV1(d),
},
Spec: networks.Spec{
AttachedVPC: d.Get("vpc_id").(string),
NetworkType: "underlay_neutron",
NetworkID: d.Get("network_id").(string),
SubnetID: d.Get("subnet_id").(string),
AvailableZone: d.Get("available_zone").(string),
Cidr: d.Get("cidr").(string),
},
}

ns := d.Get("namespace").(string)
create, err := networks.Create(cciClient, ns, createOpts).Extract()

if err != nil {
return fmt.Errorf("Error creating HuaweiCloud CCI Network: %s", err)
}

log.Printf("[DEBUG] Waiting for HuaweiCloud CCI network (%s) to become available", create.Metadata.Name)

stateConf := &resource.StateChangeConf{
Pending: []string{"Initializing", "Pending"},
Target: []string{"Active"},
Refresh: waitForCCINetworkActive(cciClient, ns, create.Metadata.Name),
Timeout: d.Timeout(schema.TimeoutCreate),
Delay: 5 * time.Second,
MinTimeout: 3 * time.Second,
}

_, err = stateConf.WaitForState()
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud CCI network: %s", err)
}
d.SetId(create.Metadata.Name)

return resourceCCINetworkV1Read(d, meta)
}

func resourceCCINetworkV1Read(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
cciClient, err := config.cciV1Client(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud CCI client: %s", err)
}

ns := d.Get("namespace").(string)
n, err := networks.Get(cciClient, ns, d.Id()).Extract()
if err != nil {
if _, ok := err.(golangsdk.ErrDefault404); ok {
d.SetId("")
return nil
}

return fmt.Errorf("Error retrieving HuaweiCloud CCI: %s", err)
}

d.Set("name", n.Metadata.Name)
d.Set("vpc_id", n.Spec.AttachedVPC)
d.Set("network_id", n.Spec.NetworkID)
d.Set("subnet_id", n.Spec.SubnetID)
d.Set("available_zone", n.Spec.AvailableZone)
d.Set("cidr", n.Spec.Cidr)

return nil
}

func resourceCCINetworkV1Delete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
cciClient, err := config.cciV1Client(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud CCI Client: %s", err)
}

ns := d.Get("namespace").(string)
err = networks.Delete(cciClient, ns, d.Id()).ExtractErr()
if err != nil {
return fmt.Errorf("Error deleting HuaweiCloud CCI Network: %s", err)
}
stateConf := &resource.StateChangeConf{
Pending: []string{"Terminating", "Active"},
Target: []string{"Deleted"},
Refresh: waitForCCINetworkDelete(cciClient, ns, d.Id()),
Timeout: d.Timeout(schema.TimeoutDelete),
Delay: 5 * time.Second,
MinTimeout: 3 * time.Second,
}

_, err = stateConf.WaitForState()

if err != nil {
return fmt.Errorf("Error deleting HuaweiCloud CCI network: %s", err)
}

d.SetId("")
return nil
}

func waitForCCINetworkActive(cciClient *golangsdk.ServiceClient, ns, name string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
n, err := networks.Get(cciClient, ns, name).Extract()
if err != nil {
return nil, "", err
}

return n, n.Status.State, nil
}
}

func waitForCCINetworkDelete(cciClient *golangsdk.ServiceClient, ns, name string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
log.Printf("[DEBUG] Attempting to delete HuaweiCloud CCI network %s.\n", name)

r, err := networks.Get(cciClient, ns, name).Extract()
if err != nil {
if _, ok := err.(golangsdk.ErrDefault404); ok {
log.Printf("[DEBUG] Successfully deleted HuaweiCloud CCI network %s", name)
return r, "Deleted", nil
}
}
if r.Status.State == "Terminating" {
return r, "Terminating", nil
}
log.Printf("[DEBUG] HuaweiCloud CCI network %s still available.\n", name)
return r, "Active", nil
}
}
98 changes: 98 additions & 0 deletions huaweicloud/resource_huaweicloud_cci_network_v1_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package huaweicloud

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"

"github.com/huaweicloud/golangsdk/openstack/cci/v1/networks"
)

func TestAccCCINetworkV1_basic(t *testing.T) {
var network networks.Network

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheckCCI(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckCCINetworkV1Destroy,
Steps: []resource.TestStep{
{
Config: testAccCCINetworkV1_basic,
Check: resource.ComposeTestCheckFunc(
testAccCheckCCINetworkV1Exists("huaweicloud_cci_network_v1.net_1", &network),
resource.TestCheckResourceAttr(
"huaweicloud_cci_network_v1.net_1", "name", "cci-net"),
),
},
},
})
}

func testAccCheckCCINetworkV1Destroy(s *terraform.State) error {
config := testAccProvider.Meta().(*Config)
cciClient, err := config.cciV1Client(OS_REGION_NAME)
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud CCI client: %s", err)
}

for _, rs := range s.RootModule().Resources {
if rs.Type != "huaweicloud_cci_network_v1" {
continue
}

_, err := networks.Get(cciClient, "test_ns", rs.Primary.ID).Extract()
if err == nil {
return fmt.Errorf("Network still exists")
}
}

return nil
}

func testAccCheckCCINetworkV1Exists(n string, network *networks.Network) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}

if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}

config := testAccProvider.Meta().(*Config)
cciClient, err := config.cciV1Client(OS_REGION_NAME)
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud CCI client: %s", err)
}

found, err := networks.Get(cciClient, "test_ns", rs.Primary.ID).Extract()
if err != nil {
return err
}

if found.Metadata.Name != rs.Primary.ID {
return fmt.Errorf("Network not found")
}

*network = *found

return nil
}
}

var testAccCCINetworkV1_basic = fmt.Sprintf(`
resource "huaweicloud_cci_network_v1" "net_1" {
name = "cci-net"
namespace = "test-ns"
security_group = "3b5ceb06-3b8d-43ee-866a-dc0443b85de8"
project_id = "%s"
domain_id = "%s"
vpc_id = "%s"
network_id = "%s"
subnet_id = "%s"
available_zone = "cn-north-1a"
cidr = "192.168.0.0/24"
}`, OS_TENANT_ID, OS_DOMAIN_ID, OS_VPC_ID, OS_NETWORK_ID, OS_SUBNET_ID)
Loading

0 comments on commit 8e2d084

Please sign in to comment.