github.com/goreleaser/goreleaser@v1.25.1/www/docs/blog/posts/2022-02-05-cloud-native-storage.md (about)

     1  ---
     2  date: 2022-02-05
     3  slug: cloud-native-storage
     4  categories:
     5    - tutorials
     6  authors:
     7    - dirien
     8  ---
     9  
    10  # How to use GoReleaser with Cloud Native Storage
    11  
    12  In this tutorial, I want to describe, how quickly we can deploy our release
    13  artefacts to a cloud native storage when using GoReleaser.
    14  It’s just a few additional lines in your `.goreleaser.yaml`.
    15  
    16  <!-- more -->
    17  
    18  To better show this, I created a little demo and use the storage services of the
    19  big three cloud providers: Azure Blob Storage, AWS S3 and Google Cloud Storage.
    20  
    21  ![](https://cdn-images-1.medium.com/max/2000/1*4kvgGvBM9--v2rS7nO5c1g.png)
    22  
    23  You can use any S3 compatible storage provider too.
    24  **GoReleaser** support this too! The most prominent (self-hosted) solution is
    25  **MinIO**.
    26  
    27  ![](https://cdn-images-1.medium.com/max/4802/1*SH5PQKBDEB0M8mAY7EONeQ.png)
    28  
    29  ## The infrastructure code
    30  
    31  I created a very simple **Terraform** deployment to provision on all three cloud
    32  provider their appropriate cloud storage service.
    33  It’s a demo, why not?
    34  
    35  You don’t need to use **Terraform** for this, you could use any other means like
    36  **Pulumi**, **CLI** or even the **UI**.
    37  
    38  ###### `main.tf`
    39  
    40  ```terraform
    41  terraform {
    42    required_providers {
    43      google  = {
    44        source  = "hashicorp/google"
    45        version = "4.9.0"
    46      }
    47      azurerm = {
    48        source  = "hashicorp/azurerm"
    49        version = "2.94.0"
    50      }
    51      aws     = {
    52        source  = "hashicorp/aws"
    53        version = "3.74.0"
    54      }
    55    }
    56  }
    57  
    58  provider "azurerm" {
    59    features {}
    60  }
    61  
    62  provider "google" {
    63    credentials = file(var.gcp_auth_file)
    64    project     = var.gcp_project
    65    region      = var.gcp_region
    66  }
    67  
    68  provider "aws" {
    69    region = var.aws_region
    70  }
    71  ```
    72  
    73  ###### `variables.tf`
    74  
    75  ```terraform
    76  variable "gcp_project" {
    77    type = string
    78  }
    79  
    80  variable "gcp_region" {
    81    default = "europe-west6"
    82  }
    83  
    84  variable "gcp_zone" {
    85    default = "europe-west6-a"
    86  }
    87  
    88  variable "gcp_bucket_location" {
    89    default = "EU"
    90  }
    91  
    92  variable "gcp_auth_file" {
    93    default = "./auth.json"
    94    description = "Path to the GCP auth file"
    95  }
    96  
    97  variable "aws_region" {
    98    default = "eu-central-1"
    99  }
   100  
   101  variable "azure_location" {
   102    default = "West Europe"
   103  }
   104  
   105  variable "name" {
   106    default = "gorleaser-quickbites"
   107  }
   108  ```
   109  
   110  ###### `blob.tf`
   111  
   112  ```terraform
   113  resource "google_storage_bucket" "goreleaser-gcp-storage-bucket" {
   114    name                        = var.name
   115    location                    = var.gcp_bucket_location
   116    force_destroy               = true
   117    uniform_bucket_level_access = false
   118  }
   119  resource "google_storage_bucket_access_control" "goreleaser-gcp-storage-bucket-access-control" {
   120    bucket = google_storage_bucket.goreleaser-gcp-storage-bucket.name
   121    role   = "READER"
   122    entity = "allUsers"
   123  }
   124  
   125  resource "azurerm_resource_group" "goreleaser-azure-resource-group" {
   126    name     = var.name
   127    location = var.azure_location
   128  }
   129  
   130  resource "azurerm_storage_account" "goreleaser-azure-storage-account" {
   131    name                     = "gorleaserquickbites"
   132    resource_group_name      = azurerm_resource_group.goreleaser-azure-resource-group.name
   133    location                 = azurerm_resource_group.goreleaser-azure-resource-group.location
   134    account_tier             = "Standard"
   135    account_replication_type = "LRS"
   136    allow_blob_public_access = true
   137    network_rules {
   138      default_action = "Allow"
   139    }
   140  }
   141  
   142  resource "azurerm_storage_container" "goreleaser-storage-container" {
   143    name                  = var.name
   144    storage_account_name  = azurerm_storage_account.goreleaser-azure-storage-account.name
   145    container_access_type = "container"
   146  }
   147  
   148  resource "aws_s3_bucket" "goreleaser-s3-bucket" {
   149    bucket = var.name
   150    acl    = "public-read"
   151  }
   152  ```
   153  
   154  ###### Apply the Terraform script:
   155  
   156  ```bash
   157  terraform apply  -var  "gcp_project=xxx"
   158  ```
   159  
   160  ```
   161  ...
   162  azurerm_storage_container.goreleaser-storage-container: Creation complete after 0s [id=https://gorleaserquickbites.blob.core.windows.net/gorleaser-quickbites]
   163  
   164  Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
   165  
   166  Outputs:
   167  
   168  aws-s3-bucket-name = "gorleaser-quickbites"
   169  azure-storage-account-key = <sensitive>
   170  azure-storage-account-name = "export AZURE_STORAGE_ACCOUNT=gorleaserquickbites"
   171  gcp-bucket-url = "gs://gorleaser-quickbites"
   172  ```
   173  
   174  ###### Run this command
   175  
   176  ```bash
   177  terraform output azure-storage-account-key
   178  ```
   179  
   180  to get the Azure Storage Account Key, as it is a output field with sensitive data in it.
   181  
   182  ```bash
   183  export AZURE_STORAGE_KEY=xxxx
   184  ```
   185  
   186  Now we can add in our `.goreleaser.yaml` the new **blobs** field.
   187  Important is here to set the right provider: **gs** (for Google Cloud Storage),
   188  **azblob** (for Azure Blob) and **s3** (for AWS S3 or compatible provider)!
   189  
   190  ```yaml
   191  # This is an example .goreleaser.yml file with some sensible defaults.
   192  # Make sure to check the documentation at https://goreleaser.com
   193  before:
   194    hooks:
   195      - go mod tidy
   196  builds:
   197    - env:
   198        - CGO_ENABLED=0
   199      goos:
   200        - linux
   201        - darwin
   202  
   203  release:
   204    disable: true
   205  ---
   206  blobs:
   207    - provider: gs
   208      bucket: gorleaser-quickbites
   209    - provider: azblob
   210      bucket: gorleaser-quickbites
   211    - provider: s3
   212      bucket: gorleaser-quickbites
   213      region: eu-central-1
   214  ```
   215  
   216  In this demo, I disabled the **release **section, as I don’t want to upload to
   217  GitHub.
   218  
   219  ## Authentication
   220  
   221  In terms of authentication the GoReleaser’s blob pipe authentication varies depending upon the blob provider as mentioned below:
   222  
   223  ### S3 Provider
   224  
   225  S3 provider support AWS [default credential
   226  provider](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials)
   227  chain in the following order:
   228  
   229  - Environment variables.
   230  - Shared credentials file.
   231  - If your application is running on an Amazon EC2 instance, IAM role for Amazon EC2.
   232  
   233  ### Azure Blob Provider Currently it supports authentication only
   234  
   235  with [environment variables](https://docs.microsoft.com/en-us/azure/storage/common/storage-azure-cli#set-default-azure-storage-account-environment-variables):
   236  
   237  - AZURE_STORAGE_ACCOUNT
   238  - AZURE_STORAGE_KEY or AZURE_STORAGE_SAS_TOKEN
   239  
   240  ### GCS
   241  
   242  Provider GCS provider uses [Application Default
   243  Credentials](https://cloud.google.com/docs/authentication/production) in the
   244  following order:
   245  
   246  - Environment Variable (GOOGLE_APPLICATION_CREDENTIALS)
   247  - Default Service Account from the compute instance (Compute Engine, Kubernetes
   248    Engine, Cloud function etc).
   249  
   250  ## Run GoReleaser
   251  
   252  After configuring we can finally execute **GoReleaser**, in your pipeline code
   253  via the command:
   254  
   255  ```bash
   256  goreleaser release --rm-dist
   257  ```
   258  
   259  If everything went smooth, you should see a similar output, showing the upload of your artefacts.
   260  
   261  ```
   262    ...
   263     • publishing
   264     • blobs
   265     • uploading path=quick-bites/0.1/quick-bites_0.1_checksums.txt
   266     • uploading path=quick-bites/0.1/quick-bites_0.1_darwin_amd64.tar.gz
   267     • uploading path=quick-bites/0.1/quick-bites_0.1_linux_arm64.tar.gz
   268     • uploading path=quick-bites/0.1/quick-bites_0.1_darwin_arm64.tar.gz
   269     • uploading path=quick-bites/0.1/quick-bites_0.1_linux_amd64.tar.gz
   270     • uploading path=quick-bites/0.1/quick-bites_0.1_linux_386.tar.gz
   271     • uploading path=quick-bites/0.1/quick-bites_0.1_checksums.txt
   272     • uploading path=quick-bites/0.1/quick-bites_0.1_checksums.txt
   273     • uploading path=quick-bites/0.1/quick-bites_0.1_linux_386.tar.gz
   274     • uploading path=quick-bites/0.1/quick-bites_0.1_linux_amd64.tar.gz
   275     • uploading path=quick-bites/0.1/quick-bites_0.1_linux_arm64.tar.gz
   276     • uploading path=quick-bites/0.1/quick-bites_0.1_linux_amd64.tar.gz
   277     • uploading path=quick-bites/0.1/quick-bites_0.1_darwin_amd64.tar.gz
   278     • uploading path=quick-bites/0.1/quick-bites_0.1_darwin_arm64.tar.gz
   279     • uploading path=quick-bites/0.1/quick-bites_0.1_linux_386.tar.gz
   280     • uploading path=quick-bites/0.1/quick-bites_0.1_linux_arm64.tar.gz
   281     • uploading path=quick-bites/0.1/quick-bites_0.1_darwin_arm64.tar.gz
   282     • uploading path=quick-bites/0.1/quick-bites_0.1_darwin_amd64.tar.gz
   283     • release succeeded after 22.63s
   284    ...
   285  ```
   286  
   287  > One note: The provider fails silently, if your credentials are wrong. You
   288  > would still see uploading and release succeeded. Keep this in mind, if the
   289  > files are not appearing in the UI. I wasted some time on this. The culprit is
   290  > the underlying library GoReleaser is using.
   291  
   292  Let’s check in the consoles of the cloud provider too, If the files are present.
   293  
   294  ###### Google Cloud Storage:
   295  
   296  ![Google Cloud Storage](https://cdn-images-1.medium.com/max/2468/1*OHPaMIOK2YP7HsdgXEPpSw.png)
   297  
   298  ###### Azure Blob Storage
   299  
   300  ![Azure Blob Storage](https://cdn-images-1.medium.com/max/2792/1*K0BMoKe2qH29YHCOtZ8e9A.png)
   301  
   302  ###### AWS S3
   303  
   304  ![AWS S3](https://cdn-images-1.medium.com/max/2868/1*mvgyZMWtZseRabusw_R4Dg.png)
   305  
   306  Looks very good! Now you can share the URLs of the files for further use!
   307  
   308  ## Want more Informations?
   309  
   310  If you want to know more about some advanced options, feel free to check out the
   311  [official documentation about the blob support in
   312  GoReleaser](https://goreleaser.com/customization/blob/)
   313  
   314  And here is the example code: [dirien/quick-bytes](https://github.com/dirien/quick-bites/tree/main/goreleaser-blob)
   315  
   316  ![Have fun](https://cdn-images-1.medium.com/max/2000/0*kbicxfar7Vo9rUon.jpg)