Support custom Azure publish endpoint

This commit is contained in:
Chuan Liu
2022-04-21 17:04:15 -07:00
committed by Benj Fassbind
parent d955b06f03
commit 152538ccc1
8 changed files with 45 additions and 11 deletions

View File

@@ -45,3 +45,4 @@ List of contributors, in chronological order:
* Lorenzo Bolla (https://github.com/lbolla)
* Benj Fassbind (https://github.com/randombenj)
* Markus Muellner (https://github.com/mmianl)
* Chuan Liu (https://github.com/chuan)

View File

@@ -5,6 +5,7 @@ import (
"encoding/hex"
"fmt"
"io"
"net"
"net/http"
"net/url"
"os"
@@ -29,20 +30,47 @@ var (
_ aptly.PublishedStorage = (*PublishedStorage)(nil)
)
func isEmulatorEndpoint(endpoint string) bool {
if h, _, err := net.SplitHostPort(endpoint); err == nil {
endpoint = h
}
if endpoint == "localhost" {
return true
}
// For IPv6, there could be case where SplitHostPort fails for cannot finding port.
// In this case, eliminate the '[' and ']' in the URL.
// For details about IPv6 URL, please refer to https://tools.ietf.org/html/rfc2732
if endpoint[0] == '[' && endpoint[len(endpoint)-1] == ']' {
endpoint = endpoint[1 : len(endpoint)-1]
}
return net.ParseIP(endpoint) != nil
}
// NewPublishedStorage creates published storage from Azure storage credentials
func NewPublishedStorage(accountName, accountKey, container, prefix string) (*PublishedStorage, error) {
func NewPublishedStorage(accountName, accountKey, container, prefix, endpoint string) (*PublishedStorage, error) {
credential, err := azblob.NewSharedKeyCredential(accountName, accountKey)
if err != nil {
return nil, err
}
containerURL, err := url.Parse(fmt.Sprintf("https://%s.blob.core.windows.net/%s", accountName, container))
if endpoint == "" {
endpoint = "blob.core.windows.net"
}
var url *url.URL
if isEmulatorEndpoint(endpoint) {
url, err = url.Parse(fmt.Sprintf("http://%s/%s/%s", endpoint, accountName, container))
} else {
url, err = url.Parse(fmt.Sprintf("https://%s.%s/%s", accountName, endpoint, container))
}
if err != nil {
return nil, err
}
containerURL := azblob.NewContainerURL(*url, azblob.NewPipeline(credential, azblob.PipelineOptions{}))
result := &PublishedStorage{
container: azblob.NewContainerURL(*containerURL, azblob.NewPipeline(credential, azblob.PipelineOptions{})),
container: containerURL,
prefix: prefix,
}

View File

@@ -15,8 +15,8 @@ import (
)
type PublishedStorageSuite struct {
accountName, accountKey string
storage, prefixedStorage *PublishedStorage
accountName, accountKey, endpoint string
storage, prefixedStorage *PublishedStorage
}
var _ = Suite(&PublishedStorageSuite{})
@@ -55,6 +55,7 @@ func (s *PublishedStorageSuite) SetUpSuite(c *C) {
println(" 2. AZURE_STORAGE_ACCESS_KEY")
c.Skip("AZURE_STORAGE_ACCESS_KEY not set.")
}
s.endpoint = os.Getenv("AZURE_STORAGE_ENDPOINT")
}
func (s *PublishedStorageSuite) SetUpTest(c *C) {
@@ -63,13 +64,13 @@ func (s *PublishedStorageSuite) SetUpTest(c *C) {
var err error
s.storage, err = NewPublishedStorage(s.accountName, s.accountKey, container, "")
s.storage, err = NewPublishedStorage(s.accountName, s.accountKey, container, "", s.endpoint)
c.Assert(err, IsNil)
cnt := s.storage.container
_, err = cnt.Create(context.Background(), azblob.Metadata{}, azblob.PublicAccessContainer)
c.Assert(err, IsNil)
s.prefixedStorage, err = NewPublishedStorage(s.accountName, s.accountKey, container, prefix)
s.prefixedStorage, err = NewPublishedStorage(s.accountName, s.accountKey, container, prefix, s.endpoint)
c.Assert(err, IsNil)
}
@@ -249,7 +250,7 @@ func (s *PublishedStorageSuite) TestRemoveDirsPlus(c *C) {
list, err := s.storage.Filelist("")
c.Check(err, IsNil)
c.Check(list, DeepEquals, []string{"a", "b", "c", "lala/a b", "lala/a+b", "lala/c", "testa"})
c.Check(list, DeepEquals, []string{"a", "b", "c", "lala/a b", "lala/a+b", "lala/c", "testa"})
}
func (s *PublishedStorageSuite) TestRenameFile(c *C) {
@@ -354,7 +355,7 @@ func (s *PublishedStorageSuite) TestSymLink(c *C) {
c.Check(err, IsNil)
c.Check(link, Equals, "a/b")
c.Skip("copy not available in s3test")
c.Skip("copy not available in azure test")
}
func (s *PublishedStorageSuite) TestFileExists(c *C) {

View File

@@ -417,7 +417,7 @@ func (context *AptlyContext) GetPublishedStorage(name string) aptly.PublishedSto
var err error
publishedStorage, err = azure.NewPublishedStorage(
params.AccountName, params.AccountKey, params.Container, params.Prefix)
params.AccountName, params.AccountKey, params.Container, params.Prefix, params.Endpoint)
if err != nil {
Fatal(err)
}

View File

@@ -104,6 +104,7 @@ Configuration file is stored in JSON format (default values shown below):
"accountKey": "",
"container": "repo",
"prefix": ""
"endpoint": "blob.core.windows.net"
}
}
}

View File

@@ -96,6 +96,7 @@ Configuration file is stored in JSON format (default values shown below):
"accountKey": "",
"container": "repo",
"prefix": ""
"endpoint": "blob.core.windows.net"
}
}
}

View File

@@ -82,6 +82,7 @@ type AzurePublishRoot struct {
AccountKey string `json:"accountKey"`
Container string `json:"container"`
Prefix string `json:"prefix"`
Endpoint string `json:"endpoint"`
}
// Config is configuration for aptly, shared by all modules

View File

@@ -124,7 +124,8 @@ func (s *ConfigSuite) TestSaveConfig(c *C) {
" \"accountName\": \"\",\n"+
" \"accountKey\": \"\",\n"+
" \"container\": \"repo\",\n"+
" \"prefix\": \"\"\n"+
" \"prefix\": \"\",\n"+
" \"endpoint\": \"\"\n"+
" }\n"+
" },\n"+
" \"AsyncAPI\": false,\n"+