From d434b4a968357064f4c14de727c13899ab81eefd Mon Sep 17 00:00:00 2001 From: Van Thong Nguyen Date: Thu, 25 Nov 2021 19:04:31 +0100 Subject: [PATCH 1/6] add fsaas resource/acc test --- gridscale/config.go | 1 + gridscale/provider.go | 1 + gridscale/resource_gridscale_fsaas.go | 407 +++++++++++++++++++++ gridscale/resource_gridscale_fsaas_test.go | 72 ++++ 4 files changed, 481 insertions(+) create mode 100644 gridscale/resource_gridscale_fsaas.go create mode 100644 gridscale/resource_gridscale_fsaas_test.go diff --git a/gridscale/config.go b/gridscale/config.go index 1a7b61b34..06e0b8501 100644 --- a/gridscale/config.go +++ b/gridscale/config.go @@ -19,6 +19,7 @@ var firewallActionTypes = []string{"accept", "drop"} var firewallRuleProtocols = []string{"udp", "tcp"} var marketplaceAppCategories = []string{"CMS", "project management", "Adminpanel", "Collaboration", "Cloud Storage", "Archiving"} var postgreSQLPerformanceClasses = []string{"standard", "high", "insane", "ultra"} +var filesystemPerformanceClasses = []string{"standard", "high", "insane", "ultra"} var msSQLServerPerformanceClasses = []string{"standard", "high", "insane", "ultra"} var mariaDBPerformanceClasses = []string{"standard", "high", "insane", "ultra"} diff --git a/gridscale/provider.go b/gridscale/provider.go index b02b7036d..e47646070 100644 --- a/gridscale/provider.go +++ b/gridscale/provider.go @@ -98,6 +98,7 @@ func Provider() *schema.Provider { "gridscale_mysql": resourceGridscaleMySQL(), "gridscale_mariadb": resourceGridscaleMariaDB(), "gridscale_memcached": resourceGridscaleMemcached(), + "gridscale_filesystem": resourceGridscaleFilesystem(), "gridscale_object_storage_accesskey": resourceGridscaleObjectStorage(), "gridscale_template": resourceGridscaleTemplate(), "gridscale_isoimage": resourceGridscaleISOImage(), diff --git a/gridscale/resource_gridscale_fsaas.go b/gridscale/resource_gridscale_fsaas.go new file mode 100644 index 000000000..482df1d13 --- /dev/null +++ b/gridscale/resource_gridscale_fsaas.go @@ -0,0 +1,407 @@ +package gridscale + +import ( + "context" + "fmt" + "net/http" + "strings" + "time" + + "github.com/gridscale/gsclient-go/v3" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + errHandler "github.com/terraform-providers/terraform-provider-gridscale/gridscale/error-handler" + + "log" +) + +const filesystemTemplateFlavourName = "filesystem" + +func resourceGridscaleFilesystem() *schema.Resource { + return &schema.Resource{ + Create: resourceGridscaleFilesystemCreate, + Read: resourceGridscaleFilesystemRead, + Delete: resourceGridscaleFilesystemDelete, + Update: resourceGridscaleFilesystemUpdate, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + CustomizeDiff: customdiff.All( + customdiff.ValidateChange("release", func(ctx context.Context, old, new, meta interface{}) error { + client := meta.(*gsclient.Client) + newReleaseVal := new.(string) + paasTemplates, err := client.GetPaaSTemplateList(ctx) + if err != nil { + return err + } + var isReleaseValid bool + var releaseList []string + TEMPLATELOOP: + for _, template := range paasTemplates { + if template.Properties.Flavour == filesystemTemplateFlavourName { + // check if release already presents in the release list. + // If so, ignore it. + for _, release := range releaseList { + if release == template.Properties.Release { + continue TEMPLATELOOP + } + } + releaseList = append(releaseList, template.Properties.Release) + if template.Properties.Release == newReleaseVal { + isReleaseValid = true + } + } + } + if !isReleaseValid { + return fmt.Errorf("%v is not a valid Filesystem service release. Valid releases are: %v\n", newReleaseVal, strings.Join(releaseList, ", ")) + } + return nil + }), + ), + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Description: "The human-readable name of the object. It supports the full UTF-8 character set, with a maximum of 64 characters.", + Required: true, + ValidateFunc: validation.NoZeroValues, + }, + "release": { + Type: schema.TypeString, + Description: `The Filesystem service release of this instance.\n + For convenience, please use gscloud https://github.com/gridscale/gscloud to get the list of available Filesystem service releases.`, + Required: true, + ValidateFunc: validation.NoZeroValues, + }, + "performance_class": { + Type: schema.TypeString, + Description: "Performance class of Filesystem service.", + Required: true, + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + valid := false + for _, class := range filesystemPerformanceClasses { + if v.(string) == class { + valid = true + break + } + } + if !valid { + errors = append(errors, fmt.Errorf("%v is not a valid Filesystem performance class. Valid values are: %v", v.(string), strings.Join(postgreSQLPerformanceClasses, ","))) + } + return + }, + }, + "listen_port": { + Type: schema.TypeSet, + Description: "The port numbers where this Filesystem service accepts connections.", + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + }, + "host": { + Type: schema.TypeString, + Computed: true, + }, + "port": { + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + "security_zone_uuid": { + Type: schema.TypeString, + Description: "Security zone UUID linked to Filesystem service.", + Optional: true, + ForceNew: true, + Computed: true, + }, + "root_squash": { + Type: schema.TypeBool, + Description: "Map root user/group ownership to anon_uid/anon_gid", + Optional: true, + }, + "allowed_ip_ranges": { + Type: schema.TypeSet, + Description: "Allowed CIDR block or IP address in CIDR notation.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "anon_uid": { + Type: schema.TypeInt, + Description: "Target user id when root squash is active.", + Optional: true, + }, + "anon_gid": { + Type: schema.TypeInt, + Description: "Target group id when root squash is active.", + Optional: true, + }, + "network_uuid": { + Type: schema.TypeString, + Description: "Network UUID containing security zone.", + Computed: true, + }, + "service_template_uuid": { + Type: schema.TypeString, + Description: "PaaS service template that Filesystem service uses.", + Computed: true, + }, + "usage_in_minutes": { + Type: schema.TypeInt, + Description: "Number of minutes that Filesystem service is in use.", + Computed: true, + }, + "change_time": { + Type: schema.TypeString, + Description: "Time of the last change.", + Computed: true, + }, + "create_time": { + Type: schema.TypeString, + Description: "Date time this service has been created.", + Computed: true, + }, + "status": { + Type: schema.TypeString, + Description: "Current status of Filesystem service.", + Computed: true, + }, + "labels": { + Type: schema.TypeSet, + Description: "List of labels.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(15 * time.Minute), + Update: schema.DefaultTimeout(15 * time.Minute), + Delete: schema.DefaultTimeout(15 * time.Minute), + }, + } +} + +func resourceGridscaleFilesystemRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gsclient.Client) + errorPrefix := fmt.Sprintf("read paas (%s) resource -", d.Id()) + paas, err := client.GetPaaSService(context.Background(), d.Id()) + if err != nil { + if requestError, ok := err.(gsclient.RequestError); ok { + if requestError.StatusCode == 404 { + d.SetId("") + return nil + } + } + return fmt.Errorf("%s error: %v", errorPrefix, err) + } + props := paas.Properties + if err = d.Set("name", props.Name); err != nil { + return fmt.Errorf("%s error setting name: %v", errorPrefix, err) + } + if err = d.Set("security_zone_uuid", props.SecurityZoneUUID); err != nil { + return fmt.Errorf("%s error setting security_zone_uuid: %v", errorPrefix, err) + } + if err = d.Set("service_template_uuid", props.ServiceTemplateUUID); err != nil { + return fmt.Errorf("%s error setting service_template_uuid: %v", errorPrefix, err) + } + if err = d.Set("usage_in_minutes", props.UsageInMinutes); err != nil { + return fmt.Errorf("%s error setting usage_in_minutes: %v", errorPrefix, err) + } + if err = d.Set("change_time", props.ChangeTime.String()); err != nil { + return fmt.Errorf("%s error setting change_time: %v", errorPrefix, err) + } + if err = d.Set("create_time", props.CreateTime.String()); err != nil { + return fmt.Errorf("%s error setting create_time: %v", errorPrefix, err) + } + if err = d.Set("status", props.Status); err != nil { + return fmt.Errorf("%s error setting status: %v", errorPrefix, err) + } + + // Set Filesystem parameters + if err = d.Set("root_squash", props.Parameters["root_squash"]); err != nil { + return fmt.Errorf("%s error setting root_squash: %v", errorPrefix, err) + } + if err = d.Set("allowed_ip_ranges", props.Parameters["allowed_ip_ranges"]); err != nil { + return fmt.Errorf("%s error setting allowed_ip_ranges: %v", errorPrefix, err) + } + if err = d.Set("anon_uid", props.Parameters["anon_uid"]); err != nil { + return fmt.Errorf("%s error setting anon_uid: %v", errorPrefix, err) + } + if err = d.Set("anon_gid", props.Parameters["anon_gid"]); err != nil { + return fmt.Errorf("%s error setting anon_gid: %v", errorPrefix, err) + } + + //Get listen ports + listenPorts := make([]interface{}, 0) + for host, value := range props.ListenPorts { + for k, portValue := range value { + port := map[string]interface{}{ + "name": k, + "host": host, + "port": portValue, + } + listenPorts = append(listenPorts, port) + } + } + if err = d.Set("listen_port", listenPorts); err != nil { + return fmt.Errorf("%s error setting listen ports: %v", errorPrefix, err) + } + + //Set labels + if err = d.Set("labels", props.Labels); err != nil { + return fmt.Errorf("%s error setting labels: %v", errorPrefix, err) + } + + //Get all available networks + networks, err := client.GetNetworkList(context.Background()) + if err != nil { + return fmt.Errorf("%s error getting networks: %v", errorPrefix, err) + } + //look for a network that the Filesystem service is in + for _, network := range networks { + securityZones := network.Properties.Relations.PaaSSecurityZones + //Each network can contain only one security zone + if len(securityZones) >= 1 { + if securityZones[0].ObjectUUID == props.SecurityZoneUUID { + if err = d.Set("network_uuid", network.Properties.ObjectUUID); err != nil { + return fmt.Errorf("%s error setting network_uuid: %v", errorPrefix, err) + } + } + } + } + return nil +} + +func resourceGridscaleFilesystemCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gsclient.Client) + errorPrefix := fmt.Sprintf("create k8s (%s) resource -", d.Id()) + + release := d.Get("release").(string) + performanceClass := d.Get("performance_class").(string) + // Get filesystem template UUID + templateUUID, err := getFilesystemTemplateUUID(client, release, performanceClass) + if err != nil { + return fmt.Errorf("%s error: %v", errorPrefix, err) + } + + requestBody := gsclient.PaaSServiceCreateRequest{ + Name: d.Get("name").(string), + PaaSServiceTemplateUUID: templateUUID, + Labels: convSOStrings(d.Get("labels").(*schema.Set).List()), + PaaSSecurityZoneUUID: d.Get("security_zone_uuid").(string), + } + params := make(map[string]interface{}) + if rootSquash, ok := d.GetOk("root_squash"); ok { + params["root_squash"] = rootSquash + } + if allowedIPRanges, ok := d.GetOk("allowed_ip_ranges"); ok { + params["allowed_ip_ranges"] = convSOStrings(allowedIPRanges.(*schema.Set).List()) + } + if anonUID, ok := d.GetOk("anon_uid"); ok { + params["anon_uid"] = anonUID + } + if anonGID, ok := d.GetOk("anon_gid"); ok { + params["anon_gid"] = anonGID + } + requestBody.Parameters = params + log.Printf("-------%v\n", requestBody) + ctx, cancel := context.WithTimeout(context.Background(), d.Timeout(schema.TimeoutCreate)) + defer cancel() + response, err := client.CreatePaaSService(ctx, requestBody) + if err != nil { + return err + } + d.SetId(response.ObjectUUID) + log.Printf("The id for Filesystem service %s has been set to %v", requestBody.Name, response.ObjectUUID) + return resourceGridscaleFilesystemRead(d, meta) +} + +func resourceGridscaleFilesystemUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gsclient.Client) + errorPrefix := fmt.Sprintf("update k8s (%s) resource -", d.Id()) + + labels := convSOStrings(d.Get("labels").(*schema.Set).List()) + requestBody := gsclient.PaaSServiceUpdateRequest{ + Name: d.Get("name").(string), + Labels: &labels, + } + params := make(map[string]interface{}) + if rootSquash, ok := d.GetOk("root_squash"); ok { + params["root_squash"] = rootSquash + } + if allowedIPRanges, ok := d.GetOk("allowed_ip_ranges"); ok { + params["allowed_ip_ranges"] = convSOStrings(allowedIPRanges.(*schema.Set).List()) + } + if anonUID, ok := d.GetOk("anon_uid"); ok { + params["anon_uid"] = anonUID + } + if anonGID, ok := d.GetOk("anon_gid"); ok { + params["anon_gid"] = anonGID + } + requestBody.Parameters = params + + // Only update templateUUID, when `release` or `performance_class` is changed + if d.HasChange("release") || d.HasChange("performance_class") { + // Get postgres template UUID + release := d.Get("release").(string) + performanceClass := d.Get("performance_class").(string) + templateUUID, err := getFilesystemTemplateUUID(client, release, performanceClass) + if err != nil { + return fmt.Errorf("%s error: %v", errorPrefix, err) + } + requestBody.PaaSServiceTemplateUUID = templateUUID + } + + ctx, cancel := context.WithTimeout(context.Background(), d.Timeout(schema.TimeoutUpdate)) + defer cancel() + err := client.UpdatePaaSService(ctx, d.Id(), requestBody) + if err != nil { + return fmt.Errorf("%s error: %v", errorPrefix, err) + } + return resourceGridscaleFilesystemRead(d, meta) +} + +func resourceGridscaleFilesystemDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*gsclient.Client) + errorPrefix := fmt.Sprintf("delete paas (%s) resource -", d.Id()) + + ctx, cancel := context.WithTimeout(context.Background(), d.Timeout(schema.TimeoutDelete)) + defer cancel() + err := errHandler.RemoveErrorContainsHTTPCodes( + client.DeletePaaSService(ctx, d.Id()), + http.StatusNotFound, + ) + if err != nil { + return fmt.Errorf("%s error: %v", errorPrefix, err) + } + return nil +} + +// getFilesystemTemplateUUID returns the UUID of the filesystem service template. +func getFilesystemTemplateUUID(client *gsclient.Client, release, performanceClass string) (string, error) { + paasTemplates, err := client.GetPaaSTemplateList(context.Background()) + if err != nil { + return "", err + } + var isReleaseValid bool + var releases []string + var uTemplate gsclient.PaaSTemplate + for _, template := range paasTemplates { + if template.Properties.Flavour == filesystemTemplateFlavourName { + releases = append(releases, template.Properties.Release) + if template.Properties.Release == release && template.Properties.PerformanceClass == performanceClass { + isReleaseValid = true + uTemplate = template + } + } + } + if !isReleaseValid { + return "", fmt.Errorf("%v is not a valid Filesystem service release. Valid releases are: %v\n", release, strings.Join(releases, ", ")) + } + + return uTemplate.Properties.ObjectUUID, nil +} diff --git a/gridscale/resource_gridscale_fsaas_test.go b/gridscale/resource_gridscale_fsaas_test.go new file mode 100644 index 000000000..367c5a376 --- /dev/null +++ b/gridscale/resource_gridscale_fsaas_test.go @@ -0,0 +1,72 @@ +package gridscale + +import ( + "fmt" + + "github.com/gridscale/gsclient-go/v3" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "testing" +) + +func TestAccResourceGridscaleFilesystem_Basic(t *testing.T) { + var object gsclient.PaaSService + name := fmt.Sprintf("TEST-Filesystem-%s", acctest.RandString(10)) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckResourceGridscalePaaSDestroyCheck, + Steps: []resource.TestStep{ + { + Config: testAccCheckResourceGridscaleFilesystemConfig_basic(name), + Check: resource.ComposeTestCheckFunc( + testAccCheckResourceGridscalePaaSExists("gridscale_filesystem.test", &object), + resource.TestCheckResourceAttr( + "gridscale_filesystem.test", "name", name), + resource.TestCheckResourceAttr( + "gridscale_filesystem.test", "allowed_ip_ranges.0", "192.14.2.2"), + resource.TestCheckResourceAttr( + "gridscale_filesystem.test", "allowed_ip_ranges.1", "192.168.0.0/16"), + resource.TestCheckResourceAttrSet( + "gridscale_filesystem.test", "root_squash"), + ), + }, + { + Config: testAccCheckResourceGridscaleFilesystemConfig_basic_update(), + Check: resource.ComposeTestCheckFunc( + testAccCheckResourceGridscalePaaSExists("gridscale_filesystem.test", &object), + resource.TestCheckResourceAttr( + "gridscale_filesystem.test", "name", "newname"), + resource.TestCheckResourceAttr( + "gridscale_filesystem.test", "allowed_ip_ranges.0", "192.14.15.15"), + ), + }, + }, + }) +} + +func testAccCheckResourceGridscaleFilesystemConfig_basic(name string) string { + return fmt.Sprintf(` +resource "gridscale_filesystem" "test" { + name = "%s" + release = "1" + performance_class = "standard" + root_squash = true + allowed_ip_ranges = ["192.14.2.2", "192.168.0.0/16"] +} +`, name) +} + +func testAccCheckResourceGridscaleFilesystemConfig_basic_update() string { + return fmt.Sprintf(` +resource "gridscale_filesystem" "test" { + name = "newname" + root_squash = false + release = "1" + performance_class = "standard" + allowed_ip_ranges = ["192.14.15.15"] + labels = ["test"] +} +`) +} From 2bcb8cb59766ef93b9b043908aaf0f22746392af Mon Sep 17 00:00:00 2001 From: Van Thong Nguyen Date: Tue, 4 Jan 2022 13:20:33 +0100 Subject: [PATCH 2/6] add gridscale filesystem docs --- website/docs/r/filesystem.html.md | 80 +++++++++++++++++++++++++++++++ website/gridscale.erb | 3 ++ 2 files changed, 83 insertions(+) create mode 100644 website/docs/r/filesystem.html.md diff --git a/website/docs/r/filesystem.html.md b/website/docs/r/filesystem.html.md new file mode 100644 index 000000000..ebd1434f4 --- /dev/null +++ b/website/docs/r/filesystem.html.md @@ -0,0 +1,80 @@ +--- +layout: "gridscale" +page_title: "gridscale: gridscale_mysql" +sidebar_current: "docs-gridscale-resource-filesystem" +description: |- + Manage a Filesystem service in gridscale. +--- + +# gridscale_filesystem + +Provides a Filesystem service resource. This can be used to create, modify, and delete Filesystem service instances. + +## Example + +The following example shows how one might use this resource to add a Filesystem service to gridscale: + +```terraform +resource "gridscale_filesystem" "terra-filesystem-test" { + name = "my filesystem" + release = "1" + performance_class = "standard" + root_squash = true + allowed_ip_ranges = ["192.14.2.2", "192.168.0.0/16"] +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The human-readable name of the object. It supports the full UTF-8 character set, with a maximum of 64 characters. + +* `release` - (Required) The filesystem service release of this instance. For convenience, please use [gscloud](https://github.com/gridscale/gscloud) to get the list of available filesystem service releases. + +* `performance_class` - (Required) Performance class of filesystem service. Available performance classes at the time of writing: `standard`, `high`, `insane`, `ultra`. + +* `labels` - (Optional) List of labels in the format [ "label1", "label2" ]. + +* `security_zone_uuid` - (Optional) The UUID of the security zone that the service is running in. + +* `root_squash` - (Optional) Map root user/group ownership to anon_uid/anon_gid. + +* `allowed_ip_ranges` - (Optional) Allowed CIDR block or IP address in CIDR notation. + +* `anon_uid` - (Optional) Target user id when root squash is active. + +* `anon_gid` - (Optional) Target group id when root squash is active. + +## Timeouts + +Timeouts configuration options (in seconds): +More info: [terraform.io/docs/configuration/resources.html#operation-timeouts](https://www.terraform.io/docs/configuration/resources.html#operation-timeouts) + +* `create` - (Default value is "15m" - 15 minutes) Used for creating a resource. +* `update` - (Default value is "15m" - 15 minutes) Used for updating a resource. +* `delete` - (Default value is "15m" - 15 minutes) Used for deleting a resource. + +## Attributes + +This resource exports the following attributes: + +* `name` - See Argument Reference above. +* `release` - See Argument Reference above. +* `performance_class` - See Argument Reference above. +* `root_squash` - See Argument Reference above. +* `allowed_ip_ranges` - See Argument Reference above. +* `anon_uid` - See Argument Reference above. +* `anon_gid` - See Argument Reference above. +* `listen_port` - The port numbers where the filesystem service accepts connections. + * `name` - Name of a port. + * `host` - Host address. + * `listen_port` - Port number. +* `security_zone_uuid` - See Argument Reference above. +* `network_uuid` - Network UUID containing security zone. +* `service_template_uuid` - PaaS service template that filesystem service uses. +* `usage_in_minutes` - Number of minutes that PaaS service is in use. +* `change_time` - Time of the last change. +* `create_time` - Date time this service has been created. +* `status` - Current status of PaaS service. +* `labels` - See Argument Reference above. diff --git a/website/gridscale.erb b/website/gridscale.erb index 084873396..a257b74b5 100644 --- a/website/gridscale.erb +++ b/website/gridscale.erb @@ -119,6 +119,9 @@ > gridscale_mysql + > + gridscale_filesystem + > gridscale_paas_securityzone From a9bc49c60532e8e9705ee4336deaae2266262cd8 Mon Sep 17 00:00:00 2001 From: Van Thong Nguyen Date: Tue, 4 Jan 2022 13:22:06 +0100 Subject: [PATCH 3/6] rename fsaas files --- ...source_gridscale_fsaas.go => resource_gridscale_filesystem.go} | 0 ...dscale_fsaas_test.go => resource_gridscale_filesystem_test.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename gridscale/{resource_gridscale_fsaas.go => resource_gridscale_filesystem.go} (100%) rename gridscale/{resource_gridscale_fsaas_test.go => resource_gridscale_filesystem_test.go} (100%) diff --git a/gridscale/resource_gridscale_fsaas.go b/gridscale/resource_gridscale_filesystem.go similarity index 100% rename from gridscale/resource_gridscale_fsaas.go rename to gridscale/resource_gridscale_filesystem.go diff --git a/gridscale/resource_gridscale_fsaas_test.go b/gridscale/resource_gridscale_filesystem_test.go similarity index 100% rename from gridscale/resource_gridscale_fsaas_test.go rename to gridscale/resource_gridscale_filesystem_test.go From 8c1b1a2588ed1b267e7beceb21397fd8a303d283 Mon Sep 17 00:00:00 2001 From: Van Thong Nguyen Date: Tue, 4 Jan 2022 13:25:11 +0100 Subject: [PATCH 4/6] add filesystem gh action workflow --- .github/workflows/filesystem.yml | 43 ++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/filesystem.yml diff --git a/.github/workflows/filesystem.yml b/.github/workflows/filesystem.yml new file mode 100644 index 000000000..7403b67ed --- /dev/null +++ b/.github/workflows/filesystem.yml @@ -0,0 +1,43 @@ +name: Test Filesystem rs + +on: + workflow_dispatch: + push: + branches: + - master + paths: + - "**.go" + - ".github/workflows/filesystem.yml" + pull_request: + branches: + - master + paths: + - "**gridscale_filesystem**" + - "gridscale/error-handler/**" + - "gridscale/common.go" + - "gridscale/config.go" + - "gridscale/provider.go" + - "gridscale/provider_test.go" + - ".github/workflows/filesystem.yml" + +jobs: + build: + name: GS Filesystem AccTest + runs-on: ubuntu-latest + env: + GOPATH: /home/runner/go + GRIDSCALE_UUID: ${{ secrets.CI_USER_UUID }} + GRIDSCALE_TOKEN: ${{ secrets.CI_API_TOKEN }} + GRIDSCALE_URL: ${{ secrets.CI_API_URL }} + steps: + - name: Set up Go 1.16 + uses: actions/setup-go@v2 + with: + go-version: ^1.16 + id: go + + - name: Check out code into the Go module directory + uses: actions/checkout@v2 + + - name: Run TestAccResourceGridscaleFilesystem_Basic + run: make testacc TEST=./gridscale TESTARGS='-run=TestAccResourceGridscaleFilesystem_Basic' From 94e3bcb363523b43aabdb48016f35f18b8115efc Mon Sep 17 00:00:00 2001 From: Van Thong Nguyen Date: Tue, 4 Jan 2022 13:52:13 +0100 Subject: [PATCH 5/6] go mod vendor --- .../klauspost/compress/fse/README.md | 79 +++++++++++++++++ .../klauspost/compress/huff0/README.md | 87 +++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 vendor/github.com/klauspost/compress/fse/README.md create mode 100644 vendor/github.com/klauspost/compress/huff0/README.md diff --git a/vendor/github.com/klauspost/compress/fse/README.md b/vendor/github.com/klauspost/compress/fse/README.md new file mode 100644 index 000000000..ea7324da6 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/README.md @@ -0,0 +1,79 @@ +# Finite State Entropy + +This package provides Finite State Entropy encoding and decoding. + +Finite State Entropy (also referenced as [tANS](https://en.wikipedia.org/wiki/Asymmetric_numeral_systems#tANS)) +encoding provides a fast near-optimal symbol encoding/decoding +for byte blocks as implemented in [zstandard](https://github.com/facebook/zstd). + +This can be used for compressing input with a lot of similar input values to the smallest number of bytes. +This does not perform any multi-byte [dictionary coding](https://en.wikipedia.org/wiki/Dictionary_coder) as LZ coders, +but it can be used as a secondary step to compressors (like Snappy) that does not do entropy encoding. + +* [Godoc documentation](https://godoc.org/github.com/klauspost/compress/fse) + +## News + + * Feb 2018: First implementation released. Consider this beta software for now. + +# Usage + +This package provides a low level interface that allows to compress single independent blocks. + +Each block is separate, and there is no built in integrity checks. +This means that the caller should keep track of block sizes and also do checksums if needed. + +Compressing a block is done via the [`Compress`](https://godoc.org/github.com/klauspost/compress/fse#Compress) function. +You must provide input and will receive the output and maybe an error. + +These error values can be returned: + +| Error | Description | +|---------------------|-----------------------------------------------------------------------------| +| `` | Everything ok, output is returned | +| `ErrIncompressible` | Returned when input is judged to be too hard to compress | +| `ErrUseRLE` | Returned from the compressor when the input is a single byte value repeated | +| `(error)` | An internal error occurred. | + +As can be seen above there are errors that will be returned even under normal operation so it is important to handle these. + +To reduce allocations you can provide a [`Scratch`](https://godoc.org/github.com/klauspost/compress/fse#Scratch) object +that can be re-used for successive calls. Both compression and decompression accepts a `Scratch` object, and the same +object can be used for both. + +Be aware, that when re-using a `Scratch` object that the *output* buffer is also re-used, so if you are still using this +you must set the `Out` field in the scratch to nil. The same buffer is used for compression and decompression output. + +Decompressing is done by calling the [`Decompress`](https://godoc.org/github.com/klauspost/compress/fse#Decompress) function. +You must provide the output from the compression stage, at exactly the size you got back. If you receive an error back +your input was likely corrupted. + +It is important to note that a successful decoding does *not* mean your output matches your original input. +There are no integrity checks, so relying on errors from the decompressor does not assure your data is valid. + +For more detailed usage, see examples in the [godoc documentation](https://godoc.org/github.com/klauspost/compress/fse#pkg-examples). + +# Performance + +A lot of factors are affecting speed. Block sizes and compressibility of the material are primary factors. +All compression functions are currently only running on the calling goroutine so only one core will be used per block. + +The compressor is significantly faster if symbols are kept as small as possible. The highest byte value of the input +is used to reduce some of the processing, so if all your input is above byte value 64 for instance, it may be +beneficial to transpose all your input values down by 64. + +With moderate block sizes around 64k speed are typically 200MB/s per core for compression and +around 300MB/s decompression speed. + +The same hardware typically does Huffman (deflate) encoding at 125MB/s and decompression at 100MB/s. + +# Plans + +At one point, more internals will be exposed to facilitate more "expert" usage of the components. + +A streaming interface is also likely to be implemented. Likely compatible with [FSE stream format](https://github.com/Cyan4973/FiniteStateEntropy/blob/dev/programs/fileio.c#L261). + +# Contributing + +Contributions are always welcome. Be aware that adding public functions will require good justification and breaking +changes will likely not be accepted. If in doubt open an issue before writing the PR. \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/huff0/README.md b/vendor/github.com/klauspost/compress/huff0/README.md new file mode 100644 index 000000000..e12da4db2 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/README.md @@ -0,0 +1,87 @@ +# Huff0 entropy compression + +This package provides Huff0 encoding and decoding as used in zstd. + +[Huff0](https://github.com/Cyan4973/FiniteStateEntropy#new-generation-entropy-coders), +a Huffman codec designed for modern CPU, featuring OoO (Out of Order) operations on multiple ALU +(Arithmetic Logic Unit), achieving extremely fast compression and decompression speeds. + +This can be used for compressing input with a lot of similar input values to the smallest number of bytes. +This does not perform any multi-byte [dictionary coding](https://en.wikipedia.org/wiki/Dictionary_coder) as LZ coders, +but it can be used as a secondary step to compressors (like Snappy) that does not do entropy encoding. + +* [Godoc documentation](https://godoc.org/github.com/klauspost/compress/huff0) + +## News + + * Mar 2018: First implementation released. Consider this beta software for now. + +# Usage + +This package provides a low level interface that allows to compress single independent blocks. + +Each block is separate, and there is no built in integrity checks. +This means that the caller should keep track of block sizes and also do checksums if needed. + +Compressing a block is done via the [`Compress1X`](https://godoc.org/github.com/klauspost/compress/huff0#Compress1X) and +[`Compress4X`](https://godoc.org/github.com/klauspost/compress/huff0#Compress4X) functions. +You must provide input and will receive the output and maybe an error. + +These error values can be returned: + +| Error | Description | +|---------------------|-----------------------------------------------------------------------------| +| `` | Everything ok, output is returned | +| `ErrIncompressible` | Returned when input is judged to be too hard to compress | +| `ErrUseRLE` | Returned from the compressor when the input is a single byte value repeated | +| `ErrTooBig` | Returned if the input block exceeds the maximum allowed size (128 Kib) | +| `(error)` | An internal error occurred. | + + +As can be seen above some of there are errors that will be returned even under normal operation so it is important to handle these. + +To reduce allocations you can provide a [`Scratch`](https://godoc.org/github.com/klauspost/compress/huff0#Scratch) object +that can be re-used for successive calls. Both compression and decompression accepts a `Scratch` object, and the same +object can be used for both. + +Be aware, that when re-using a `Scratch` object that the *output* buffer is also re-used, so if you are still using this +you must set the `Out` field in the scratch to nil. The same buffer is used for compression and decompression output. + +The `Scratch` object will retain state that allows to re-use previous tables for encoding and decoding. + +## Tables and re-use + +Huff0 allows for reusing tables from the previous block to save space if that is expected to give better/faster results. + +The Scratch object allows you to set a [`ReusePolicy`](https://godoc.org/github.com/klauspost/compress/huff0#ReusePolicy) +that controls this behaviour. See the documentation for details. This can be altered between each block. + +Do however note that this information is *not* stored in the output block and it is up to the users of the package to +record whether [`ReadTable`](https://godoc.org/github.com/klauspost/compress/huff0#ReadTable) should be called, +based on the boolean reported back from the CompressXX call. + +If you want to store the table separate from the data, you can access them as `OutData` and `OutTable` on the +[`Scratch`](https://godoc.org/github.com/klauspost/compress/huff0#Scratch) object. + +## Decompressing + +The first part of decoding is to initialize the decoding table through [`ReadTable`](https://godoc.org/github.com/klauspost/compress/huff0#ReadTable). +This will initialize the decoding tables. +You can supply the complete block to `ReadTable` and it will return the data part of the block +which can be given to the decompressor. + +Decompressing is done by calling the [`Decompress1X`](https://godoc.org/github.com/klauspost/compress/huff0#Scratch.Decompress1X) +or [`Decompress4X`](https://godoc.org/github.com/klauspost/compress/huff0#Scratch.Decompress4X) function. + +For concurrently decompressing content with a fixed table a stateless [`Decoder`](https://godoc.org/github.com/klauspost/compress/huff0#Decoder) can be requested which will remain correct as long as the scratch is unchanged. The capacity of the provided slice indicates the expected output size. + +You must provide the output from the compression stage, at exactly the size you got back. If you receive an error back +your input was likely corrupted. + +It is important to note that a successful decoding does *not* mean your output matches your original input. +There are no integrity checks, so relying on errors from the decompressor does not assure your data is valid. + +# Contributing + +Contributions are always welcome. Be aware that adding public functions will require good justification and breaking +changes will likely not be accepted. If in doubt open an issue before writing the PR. From 0da4a75e26787e676ad218b709b704d3f52f8cb6 Mon Sep 17 00:00:00 2001 From: Van Thong Nguyen Date: Tue, 18 Jan 2022 16:30:54 +0100 Subject: [PATCH 6/6] fix indentations --- gridscale/resource_gridscale_filesystem_test.go | 8 ++++---- website/docs/r/filesystem.html.md | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/gridscale/resource_gridscale_filesystem_test.go b/gridscale/resource_gridscale_filesystem_test.go index 367c5a376..1487e9fd4 100644 --- a/gridscale/resource_gridscale_filesystem_test.go +++ b/gridscale/resource_gridscale_filesystem_test.go @@ -51,9 +51,9 @@ func testAccCheckResourceGridscaleFilesystemConfig_basic(name string) string { resource "gridscale_filesystem" "test" { name = "%s" release = "1" - performance_class = "standard" + performance_class = "standard" root_squash = true - allowed_ip_ranges = ["192.14.2.2", "192.168.0.0/16"] + allowed_ip_ranges = ["192.14.2.2", "192.168.0.0/16"] } `, name) } @@ -64,8 +64,8 @@ resource "gridscale_filesystem" "test" { name = "newname" root_squash = false release = "1" - performance_class = "standard" - allowed_ip_ranges = ["192.14.15.15"] + performance_class = "standard" + allowed_ip_ranges = ["192.14.15.15"] labels = ["test"] } `) diff --git a/website/docs/r/filesystem.html.md b/website/docs/r/filesystem.html.md index ebd1434f4..cfa3151b5 100644 --- a/website/docs/r/filesystem.html.md +++ b/website/docs/r/filesystem.html.md @@ -16,11 +16,11 @@ The following example shows how one might use this resource to add a Filesystem ```terraform resource "gridscale_filesystem" "terra-filesystem-test" { - name = "my filesystem" - release = "1" - performance_class = "standard" - root_squash = true - allowed_ip_ranges = ["192.14.2.2", "192.168.0.0/16"] + name = "my filesystem" + release = "1" + performance_class = "standard" + root_squash = true + allowed_ip_ranges = ["192.14.2.2", "192.168.0.0/16"] } ```