diff --git a/decort/provider.go b/decort/provider.go index 0dc8876..2a12f08 100644 --- a/decort/provider.go +++ b/decort/provider.go @@ -103,7 +103,7 @@ func Provider() *schema.Provider { "decort_kvmvm": resourceCompute(), "decort_disk": resourceDisk(), "decort_vins": resourceVins(), - // "decort_pfw": resourcePfw(), + "decort_pfw": resourcePfw(), }, DataSourcesMap: map[string]*schema.Resource{ diff --git a/decort/resource_pfw.go b/decort/resource_pfw.go new file mode 100644 index 0000000..946cf5f --- /dev/null +++ b/decort/resource_pfw.go @@ -0,0 +1,195 @@ +/* +Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved. +Author: Petr Krutov, + +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. +*/ + +/* +This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration +Technology platfom. + +Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates. +*/ + +package decort + +import ( + "net/url" + "strconv" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + log "github.com/sirupsen/logrus" +) + +func resourcePfwCreate(d *schema.ResourceData, m interface{}) error { + log.Debugf("resourcePfwCreate: called for compute %d", d.Get("compute_id").(int)) + + controller := m.(*ControllerCfg) + urlValues := &url.Values{} + urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int))) + urlValues.Add("publicPortStart", strconv.Itoa(d.Get("public_port_start").(int))) + urlValues.Add("localBasePort", strconv.Itoa(d.Get("local_base_port").(int))) + urlValues.Add("proto", d.Get("proto").(string)) + + if portEnd, ok := d.GetOk("public_port_end"); ok { + urlValues.Add("publicPortEnd", strconv.Itoa(portEnd.(int))) + } + + pfwId, err := controller.decortAPICall("POST", ComputePfwAddAPI, urlValues) + if err != nil { + return err + } + + d.SetId(pfwId) + + pfw, err := utilityPfwCheckPresence(d, m) + if err != nil { + return err + } + + d.Set("local_ip", pfw.LocalIP) + if _, ok := d.GetOk("public_port_end"); !ok { + d.Set("public_port_end", pfw.PublicPortEnd) + } + + return nil +} + +func resourcePfwRead(d *schema.ResourceData, m interface{}) error { + log.Debugf("resourcePfwRead: called for compute %d, rule %s", d.Get("compute_id").(int), d.Id()) + + pfw, err := utilityPfwCheckPresence(d, m) + if pfw == nil { + if err != nil { + return err + } + return nil + } + + d.Set("compute_id", pfw.ComputeID) + d.Set("public_port_start", pfw.PublicPortStart) + d.Set("public_port_end", pfw.PublicPortEnd) + d.Set("local_ip", pfw.LocalIP) + d.Set("local_base_port", pfw.LocalPort) + d.Set("proto", pfw.Protocol) + + return nil +} + +func resourcePfwDelete(d *schema.ResourceData, m interface{}) error { + log.Debugf("resourcePfwDelete: called for compute %d, rule %s", d.Get("compute_id").(int), d.Id()) + + pfw, err := utilityPfwCheckPresence(d, m) + if pfw == nil { + if err != nil { + return err + } + return nil + } + + controller := m.(*ControllerCfg) + urlValues := &url.Values{} + urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int))) + urlValues.Add("ruleId", d.Id()) + + _, err = controller.decortAPICall("POST", ComputePfwDelAPI, urlValues) + if err != nil { + return err + } + + return nil +} + +func resourcePfwExists(d *schema.ResourceData, m interface{}) (bool, error) { + log.Debugf("resourcePfwExists: called for compute %d, rule %s", d.Get("compute_id").(int), d.Id()) + + pfw, err := utilityPfwCheckPresence(d, m) + if pfw == nil { + if err != nil { + return false, err + } + return false, nil + } + + return true, nil +} + +func resourcePfwSchemaMake() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "compute_id": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: "ID of compute instance.", + }, + + "public_port_start": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(1, 65535), + Description: "External start port number for the rule.", + }, + + "public_port_end": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(1, 65535), + Description: "End port number (inclusive) for the ranged rule.", + }, + + "local_ip": { + Type: schema.TypeString, + Computed: true, + Description: "IP address of compute instance.", + }, + + "local_base_port": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(1, 65535), + Description: "Internal base port number.", + }, + + "proto": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"tcp", "udp"}, false), + Description: "Network protocol, either 'tcp' or 'udp'.", + }, + } +} + +func resourcePfw() *schema.Resource { + return &schema.Resource{ + SchemaVersion: 1, + + Create: resourcePfwCreate, + Read: resourcePfwRead, + Delete: resourcePfwDelete, + Exists: resourcePfwExists, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + //TODO timeouts + + Schema: resourcePfwSchemaMake(), + } +} diff --git a/decort/utility_pfw.go b/decort/utility_pfw.go new file mode 100644 index 0000000..65f4e11 --- /dev/null +++ b/decort/utility_pfw.go @@ -0,0 +1,43 @@ +package decort + +import ( + "encoding/json" + "net/url" + "strconv" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func utilityPfwCheckPresence(d *schema.ResourceData, m interface{}) (*PfwRecord, error) { + controller := m.(*ControllerCfg) + urlValues := &url.Values{} + + urlValues.Add("computeId", strconv.Itoa(d.Get("compute_id").(int))) + resp, err := controller.decortAPICall("POST", ComputePfwListAPI, urlValues) + if err != nil { + return nil, err + } + + if resp == "" { + return nil, nil + } + + idS := d.Id() + id, err := strconv.Atoi(idS) + if err != nil { + return nil, err + } + + var pfws []PfwRecord + if err := json.Unmarshal([]byte(resp), &pfws); err != nil { + return nil, err + } + + for _, pfw := range pfws { + if pfw.ID == id { + return &pfw, nil + } + } + + return nil, nil +}