Add locations

This commit is contained in:
stSolo
2022-07-07 18:46:39 +03:00
parent e4be812c68
commit 48cada2cf3
77 changed files with 520 additions and 44 deletions

View File

@@ -25,6 +25,8 @@ import (
"github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/bservice"
"github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/disks"
"github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/extnet"
"github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/kvmvm"
"github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/locations"
"github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/rg"
"github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/snapshot"
"github.com/rudecs/terraform-provider-decort/internal/service/cloudapi/vgpu"
@@ -37,9 +39,9 @@ import (
func NewDataSourcesMap() map[string]*schema.Resource {
return map[string]*schema.Resource{
"decort_account": account.DataSourceAccount(),
"decort_resgroup": rg.DataSourceResgroup(),
// "decort_kvmvm": dataSourceCompute(),
"decort_account": account.DataSourceAccount(),
"decort_resgroup": rg.DataSourceResgroup(),
"decort_kvmvm": kvmvm.DataSourceCompute(),
"decort_image": image.DataSourceImage(),
"decort_disk": disks.DataSourceDisk(),
"decort_vins": vins.DataSourceVins(),
@@ -81,6 +83,8 @@ func NewDataSourcesMap() map[string]*schema.Resource {
"decort_extnet": extnet.DataSourceExtnet(),
"decort_extnet_default": extnet.DataSourceExtnetDefault(),
"decort_vins_list": vins.DataSourceVinsList(),
"decort_locations_list": locations.DataSourceLocationsList(),
"decort_location_url": locations.DataSourceLocationUrl(),
// "decort_pfw": dataSourcePfw(),
}

View File

@@ -21,7 +21,6 @@ package provider
import (
"fmt"
"strings"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
@@ -29,6 +28,7 @@ import (
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/rudecs/terraform-provider-decort/internal/location"
"github.com/rudecs/terraform-provider-decort/internal/statefuncs"
)
func Provider() *schema.Provider {
@@ -37,7 +37,7 @@ func Provider() *schema.Provider {
"authenticator": {
Type: schema.TypeString,
Required: true,
StateFunc: StateFuncToLower,
StateFunc: statefuncs.StateFuncToLower,
ValidateFunc: validation.StringInSlice([]string{"oauth2", "legacy", "jwt"}, true), // ignore case while validating
Description: "Authentication mode to use when connecting to DECORT cloud API. Should be one of 'oauth2', 'legacy' or 'jwt'.",
},
@@ -45,7 +45,7 @@ func Provider() *schema.Provider {
"oauth2_url": {
Type: schema.TypeString,
Optional: true,
StateFunc: StateFuncToLower,
StateFunc: statefuncs.StateFuncToLower,
DefaultFunc: schema.EnvDefaultFunc("DECORT_OAUTH2_URL", nil),
Description: "OAuth2 application URL in 'oauth2' authentication mode.",
},
@@ -54,7 +54,7 @@ func Provider() *schema.Provider {
Type: schema.TypeString,
Required: true,
ForceNew: true,
StateFunc: StateFuncToLower,
StateFunc: statefuncs.StateFuncToLower,
Description: "URL of DECORT Cloud controller to use. API calls will be directed to this URL.",
},
@@ -109,14 +109,6 @@ func Provider() *schema.Provider {
}
}
func StateFuncToLower(argval interface{}) string {
return strings.ToLower(argval.(string))
}
func StateFuncToUpper(argval interface{}) string {
return strings.ToUpper(argval.(string))
}
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
decsController, err := controller.ControllerConfigure(d)
if err != nil {

View File

@@ -168,13 +168,11 @@ func dataSourceAccountSchemaMake() map[string]*schema.Schema {
"resources": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"current": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cpu": {
@@ -207,7 +205,6 @@ func dataSourceAccountSchemaMake() map[string]*schema.Schema {
"reserved": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cpu": {
@@ -330,7 +327,6 @@ func dataSourceAccountSchemaMake() map[string]*schema.Schema {
"resource_limits": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cu_c": {
@@ -390,7 +386,6 @@ func dataSourceAccountSchemaMake() map[string]*schema.Schema {
"computes": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"started": {
@@ -407,7 +402,6 @@ func dataSourceAccountSchemaMake() map[string]*schema.Schema {
"machines": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"halted": {

View File

@@ -113,7 +113,6 @@ func dataSourceAccountRGListSchemaMake() map[string]*schema.Schema {
Schema: map[string]*schema.Schema{
"computes": {
Type: schema.TypeList,
MaxItems: 1,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
@@ -131,13 +130,11 @@ func dataSourceAccountRGListSchemaMake() map[string]*schema.Schema {
"resources": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"consumed": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cpu": {
@@ -171,7 +168,6 @@ func dataSourceAccountRGListSchemaMake() map[string]*schema.Schema {
"limits": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cpu": {
@@ -204,7 +200,6 @@ func dataSourceAccountRGListSchemaMake() map[string]*schema.Schema {
"reserved": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cpu": {

View File

@@ -559,13 +559,11 @@ func resourceAccountSchemaMake() map[string]*schema.Schema {
"resources": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"current": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cpu": {
@@ -598,7 +596,6 @@ func resourceAccountSchemaMake() map[string]*schema.Schema {
"reserved": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cpu": {
@@ -740,7 +737,6 @@ func resourceAccountSchemaMake() map[string]*schema.Schema {
"computes": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"started": {
@@ -757,7 +753,6 @@ func resourceAccountSchemaMake() map[string]*schema.Schema {
"machines": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"halted": {

View File

@@ -156,7 +156,6 @@ func dataSourceExtnetSchemaMake() map[string]*schema.Schema {
},
"default_qos": {
Type: schema.TypeList,
MaxItems: 1,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
@@ -302,7 +301,6 @@ func dataSourceExtnetSchemaMake() map[string]*schema.Schema {
},
"vnfs": {
Type: schema.TypeList,
MaxItems: 1,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{

View File

@@ -207,7 +207,7 @@ func dataSourceComputeRead(ctx context.Context, d *schema.ResourceData, m interf
return diag.FromErr(flattenCompute(d, compFacts))
}
func dataSourceCompute() *schema.Resource {
func DataSourceCompute() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
@@ -302,7 +302,6 @@ func dataSourceCompute() *schema.Resource {
"extra_disks": {
Type: schema.TypeSet,
Computed: true,
MaxItems: constants.MaxExtraDisksPerCompute,
Elem: &schema.Schema{
Type: schema.TypeInt,
},

View File

@@ -35,7 +35,7 @@ import (
"bytes"
"hash/fnv"
"github.com/rudecs/terraform-provider-decort/internal/provider"
"github.com/rudecs/terraform-provider-decort/internal/statefuncs"
log "github.com/sirupsen/logrus"
"sort"
@@ -125,7 +125,7 @@ func networkSubresourceSchemaMake() map[string]*schema.Schema {
"net_type": {
Type: schema.TypeString,
Required: true,
StateFunc: provider.StateFuncToUpper,
StateFunc: statefuncs.StateFuncToUpper,
ValidateFunc: validation.StringInSlice([]string{"EXTNET", "VINS"}, false), // observe case while validating
Description: "Type of the network for this connection, either EXTNET or VINS.",
},

View File

@@ -40,7 +40,7 @@ import (
"github.com/rudecs/terraform-provider-decort/internal/constants"
"github.com/rudecs/terraform-provider-decort/internal/controller"
"github.com/rudecs/terraform-provider-decort/internal/provider"
"github.com/rudecs/terraform-provider-decort/internal/statefuncs"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
@@ -394,7 +394,7 @@ func ResourceCompute() *schema.Resource {
Type: schema.TypeString,
Required: true,
ForceNew: true,
StateFunc: provider.StateFuncToUpper,
StateFunc: statefuncs.StateFuncToUpper,
ValidateFunc: validation.StringInSlice([]string{"KVM_X86", "KVM_PPC"}, false), // observe case while validating
Description: "Hardware architecture of this compute instance.",
},

View File

@@ -0,0 +1,23 @@
package locations
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@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.
*/
const locationsListAPI = "/restmachine/cloudapi/locations/list"
const locationURLAPI = "/restmachine/cloudapi/locations/getUrl"

View File

@@ -0,0 +1,155 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package locations
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
"github.com/rudecs/terraform-provider-decort/internal/flattens"
)
func flattenLocationsList(ll LocationsList) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, l := range ll {
temp := map[string]interface{}{
"ckey": l.CKey,
"meta": flattens.FlattenMeta(l.Meta),
"flag": l.Flag,
"gid": l.GridID,
"guid": l.Guid,
"id": l.Id,
"location_code": l.LocationCode,
"name": l.Name,
}
res = append(res, temp)
}
return res
}
func dataSourceLocationsListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
locations, err := utilityLocationsListCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenLocationsList(locations))
return nil
}
func dataSourceLocationsListSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"page": {
Type: schema.TypeInt,
Optional: true,
Description: "page number",
},
"size": {
Type: schema.TypeInt,
Optional: true,
Description: "page size",
},
"items": {
Type: schema.TypeList,
Computed: true,
Description: "Locations list",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"ckey": {
Type: schema.TypeString,
Computed: true,
},
"meta": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"flag": {
Type: schema.TypeString,
Computed: true,
},
"gid": {
Type: schema.TypeInt,
Computed: true,
Description: "Grid id",
},
"guid": {
Type: schema.TypeInt,
Computed: true,
Description: "location id",
},
"id": {
Type: schema.TypeInt,
Computed: true,
Description: "location id",
},
"location_code": {
Type: schema.TypeString,
Computed: true,
Description: "Location code",
},
"name": {
Type: schema.TypeString,
Computed: true,
Description: "Location name",
},
},
},
},
}
}
func DataSourceLocationsList() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceLocationsListRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceLocationsListSchemaMake(),
}
}

View File

@@ -0,0 +1,81 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package locations
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/rudecs/terraform-provider-decort/internal/constants"
)
func dataSourceLocationUrlRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
url, err := utilityLocationUrlCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("url", url)
return nil
}
func dataSourceLocationUrlSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"url": {
Type: schema.TypeString,
Computed: true,
Description: "Location url",
},
}
}
func DataSourceLocationUrl() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceLocationUrlRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceLocationUrlSchemaMake(),
}
}

View File

@@ -0,0 +1,33 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@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.
*/
package locations
type Location struct {
GridID int `json:"gid"`
Id int `json:"id"`
Guid int `json:"guid"`
LocationCode string `json:"locationCode"`
Name string `json:"name"`
Flag string `json:"flag"`
Meta []interface{} `json:"_meta"`
CKey string `json:"_ckey"`
}
type LocationsList []Location

View File

@@ -0,0 +1,61 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package locations
import (
"context"
"encoding/json"
"net/url"
"github.com/rudecs/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityLocationUrlCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (string, error) {
c := m.(*controller.ControllerCfg)
log.Debugf("utilityLocationUrlCheckPresence: load locations list")
locationUrl, err := c.DecortAPICall(ctx, "POST", locationURLAPI, &url.Values{})
if err != nil {
return "", err
}
location := new(string)
err = json.Unmarshal([]byte(locationUrl), location)
if err != nil {
return "", nil
}
return *location, nil
}

View File

@@ -0,0 +1,70 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://github.com/rudecs/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://github.com/rudecs/terraform-provider-decort/wiki
*/
package locations
import (
"context"
"encoding/json"
"net/url"
"strconv"
"github.com/rudecs/terraform-provider-decort/internal/controller"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityLocationsListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (LocationsList, error) {
locationsList := LocationsList{}
c := m.(*controller.ControllerCfg)
urlValues := &url.Values{}
if page, ok := d.GetOk("page"); ok {
urlValues.Add("page", strconv.Itoa(page.(int)))
}
if size, ok := d.GetOk("size"); ok {
urlValues.Add("size", strconv.Itoa(size.(int)))
}
log.Debugf("utilityLocationsListCheckPresence: load locations list")
locationsListRaw, err := c.DecortAPICall(ctx, "POST", locationsListAPI, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(locationsListRaw), &locationsList)
if err != nil {
return nil, err
}
return locationsList, nil
}

View File

@@ -147,7 +147,6 @@ func DataSourceResgroup() *schema.Resource {
"quota": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: quotaRgSubresourceSchemaMake(), // this is a dictionary
},

View File

@@ -242,7 +242,6 @@ func dataSourceRgListSchemaMake() map[string]*schema.Schema {
"resource_limits": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cu_c": {

View File

@@ -141,7 +141,6 @@ func dataSourceSepConsumptionSchemaMake() map[string]*schema.Schema {
"total": {
Type: schema.TypeList,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"capacity_limit": {

View File

@@ -0,0 +1,30 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@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.
*/
package statefuncs
import "strings"
func StateFuncToLower(argval interface{}) string {
return strings.ToLower(argval.(string))
}
func StateFuncToUpper(argval interface{}) string {
return strings.ToUpper(argval.(string))
}