From df89437b466a10de953f7d619c2788670304a33b Mon Sep 17 00:00:00 2001
From: Abeeujah
Date: Mon, 18 Nov 2024 18:18:30 +0100
Subject: [PATCH] refac: Implemented requested changes
---
README.md | 58 ++++-----
cmd/relayproxy/config/retriever.go | 23 ++--
cmd/relayproxy/config/retriever_test.go | 9 +-
cmd/relayproxy/service/gofeatureflag.go | 2 +-
retriever/azblobstorageretriever/README.md | 115 ++++++++++++++++--
retriever/azblobstorageretriever/retriever.go | 74 ++++++++---
.../azblobstorageretriever/retriever_test.go | 2 +-
7 files changed, 216 insertions(+), 67 deletions(-)
diff --git a/README.md b/README.md
index ad0485ca570d..a96f4f690db0 100644
--- a/README.md
+++ b/README.md
@@ -19,9 +19,9 @@
-> :pray: If you are using **GO Feature Flag** please consider to add yourself in the [adopters](./ADOPTERS.md) list.
+> :pray: If you are using **GO Feature Flag** please consider to add yourself in the [adopters](./ADOPTERS.md) list.
> This simple act significantly boosts the project's visibility and credibility, making a substantial contribution to its advancement.
->
+>
> If you want to support me and GO Feature Flag, you can also [become a sponsor](https://github.com/sponsors/thomaspoignant).
## Table of Contents
@@ -82,11 +82,11 @@ _The code of this demo is available in [`examples/demo`](examples/demo) reposito
> [!IMPORTANT]
> Before starting to use **GO Feature Flag** you should decide
> if you want to use Open Feature SDKs or if you want to use GO Feature Flag as a GO Module.
->
+>
> We recommend using the relay-proxy for a central flag management and evaluation solution,
-> it enables the multi-languages support, and it integrates seamlessly with the Open Feature SDKs.
+> it enables the multi-languages support, and it integrates seamlessly with the Open Feature SDKs.
> This is the best way to get full potential of GO Feature Flag.
->
+>
> If your project is exclusively in GO, the GO module is an option. It will perform the flag evaluation directly in your GO code.
@@ -128,7 +128,7 @@ exporter:
### Install the relay proxy
-And we will run the **relay proxy** locally to make the API available.
+And we will run the **relay proxy** locally to make the API available.
The default port will be `1031`.
```shell
@@ -239,8 +239,8 @@ defer ffclient.Close()
*This example will load a file from your local computer and will refresh the flags every 3 seconds (if you omit the
PollingInterval, the default value is 60 seconds).*
-> ℹ info
-This is a basic configuration to test locally, in production it is better to use a remote place to store your feature flag configuration file.
+> ℹ info
+This is a basic configuration to test locally, in production it is better to use a remote place to store your feature flag configuration file.
Look at the list of available options in the [**Store your feature flag file** page](https://gofeatureflag.org/docs/go_module/store_file/).
### Evaluate your flags
@@ -255,18 +255,18 @@ if hasFlag {
// flag "test-flag" is false for the user
}
```
-The full documentation is available on https://docs.gofeatureflag.org
+The full documentation is available on https://docs.gofeatureflag.org
You can find more examples in the [examples/](https://github.com/thomaspoignant/go-feature-flag/tree/main/examples) directory.
## Can I use GO Feature Flag with any language?
-Originally GO Feature Flag was built to be a GOlang only library, but it limits the ecosystem too much.
+Originally GO Feature Flag was built to be a GOlang only library, but it limits the ecosystem too much.
To be compatible with more languages we have implemented the [GO Feature Flag Relay Proxy](cmd/relayproxy/).
It is a service you can host that provides an API to evaluate your flags, you can call it using HTTP to get your variation.
-Since we believe in standardization we are also implementing [OpenFeature](https://github.com/open-feature) providers to interact with this API in the language of your choice.
+Since we believe in standardization we are also implementing [OpenFeature](https://github.com/open-feature) providers to interact with this API in the language of your choice.
_(OpenFeature is still at an early stage, so not all languages are supported and expect some changes in the future)_
For now, we have providers for:
@@ -275,7 +275,7 @@ For now, we have providers for:
|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Go | [Go Provider](https://github.com/open-feature/go-sdk-contrib/tree/main/providers/go-feature-flag) | [![version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fproxy.golang.org%2Fgithub.com%2Fopen-feature%2Fgo-sdk-contrib%2Fproviders%2Fgo-feature-flag%2F%40latest&query=%24.Version&label=GO&color=blue&style=flat-square&logo=golang)](https://github.com/open-feature/go-sdk-contrib/tree/main/providers/go-feature-flag) |
| Java / Kotlin (server) | [Java Provider](https://github.com/open-feature/java-sdk-contrib/tree/main/providers/go-feature-flag) | [![version](https://img.shields.io/maven-central/v/dev.openfeature.contrib.providers/go-feature-flag?color=blue&style=flat-square&logo=java)](https://central.sonatype.com/artifact/dev.openfeature.contrib.providers/go-feature-flag) |
-| Android / Kotlin (client) | [Kotlin Provider](openfeature/providers/kotlin-provider) | [![version](https://img.shields.io/maven-central/v/org.gofeatureflag.openfeature/gofeatureflag-kotlin-provider?color=blue&style=flat-square&logo=android)](https://central.sonatype.com/artifact/org.gofeatureflag.openfeature/gofeatureflag-kotlin-provider) |
+| Android / Kotlin (client) | [Kotlin Provider](openfeature/providers/kotlin-provider) | [![version](https://img.shields.io/maven-central/v/org.gofeatureflag.openfeature/gofeatureflag-kotlin-provider?color=blue&style=flat-square&logo=android)](https://central.sonatype.com/artifact/org.gofeatureflag.openfeature/gofeatureflag-kotlin-provider) |
| Javascript/Typescript (server) | [Server Provider](https://github.com/open-feature/js-sdk-contrib/tree/main/libs/providers/go-feature-flag) | [![version](https://img.shields.io/npm/v/%40openfeature%2Fgo-feature-flag-provider?color=blue&style=flat-square&logo=npm)](https://www.npmjs.com/package/@openfeature/go-feature-flag-provider) |
| Javascript/Typescript (client) | [Client Provider](https://github.com/open-feature/js-sdk-contrib/tree/main/libs/providers/go-feature-flag-web) | [![version](https://img.shields.io/npm/v/%40openfeature%2Fgo-feature-flag-web-provider?color=blue&style=flat-square&logo=npm)](https://www.npmjs.com/package/@openfeature/go-feature-flag-web-provider) |
| Python | [Python Provider](openfeature/providers/python-provider) | [![version](https://img.shields.io/pypi/v/gofeatureflag-python-provider?color=blue&style=flat-square&logo=pypi)](https://pypi.org/project/gofeatureflag-python-provider/) |
@@ -283,11 +283,11 @@ For now, we have providers for:
| Ruby | [Ruby Provider](https://github.com/open-feature/ruby-sdk-contrib/tree/main/providers/openfeature-go-feature-flag-provider) | [![version](https://img.shields.io/gem/v/openfeature-go-feature-flag-provider?color=blue&style=flat-square&logo=ruby)](https://rubygems.org/gems/openfeature-go-feature-flag-provider) |
| Swift | [Swift Provider](https://github.com/go-feature-flag/openfeature-swift-provider) | [![version](https://img.shields.io/github/v/release/go-feature-flag/openfeature-swift-provider?label=Swift&display_name=tag&style=flat-square&logo=Swift)](https://github.com/go-feature-flag/openfeature-swift-provider) |
| PHP | [PHP Provider](https://github.com/open-feature/php-sdk-contrib/tree/main/providers/GoFeatureFlag) | [![version](https://img.shields.io/packagist/v/open-feature/go-feature-flag-provider?logo=php&color=blue&style=flat-square)](https://packagist.org/packages/open-feature/go-feature-flag-provider) |
-
+
## Where do I store my flags file?
-The module supports different ways of retrieving the flag file.
+The module supports different ways of retrieving the flag file.
The available retrievers are:
- **GitHub**
- **GitLab**
@@ -309,7 +309,7 @@ _[See the full list and more information.](https://gofeatureflag.org/docs/config
Your file should be a `YAML`, `JSON` or `TOML` file with a list of flags *(examples: [`YAML`](testdata/flag-config.yaml), [`JSON`](testdata/flag-config.json), [`TOML`](testdata/flag-config.toml))*.
-The easiest way to create your configuration file is to use **GO Feature Flag Editor** available at https://editor.gofeatureflag.org.
+The easiest way to create your configuration file is to use **GO Feature Flag Editor** available at https://editor.gofeatureflag.org.
If you prefer to do it manually please follow the instruction below.
**A flag configuration looks like this:**
@@ -455,20 +455,20 @@ For detailed information on the fields required to create a flag, please refer t
The query format is based on the [`nikunjy/rules`](https://github.com/nikunjy/rules) library.
-All the operations can be written in capitalized or lowercase (ex: `eq` or `EQ` can be used).
+All the operations can be written in capitalized or lowercase (ex: `eq` or `EQ` can be used).
Logical Operations supported are `AND` `OR`.
Compare Expression and their definitions (`a|b` means you can use either one of the two `a` or `b`):
```
-eq|==: equals to
+eq|==: equals to
ne|!=: not equals to
-lt|<: less than
+lt|<: less than
gt|>: greater than
le|<=: less than equal to
-ge|>=: greater than equal to
-co: contains
-sw: starts with
+ge|>=: greater than equal to
+co: contains
+sw: starts with
ew: ends with
in: in a list
pr: present
@@ -487,8 +487,8 @@ When using GO Feature Flag, it's often necessary to personalize the experience f
For instance, GO Feature Flag ensures that in cases where a feature is being rolled out to a percentage of users, based on the targeting key, they will see the same variation each time they encounter the feature flag.
-The targeting key is a fundamental part of the evaluation context because it directly affects the determination of which feature variant is served to a particular user, and it maintains that continuity over time. To do so GO Feature Flag to do a hash to define if the flag can apply to this evaluation context or not.
-**We recommend using a hash if possible.**
+The targeting key is a fundamental part of the evaluation context because it directly affects the determination of which feature variant is served to a particular user, and it maintains that continuity over time. To do so GO Feature Flag to do a hash to define if the flag can apply to this evaluation context or not.
+**We recommend using a hash if possible.**
Feature flag targeting and rollouts are all determined by the user you pass to your evaluation calls.
@@ -499,7 +499,7 @@ In some cases, you might need to _bucket_ users based on a different key, e.g. a
This can be achieved by defining the `bucketingKey` field in the flag configuration. When present, the value corresponding to the `bucketingKey` will be extracted from the attributes, and that value used for hashing and determining the outcome in place of the `targetingKey`.
## Variations
-Variations are the different values possible for a feature flag.
+Variations are the different values possible for a feature flag.
GO Feature Flag can manage more than just `boolean` values; the value of your flag can be any of the following types:
- `bool`
- `int`
@@ -519,7 +519,7 @@ Variation methods take the feature **flag key**, an **evaluation context**, and
**Why do we need a default value?** If we have any error during the evaluation of the flag, we will return the default value, you will always get a value return from the function and we will never throw an error.
-In the example, if the flag `your.feature.key` does not exist, the result will be `false`.
+In the example, if the flag `your.feature.key` does not exist, the result will be `false`.
Note that the result will always provide a usable value.
## Rollout
@@ -551,7 +551,7 @@ Available notifiers are:
- **Microsoft Teams**
## Export data
-**GO Feature Flag** allows you to export data about the usage of your flags.
+**GO Feature Flag** allows you to export data about the usage of your flags.
It collects all variation events and can save these events in several locations:
- **Local file** *- create local files with the variation usages.*
@@ -563,7 +563,7 @@ It collects all variation events and can save these events in several locations:
- **AWS SQS** *- export your variation usages by sending events to SQS.*
- **Google PubSub** *- export your variation usages by publishing events to PubSub topic.*
-Currently, we are supporting only feature events.
+Currently, we are supporting only feature events.
It represents individual flag evaluations and is considered "full fidelity" events.
**An example feature event below:**
@@ -591,7 +591,7 @@ A command line tool is available to help you lint your configuration file: [go-f
This project welcomes contributions from the community. If you're interested in contributing, see the [contributors' guide](CONTRIBUTING.md) for some helpful tips.
## Community meetings
-Since everyone's voice is important we want to hear back from the community.
+Since everyone's voice is important we want to hear back from the community.
For this reason, we are launching a community meeting every 2 weeks and it is the perfect place to discuss the future of GO Feature Flag and help you use it at full potential.
| Name | Meeting Time | Meeting Notes | Discussions |
@@ -621,4 +621,4 @@ These are our really cool sponsors!
If you are using `go-feature-flag`, we encourage you to include your company's name in this list. This simple act significantly boosts the project's visibility and credibility, making a substantial contribution to its advancement. To do so, kindly add yourself to [adopters](./ADOPTERS.md).
-Here is the list of [adopters](./ADOPTERS.md).
+Here is the list of [adopters](./ADOPTERS.md).
\ No newline at end of file
diff --git a/cmd/relayproxy/config/retriever.go b/cmd/relayproxy/config/retriever.go
index 24c86694df5c..c494be0474a7 100644
--- a/cmd/relayproxy/config/retriever.go
+++ b/cmd/relayproxy/config/retriever.go
@@ -70,14 +70,8 @@ func (c *RetrieverConf) IsValid() error {
if c.Kind == RedisRetriever {
return c.validateRedisRetriever()
}
- if c.Kind == AzBlobStorageRetriever && c.AccountName == "" {
- return fmt.Errorf("invalid retriever: no \"accountName\" property found for kind \"%s\"", c.Kind)
- }
- if c.Kind == AzBlobStorageRetriever && c.Container == "" {
- return fmt.Errorf("invalid retriever: no \"container\" property found for kind \"%s\"", c.Kind)
- }
- if c.Kind == AzBlobStorageRetriever && c.Object == "" {
- return fmt.Errorf("invalid retriever: no \"object\" property found for kind \"%s\"", c.Kind)
+ if c.Kind == AzBlobStorageRetriever {
+ return c.validateAzBlobStorageRetriever()
}
return nil
}
@@ -125,6 +119,19 @@ func (c *RetrieverConf) validateRedisRetriever() error {
return nil
}
+func (c *RetrieverConf) validateAzBlobStorageRetriever() error {
+ if c.AccountName == "" {
+ return fmt.Errorf("invalid retriever: no \"accountName\" property found for kind \"%s\"", c.Kind)
+ }
+ if c.Container == "" {
+ return fmt.Errorf("invalid retriever: no \"container\" property found for kind \"%s\"", c.Kind)
+ }
+ if c.Object == "" {
+ return fmt.Errorf("invalid retriever: no \"object\" property found for kind \"%s\"", c.Kind)
+ }
+ return nil
+}
+
// RetrieverKind is an enum containing all accepted Retriever kind
type RetrieverKind string
diff --git a/cmd/relayproxy/config/retriever_test.go b/cmd/relayproxy/config/retriever_test.go
index 231af2ef5040..d831abedf8ca 100644
--- a/cmd/relayproxy/config/retriever_test.go
+++ b/cmd/relayproxy/config/retriever_test.go
@@ -123,14 +123,15 @@ func TestRetrieverConf_IsValid(t *testing.T) {
errValue: "invalid retriever: no \"bucket\" property found for kind \"googleStorage\"",
},
{
- name: "valid azureBlobStorage",
+ name: "kind azureBlobStorage without object",
fields: config.RetrieverConf{
Kind: "azureBlobStorage",
Container: "testcontainer",
- Object: "flag-config.yaml",
AccountName: "devstoreaccount1",
AccountKey: "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq",
},
+ wantErr: true,
+ errValue: "invalid retriever: no \"object\" property found for kind \"azureBlobStorage\"",
},
{
name: "kind azureBlobStorage without accountName",
@@ -140,6 +141,8 @@ func TestRetrieverConf_IsValid(t *testing.T) {
Object: "flag-config.yaml",
AccountKey: "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq",
},
+ wantErr: true,
+ errValue: "invalid retriever: no \"accountName\" property found for kind \"azureBlobStorage\"",
},
{
name: "kind azureBlobStorage without container",
@@ -149,6 +152,8 @@ func TestRetrieverConf_IsValid(t *testing.T) {
AccountName: "devstoreaccount1",
AccountKey: "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq",
},
+ wantErr: true,
+ errValue: "invalid retriever: no \"container\" property found for kind \"azureBlobStorage\"",
},
{
name: "valid s3",
diff --git a/cmd/relayproxy/service/gofeatureflag.go b/cmd/relayproxy/service/gofeatureflag.go
index b9582bf0039e..4cf2ba69eadb 100644
--- a/cmd/relayproxy/service/gofeatureflag.go
+++ b/cmd/relayproxy/service/gofeatureflag.go
@@ -26,7 +26,7 @@ import (
"github.com/thomaspoignant/go-feature-flag/notifier/slacknotifier"
"github.com/thomaspoignant/go-feature-flag/notifier/webhooknotifier"
"github.com/thomaspoignant/go-feature-flag/retriever"
- azblobretriever "github.com/thomaspoignant/go-feature-flag/retriever/azblobstorageretriever"
+ "github.com/thomaspoignant/go-feature-flag/retriever/azblobstorageretriever"
"github.com/thomaspoignant/go-feature-flag/retriever/bitbucketretriever"
"github.com/thomaspoignant/go-feature-flag/retriever/fileretriever"
"github.com/thomaspoignant/go-feature-flag/retriever/gcstorageretriever"
diff --git a/retriever/azblobstorageretriever/README.md b/retriever/azblobstorageretriever/README.md
index 4302a2e621d3..213c0e137b7a 100644
--- a/retriever/azblobstorageretriever/README.md
+++ b/retriever/azblobstorageretriever/README.md
@@ -1,9 +1,106 @@
-# Redis retriever
-This retriever is used to retrieve data from your Azure Blob Storage Container.
-
-## How to use?
-Provide the following fields:
-- Azure Account Name
-- Azure Account Key (Optional if you're authenticating with Microsoft Entra ID)
-- Azure Container Name
-- Azure Blob Name
+# Azure Blob Storage Feature Flag Retriever
+
+This retriever is used to retrieve data from a Container on Azure Blob Storage.
+
+## Installation
+
+```bash
+go get github.com/thomaspoignant/go-feature-flag/retriever/azblobstorageretriever
+```
+
+## Usage
+
+### Configuration
+
+Create a `Retriever` struct with the following fields:
+
+- `Container`: Name of the Azure Blob Storage container
+- `AccountName`: Azure Storage Account Name
+- `AccountKey`: (Optional) Storage Account Key
+- `ServiceURL`: (Optional) Custom service URL
+- `Object`: Name of the feature flag file in the container
+
+### Authentication Methods
+
+#### 1. Shared Key Authentication
+
+```go
+retriever := &azblobretriever.Retriever{
+ Container: "your-container",
+ AccountName: "your-account-name",
+ AccountKey: "your-account-key",
+ Object: "feature-flags.json",
+}
+```
+
+#### 2. Microsoft Entra ID (Recommended)
+
+```go
+retriever := &azblobretriever.Retriever{
+ Container: "your-container",
+ AccountName: "your-account-name",
+ Object: "feature-flags.json",
+}
+```
+
+### Retrieving Feature Flags
+
+```go
+package main
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "time"
+
+ "github.com/thomaspoignant/go-feature-flag/retriever/azblobstorageretriever"
+)
+
+func main() {
+ retriever := &azblobretriever.Retriever{
+ Container: "feature-flags",
+ AccountName: "mystorageaccount",
+ AccountKey: "your-account-key",
+ Object: "flags.json",
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+ defer cancel()
+
+ err := retriever.Init(context.Background(), nil)
+ if err != nil {
+ log.Fatalf("Failed to initialize retriever:", err)
+ }
+
+ data, err := retriever.Retrieve(ctx)
+ if err != nil {
+ log.Fatalf("Failed to retrieve feature flags: %v", err)
+ }
+
+ retriever.Shutdown()
+
+ fmt.Println("Retrieved feature flags:")
+ fmt.Println(string(data))
+}
+```
+
+## Key Features
+
+- Supports both shared key and default Azure credential authentication
+- Automatic retry mechanism for blob downloads
+- Flexible configuration with optional custom service URL
+
+## Error Handling
+
+The `Retrieve` method returns an error if:
+- `AccountName` is empty
+- `Container` or `Object` is not specified
+- There's an issue initializing the Azure client.
+- There's a problem downloading or reading the file from Azure Blob Storage.
+
+## Best Practices
+
+- **Security** Never hard-code your `AccountKey` in your source code. Use environment variables or a secure secret management system.
+- **Error Handling**: Always check for errors returned by the `Retrieve` method.
+- **Context**: Use a context with timeout for better control over the retrieval process.
diff --git a/retriever/azblobstorageretriever/retriever.go b/retriever/azblobstorageretriever/retriever.go
index 31e94cc7e9d2..26ceb64f4501 100644
--- a/retriever/azblobstorageretriever/retriever.go
+++ b/retriever/azblobstorageretriever/retriever.go
@@ -7,6 +7,8 @@ import (
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
+ "github.com/thomaspoignant/go-feature-flag/retriever"
+ "github.com/thomaspoignant/go-feature-flag/utils/fflog"
)
type Retriever struct {
@@ -24,38 +26,76 @@ type Retriever struct {
// Object is the name of your file in your container.
Object string
+
+ // client is a pointer to an Azure Blob Storage client.
+ // It provides access to Azure Blob Storage services for operations like
+ // creating, reading, updating, and deleting blobs.
+ client *azblob.Client
+ status retriever.Status
}
-func (f *Retriever) initializeAzureClient() (*azblob.Client, error) {
- url := fmt.Sprintf("https://%s.blob.core.windows.net/", f.AccountName)
- if f.ServiceURL != "" {
- url = f.ServiceURL
+func (r *Retriever) Init(_ context.Context, _ *fflog.FFLogger) error {
+ if r.AccountName == "" {
+ return fmt.Errorf("unable to connect to Azure Blob Storage, \"AccountName\" cannot be empty")
+ }
+
+ url := r.ServiceURL
+ if url == "" {
+ url = fmt.Sprintf("https://%s.blob.core.windows.net/", r.AccountName)
}
- if f.AccountKey == "" {
- cred, err := azidentity.NewDefaultAzureCredential(nil)
+
+ var client *azblob.Client
+ var err error
+
+ if r.AccountKey == "" {
+ var cred *azidentity.DefaultAzureCredential
+ cred, err = azidentity.NewDefaultAzureCredential(nil)
if err != nil {
- return nil, err
+ r.status = retriever.RetrieverError
+ return err
}
- return azblob.NewClient(url, cred, nil)
+ client, err = azblob.NewClient(url, cred, nil)
+ } else {
+ var cred *azblob.SharedKeyCredential
+ cred, err = azblob.NewSharedKeyCredential(r.AccountName, r.AccountKey)
+ if err != nil {
+ r.status = retriever.RetrieverError
+ return err
+ }
+ client, err = azblob.NewClientWithSharedKeyCredential(url, cred, nil)
}
- cred, err := azblob.NewSharedKeyCredential(f.AccountName, f.AccountKey)
+
if err != nil {
- return nil, err
+ r.status = retriever.RetrieverError
+ return err
}
- return azblob.NewClientWithSharedKeyCredential(url, cred, nil)
+
+ r.client = client
+ r.status = retriever.RetrieverReady
+ return nil
+}
+
+func (r *Retriever) Shutdown(_ context.Context) error {
+ r.status = retriever.RetrieverNotReady
+ r.client = nil
+ return nil
+}
+
+func (r *Retriever) Status() retriever.Status {
+ return r.status
}
func (r *Retriever) Retrieve(ctx context.Context) ([]byte, error) {
- if r.Object == "" || r.Container == "" {
- return nil, fmt.Errorf("missing mandatory information filePath=%s, repositorySlug=%s", r.Object, r.Container)
+ if r.client == nil {
+ r.status = retriever.RetrieverError
+ return nil, fmt.Errorf("client is not initialized")
}
- client, err := r.initializeAzureClient()
- if err != nil {
- return nil, err
+ if r.Object == "" || r.Container == "" {
+ return nil, fmt.Errorf("missing mandatory information filePath=%s, repositorySlug=%s", r.Object, r.Container)
}
- fileStream, err := client.DownloadStream(ctx, r.Container, r.Object, nil)
+ fileStream, err := r.client.DownloadStream(ctx, r.Container, r.Object, nil)
if err != nil {
return nil, err
}
diff --git a/retriever/azblobstorageretriever/retriever_test.go b/retriever/azblobstorageretriever/retriever_test.go
index 7ec55b5c963b..ac500bef76d5 100644
--- a/retriever/azblobstorageretriever/retriever_test.go
+++ b/retriever/azblobstorageretriever/retriever_test.go
@@ -1,7 +1,7 @@
//go:build docker
// +build docker
-package azblobretriever
+package azblobretriever_test
import (
"context"