Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1bf17c23c8 | ||
|
|
668d57cd3b | ||
|
|
dfeb9a9165 | ||
|
|
ab070b73cb | ||
|
|
80a4b70db8 | ||
|
|
28db919ffa |
@@ -25,7 +25,6 @@ Visit https://github.com/rudecs/terraform-provider-decort for full source code p
|
|||||||
package decort
|
package decort
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -34,6 +33,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
// "time"
|
// "time"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@@ -42,30 +42,29 @@ import (
|
|||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
||||||
// "github.com/hashicorp/terraform-plugin-sdk/terraform"
|
// "github.com/hashicorp/terraform-plugin-sdk/terraform"
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// enumerated constants that define authentication modes
|
// enumerated constants that define authentication modes
|
||||||
const (
|
const (
|
||||||
MODE_UNDEF = iota // this is the invalid mode - it should never be seen
|
MODE_UNDEF = iota // this is the invalid mode - it should never be seen
|
||||||
MODE_LEGACY = iota
|
MODE_LEGACY = iota
|
||||||
MODE_OAUTH2 = iota
|
MODE_OAUTH2 = iota
|
||||||
MODE_JWT = iota
|
MODE_JWT = iota
|
||||||
)
|
)
|
||||||
|
|
||||||
type ControllerCfg struct {
|
type ControllerCfg struct {
|
||||||
controller_url string // always required
|
controller_url string // always required
|
||||||
auth_mode_code int // always required
|
auth_mode_code int // always required
|
||||||
auth_mode_txt string // always required, it is a text representation of auth mode
|
auth_mode_txt string // always required, it is a text representation of auth mode
|
||||||
legacy_user string // required for legacy mode
|
legacy_user string // required for legacy mode
|
||||||
legacy_password string // required for legacy mode
|
legacy_password string // required for legacy mode
|
||||||
legacy_sid string // obtained from DECORT controller on successful login in legacy mode
|
legacy_sid string // obtained from DECORT controller on successful login in legacy mode
|
||||||
jwt string // obtained from Outh2 provider on successful login in oauth2 mode, required in jwt mode
|
jwt string // obtained from Outh2 provider on successful login in oauth2 mode, required in jwt mode
|
||||||
app_id string // required for oauth2 mode
|
app_id string // required for oauth2 mode
|
||||||
app_secret string // required for oauth2 mode
|
app_secret string // required for oauth2 mode
|
||||||
oauth2_url string // always required
|
oauth2_url string // always required
|
||||||
decort_username string // assigned to either legacy_user (legacy mode) or Oauth2 user (oauth2 mode) upon successful verification
|
decort_username string // assigned to either legacy_user (legacy mode) or Oauth2 user (oauth2 mode) upon successful verification
|
||||||
cc_client *http.Client // assigned when all initial checks successfully passed
|
cc_client *http.Client // assigned when all initial checks successfully passed
|
||||||
}
|
}
|
||||||
|
|
||||||
func ControllerConfigure(d *schema.ResourceData) (*ControllerCfg, error) {
|
func ControllerConfigure(d *schema.ResourceData) (*ControllerCfg, error) {
|
||||||
@@ -90,7 +89,7 @@ func ControllerConfigure(d *schema.ResourceData) (*ControllerCfg, error) {
|
|||||||
app_id: d.Get("app_id").(string),
|
app_id: d.Get("app_id").(string),
|
||||||
app_secret: d.Get("app_secret").(string),
|
app_secret: d.Get("app_secret").(string),
|
||||||
oauth2_url: d.Get("oauth2_url").(string),
|
oauth2_url: d.Get("oauth2_url").(string),
|
||||||
decort_username: "",
|
decort_username: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
var allow_unverified_ssl bool
|
var allow_unverified_ssl bool
|
||||||
@@ -137,10 +136,10 @@ func ControllerConfigure(d *schema.ResourceData) (*ControllerCfg, error) {
|
|||||||
|
|
||||||
if allow_unverified_ssl {
|
if allow_unverified_ssl {
|
||||||
log.Warn("ControllerConfigure: allow_unverified_ssl is set - will not check certificates!")
|
log.Warn("ControllerConfigure: allow_unverified_ssl is set - will not check certificates!")
|
||||||
transCfg := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true},}
|
transCfg := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
|
||||||
ret_config.cc_client = &http.Client{
|
ret_config.cc_client = &http.Client{
|
||||||
Transport: transCfg,
|
Transport: transCfg,
|
||||||
Timeout: Timeout180s,
|
Timeout: Timeout180s,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ret_config.cc_client = &http.Client{
|
ret_config.cc_client = &http.Client{
|
||||||
@@ -181,7 +180,7 @@ func ControllerConfigure(d *schema.ResourceData) (*ControllerCfg, error) {
|
|||||||
tbuf.WriteString(claims["username"].(string))
|
tbuf.WriteString(claims["username"].(string))
|
||||||
tbuf.WriteString("@")
|
tbuf.WriteString("@")
|
||||||
tbuf.WriteString(claims["iss"].(string))
|
tbuf.WriteString(claims["iss"].(string))
|
||||||
ret_config.decort_username = tbuf.String()
|
ret_config.decort_username = tbuf.String()
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("Failed to extract user and iss fields from JWT token in oauth2 mode.")
|
return nil, fmt.Errorf("Failed to extract user and iss fields from JWT token in oauth2 mode.")
|
||||||
}
|
}
|
||||||
@@ -195,7 +194,7 @@ func ControllerConfigure(d *schema.ResourceData) (*ControllerCfg, error) {
|
|||||||
return ret_config, nil
|
return ret_config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *ControllerCfg) getDecortUsername() (string) {
|
func (config *ControllerCfg) getDecortUsername() string {
|
||||||
return config.decort_username
|
return config.decort_username
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +215,7 @@ func (config *ControllerCfg) getOAuth2JWT() (string, error) {
|
|||||||
params.Add("validity", "3600")
|
params.Add("validity", "3600")
|
||||||
params_str := params.Encode()
|
params_str := params.Encode()
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", config.oauth2_url + "/v1/oauth/access_token", strings.NewReader(params_str))
|
req, err := http.NewRequest("POST", config.oauth2_url+"/v1/oauth/access_token", strings.NewReader(params_str))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -232,14 +231,14 @@ func (config *ControllerCfg) getOAuth2JWT() (string, error) {
|
|||||||
// fmt.Println("response Headers:", resp.Header)
|
// fmt.Println("response Headers:", resp.Header)
|
||||||
// fmt.Println("response Headers:", req.URL)
|
// fmt.Println("response Headers:", req.URL)
|
||||||
return "", fmt.Errorf("getOauth2JWT: unexpected status code %d when obtaining JWT from %q for APP_ID %q, request Body %q",
|
return "", fmt.Errorf("getOauth2JWT: unexpected status code %d when obtaining JWT from %q for APP_ID %q, request Body %q",
|
||||||
resp.StatusCode, req.URL, config.app_id, params_str)
|
resp.StatusCode, req.URL, config.app_id, params_str)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
responseData, err := ioutil.ReadAll(resp.Body)
|
responseData, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// validation successful - store JWT in the corresponding field of the ControllerCfg structure
|
// validation successful - store JWT in the corresponding field of the ControllerCfg structure
|
||||||
config.jwt = strings.TrimSpace(string(responseData))
|
config.jwt = strings.TrimSpace(string(responseData))
|
||||||
@@ -249,10 +248,10 @@ func (config *ControllerCfg) getOAuth2JWT() (string, error) {
|
|||||||
|
|
||||||
func (config *ControllerCfg) validateJWT(jwt string) (bool, error) {
|
func (config *ControllerCfg) validateJWT(jwt string) (bool, error) {
|
||||||
/*
|
/*
|
||||||
Validate JWT against DECORT controller. JWT can be supplied as argument to this method. If empty string supplied as
|
Validate JWT against DECORT controller. JWT can be supplied as argument to this method. If empty string supplied as
|
||||||
argument, JWT will be taken from config attribute.
|
argument, JWT will be taken from config attribute.
|
||||||
DECORT controller URL will always be taken from the config attribute assigned at instantiation.
|
DECORT controller URL will always be taken from the config attribute assigned at instantiation.
|
||||||
Validation is accomplished by attempting API call that lists accounts for the invoking user.
|
Validation is accomplished by attempting API call that lists accounts for the invoking user.
|
||||||
*/
|
*/
|
||||||
if jwt == "" {
|
if jwt == "" {
|
||||||
if config.jwt == "" {
|
if config.jwt == "" {
|
||||||
@@ -265,7 +264,7 @@ func (config *ControllerCfg) validateJWT(jwt string) (bool, error) {
|
|||||||
return false, fmt.Errorf("validateJWT method called, but no OAuth2 URL provided.")
|
return false, fmt.Errorf("validateJWT method called, but no OAuth2 URL provided.")
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", config.controller_url + "/restmachine/cloudapi/accounts/list", nil)
|
req, err := http.NewRequest("POST", config.controller_url+"/restmachine/cloudapi/accounts/list", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@@ -280,7 +279,7 @@ func (config *ControllerCfg) validateJWT(jwt string) (bool, error) {
|
|||||||
}
|
}
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return false, fmt.Errorf("validateJWT: unexpected status code %d when validating JWT against %q.",
|
return false, fmt.Errorf("validateJWT: unexpected status code %d when validating JWT against %q.",
|
||||||
resp.StatusCode, req.URL)
|
resp.StatusCode, req.URL)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
@@ -289,10 +288,10 @@ func (config *ControllerCfg) validateJWT(jwt string) (bool, error) {
|
|||||||
|
|
||||||
func (config *ControllerCfg) validateLegacyUser() (bool, error) {
|
func (config *ControllerCfg) validateLegacyUser() (bool, error) {
|
||||||
/*
|
/*
|
||||||
Validate legacy user by obtaining a session key, which will be used for authenticating subsequent API calls
|
Validate legacy user by obtaining a session key, which will be used for authenticating subsequent API calls
|
||||||
to DECORT controller.
|
to DECORT controller.
|
||||||
If successful, the session key is stored in config.legacy_sid and true is returned. If unsuccessful for any
|
If successful, the session key is stored in config.legacy_sid and true is returned. If unsuccessful for any
|
||||||
reason, the method will return false and error.
|
reason, the method will return false and error.
|
||||||
*/
|
*/
|
||||||
if config.auth_mode_code == MODE_UNDEF {
|
if config.auth_mode_code == MODE_UNDEF {
|
||||||
return false, fmt.Errorf("validateLegacyUser method called for undefined authorization mode.")
|
return false, fmt.Errorf("validateLegacyUser method called for undefined authorization mode.")
|
||||||
@@ -306,7 +305,7 @@ func (config *ControllerCfg) validateLegacyUser() (bool, error) {
|
|||||||
params.Add("password", config.legacy_password)
|
params.Add("password", config.legacy_password)
|
||||||
params_str := params.Encode()
|
params_str := params.Encode()
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", config.controller_url + "/restmachine/cloudapi/users/authenticate", strings.NewReader(params_str))
|
req, err := http.NewRequest("POST", config.controller_url+"/restmachine/cloudapi/users/authenticate", strings.NewReader(params_str))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@@ -320,14 +319,14 @@ func (config *ControllerCfg) validateLegacyUser() (bool, error) {
|
|||||||
}
|
}
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return false, fmt.Errorf("validateLegacyUser: unexpected status code %d when validating legacy user %q against %q.",
|
return false, fmt.Errorf("validateLegacyUser: unexpected status code %d when validating legacy user %q against %q.",
|
||||||
resp.StatusCode, config.legacy_user, config.controller_url)
|
resp.StatusCode, config.legacy_user, config.controller_url)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
responseData, err := ioutil.ReadAll(resp.Body)
|
responseData, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// validation successful - keep session ID for future use
|
// validation successful - keep session ID for future use
|
||||||
config.legacy_sid = string(responseData)
|
config.legacy_sid = string(responseData)
|
||||||
@@ -367,12 +366,13 @@ func (config *ControllerCfg) decortAPICall(method string, api_name string, url_v
|
|||||||
}
|
}
|
||||||
params_str := url_values.Encode()
|
params_str := url_values.Encode()
|
||||||
|
|
||||||
req, err := http.NewRequest(method, config.controller_url + api_name, strings.NewReader(params_str))
|
req, err := http.NewRequest(method, config.controller_url+api_name, strings.NewReader(params_str))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
req.Header.Set("Content-Length", strconv.Itoa(len(params_str)))
|
req.Header.Set("Content-Length", strconv.Itoa(len(params_str)))
|
||||||
|
req.Header.Set("Accept", "application/json")
|
||||||
|
|
||||||
if config.auth_mode_code == MODE_OAUTH2 || config.auth_mode_code == MODE_JWT {
|
if config.auth_mode_code == MODE_OAUTH2 || config.auth_mode_code == MODE_JWT {
|
||||||
req.Header.Set("Authorization", fmt.Sprintf("bearer %s", config.jwt))
|
req.Header.Set("Authorization", fmt.Sprintf("bearer %s", config.jwt))
|
||||||
@@ -384,25 +384,23 @@ func (config *ControllerCfg) decortAPICall(method string, api_name string, url_v
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode == http.StatusOK {
|
if resp.StatusCode == http.StatusOK {
|
||||||
tmp_body, err := ioutil.ReadAll(resp.Body)
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
json_resp := Jo2JSON(string(tmp_body))
|
log.Debugf("decortAPICall: %s %s\n %s", method, api_name, body)
|
||||||
log.Debugf("decortAPICall: %s %s\n %s", method, api_name, json_resp)
|
return string(body), nil
|
||||||
return json_resp, nil
|
|
||||||
} else {
|
} else {
|
||||||
return "", fmt.Errorf("decortAPICall: unexpected status code %d when calling API %q with request Body %q",
|
return "", fmt.Errorf("decortAPICall: unexpected status code %d when calling API %q with request Body %q",
|
||||||
resp.StatusCode, req.URL, params_str)
|
resp.StatusCode, req.URL, params_str)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if resp.StatusCode == StatusServiceUnavailable {
|
if resp.StatusCode == StatusServiceUnavailable {
|
||||||
return nil, fmt.Errorf("decortAPICall method called for incompatible authorization mode %q.", config.auth_mode_txt)
|
return nil, fmt.Errorf("decortAPICall method called for incompatible authorization mode %q.", config.auth_mode_txt)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ func flattenCompute(d *schema.ResourceData, compFacts string) error {
|
|||||||
d.Set("rg_name", model.RgName)
|
d.Set("rg_name", model.RgName)
|
||||||
d.Set("account_id", model.AccountID)
|
d.Set("account_id", model.AccountID)
|
||||||
d.Set("account_name", model.AccountName)
|
d.Set("account_name", model.AccountName)
|
||||||
d.Set("arch", model.Arch)
|
d.Set("driver", model.Driver)
|
||||||
d.Set("cpu", model.Cpu)
|
d.Set("cpu", model.Cpu)
|
||||||
d.Set("ram", model.Ram)
|
d.Set("ram", model.Ram)
|
||||||
// d.Set("boot_disk_size", model.BootDiskSize) - bootdiskSize key in API compute/get is always zero, so we set boot_disk_size in another way
|
// d.Set("boot_disk_size", model.BootDiskSize) - bootdiskSize key in API compute/get is always zero, so we set boot_disk_size in another way
|
||||||
@@ -367,7 +367,7 @@ func dataSourceCompute() *schema.Resource {
|
|||||||
Description: "Name of the account this compute instance belongs to.",
|
Description: "Name of the account this compute instance belongs to.",
|
||||||
},
|
},
|
||||||
|
|
||||||
"arch": {
|
"driver": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "Hardware architecture of this compute instance.",
|
Description: "Hardware architecture of this compute instance.",
|
||||||
|
|||||||
@@ -356,6 +356,7 @@ type ComputeGetResp struct {
|
|||||||
Cpu int `json:"cpus"`
|
Cpu int `json:"cpus"`
|
||||||
Desc string `json:"desc"`
|
Desc string `json:"desc"`
|
||||||
Disks []DiskRecord `json:"disks"`
|
Disks []DiskRecord `json:"disks"`
|
||||||
|
Driver string `json:"driver"`
|
||||||
GridID int `json:"gid"`
|
GridID int `json:"gid"`
|
||||||
ID uint `json:"id"`
|
ID uint `json:"id"`
|
||||||
ImageID int `json:"imageId"`
|
ImageID int `json:"imageId"`
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ import (
|
|||||||
func parseOsUsers(logins []OsUserRecord) []interface{} {
|
func parseOsUsers(logins []OsUserRecord) []interface{} {
|
||||||
var result = make([]interface{}, len(logins))
|
var result = make([]interface{}, len(logins))
|
||||||
|
|
||||||
elem := make(map[string]interface{})
|
|
||||||
|
|
||||||
for index, value := range logins {
|
for index, value := range logins {
|
||||||
|
elem := make(map[string]interface{})
|
||||||
|
|
||||||
elem["guid"] = value.Guid
|
elem["guid"] = value.Guid
|
||||||
elem["login"] = value.Login
|
elem["login"] = value.Login
|
||||||
elem["password"] = value.Password
|
elem["password"] = value.Password
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ func Provider() *schema.Provider {
|
|||||||
"decort_kvmvm": resourceCompute(),
|
"decort_kvmvm": resourceCompute(),
|
||||||
"decort_disk": resourceDisk(),
|
"decort_disk": resourceDisk(),
|
||||||
"decort_vins": resourceVins(),
|
"decort_vins": resourceVins(),
|
||||||
// "decort_pfw": resourcePfw(),
|
"decort_pfw": resourcePfw(),
|
||||||
},
|
},
|
||||||
|
|
||||||
DataSourcesMap: map[string]*schema.Resource{
|
DataSourcesMap: map[string]*schema.Resource{
|
||||||
|
|||||||
202
decort/resource_pfw.go
Normal file
202
decort/resource_pfw.go
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2019-2021 Digital Energy Cloud Solutions LLC. All Rights Reserved.
|
||||||
|
Author: Petr Krutov, <petr.krutov@digitalenergy.online>
|
||||||
|
|
||||||
|
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 (
|
||||||
|
"fmt"
|
||||||
|
"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(fmt.Sprintf("%d-%s", d.Get("compute_id").(int), 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,
|
||||||
|
},
|
||||||
|
|
||||||
|
Timeouts: &schema.ResourceTimeout{
|
||||||
|
Create: &Timeout60s,
|
||||||
|
Read: &Timeout30s,
|
||||||
|
Update: &Timeout60s,
|
||||||
|
Delete: &Timeout60s,
|
||||||
|
Default: &Timeout60s,
|
||||||
|
},
|
||||||
|
|
||||||
|
Schema: resourcePfwSchemaMake(),
|
||||||
|
}
|
||||||
|
}
|
||||||
44
decort/utility_pfw.go
Normal file
44
decort/utility_pfw.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package decort
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"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 := strings.Split(d.Id(), "-")[1]
|
||||||
|
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
|
||||||
|
}
|
||||||
@@ -29,12 +29,12 @@ description: |-
|
|||||||
|
|
||||||
- **account_id** (Number) ID of the account this compute instance belongs to.
|
- **account_id** (Number) ID of the account this compute instance belongs to.
|
||||||
- **account_name** (String) Name of the account this compute instance belongs to.
|
- **account_name** (String) Name of the account this compute instance belongs to.
|
||||||
- **arch** (String) Hardware architecture of this compute instance.
|
|
||||||
- **boot_disk_id** (Number) This compute instance boot disk ID.
|
- **boot_disk_id** (Number) This compute instance boot disk ID.
|
||||||
- **boot_disk_size** (Number) This compute instance boot disk size in GB.
|
- **boot_disk_size** (Number) This compute instance boot disk size in GB.
|
||||||
- **cloud_init** (String) Placeholder for cloud_init parameters.
|
- **cloud_init** (String) Placeholder for cloud_init parameters.
|
||||||
- **cpu** (Number) Number of CPUs allocated for this compute instance.
|
- **cpu** (Number) Number of CPUs allocated for this compute instance.
|
||||||
- **description** (String) User-defined text description of this compute instance.
|
- **description** (String) User-defined text description of this compute instance.
|
||||||
|
- **driver** (String) Hardware architecture of this compute instance.
|
||||||
- **extra_disks** (Set of Number) IDs of the extra disk(s) attached to this compute.
|
- **extra_disks** (Set of Number) IDs of the extra disk(s) attached to this compute.
|
||||||
- **image_id** (Number) ID of the OS image this compute instance is based on.
|
- **image_id** (Number) ID of the OS image this compute instance is based on.
|
||||||
- **image_name** (String) Name of the OS image this compute instance is based on.
|
- **image_name** (String) Name of the OS image this compute instance is based on.
|
||||||
|
|||||||
46
docs/resources/pfw.md
Normal file
46
docs/resources/pfw.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||||
|
page_title: "decort_pfw Resource - terraform-provider-decort"
|
||||||
|
subcategory: ""
|
||||||
|
description: |-
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# decort_pfw (Resource)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- schema generated by tfplugindocs -->
|
||||||
|
## Schema
|
||||||
|
|
||||||
|
### Required
|
||||||
|
|
||||||
|
- **compute_id** (Number) ID of compute instance.
|
||||||
|
- **local_base_port** (Number) Internal base port number.
|
||||||
|
- **proto** (String) Network protocol, either 'tcp' or 'udp'.
|
||||||
|
- **public_port_start** (Number) External start port number for the rule.
|
||||||
|
|
||||||
|
### Optional
|
||||||
|
|
||||||
|
- **id** (String) The ID of this resource.
|
||||||
|
- **public_port_end** (Number) End port number (inclusive) for the ranged rule.
|
||||||
|
- **timeouts** (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))
|
||||||
|
|
||||||
|
### Read-Only
|
||||||
|
|
||||||
|
- **local_ip** (String) IP address of compute instance.
|
||||||
|
|
||||||
|
<a id="nestedblock--timeouts"></a>
|
||||||
|
### Nested Schema for `timeouts`
|
||||||
|
|
||||||
|
Optional:
|
||||||
|
|
||||||
|
- **create** (String)
|
||||||
|
- **default** (String)
|
||||||
|
- **delete** (String)
|
||||||
|
- **read** (String)
|
||||||
|
- **update** (String)
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user