Merge pull request #2788 from Lucretius/azure-blob-logs
Add support for primary store of Azure blob
This commit is contained in:
commit
d581dab302
6 changed files with 159 additions and 10 deletions
|
@ -49,6 +49,7 @@ type (
|
||||||
|
|
||||||
Authn Authentication
|
Authn Authentication
|
||||||
Agent Agent
|
Agent Agent
|
||||||
|
AzureBlob AzureBlob
|
||||||
Cron Cron
|
Cron Cron
|
||||||
Cloning Cloning
|
Cloning Cloning
|
||||||
Database Database
|
Database Database
|
||||||
|
@ -362,6 +363,13 @@ type (
|
||||||
PathStyle bool `envconfig:"DRONE_S3_PATH_STYLE"`
|
PathStyle bool `envconfig:"DRONE_S3_PATH_STYLE"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//AzureBlob providers the storage configuration.
|
||||||
|
AzureBlob struct {
|
||||||
|
ContainerName string `envconfig:"DRONE_AZURE_BLOB_CONTAINER_NAME"`
|
||||||
|
StorageAccountName string `envconfig:"DRONE_AZURE_STORAGE_ACCOUNT_NAME"`
|
||||||
|
StorageAccessKey string `envconfig:"DRONE_AZURE_STORAGE_ACCESS_KEY"`
|
||||||
|
}
|
||||||
|
|
||||||
// HTTP provides http configuration.
|
// HTTP provides http configuration.
|
||||||
HTTP struct {
|
HTTP struct {
|
||||||
AllowedHosts []string `envconfig:"DRONE_HTTP_ALLOWED_HOSTS"`
|
AllowedHosts []string `envconfig:"DRONE_HTTP_ALLOWED_HOSTS"`
|
||||||
|
|
|
@ -81,17 +81,25 @@ func provideBuildStore(db *db.DB) core.BuildStore {
|
||||||
// provideLogStore is a Wire provider function that provides a
|
// provideLogStore is a Wire provider function that provides a
|
||||||
// log datastore, configured from the environment.
|
// log datastore, configured from the environment.
|
||||||
func provideLogStore(db *db.DB, config config.Config) core.LogStore {
|
func provideLogStore(db *db.DB, config config.Config) core.LogStore {
|
||||||
if config.S3.Bucket == "" {
|
|
||||||
return logs.New(db)
|
|
||||||
}
|
|
||||||
s := logs.New(db)
|
s := logs.New(db)
|
||||||
p := logs.NewS3Env(
|
if config.S3.Bucket != "" {
|
||||||
config.S3.Bucket,
|
p := logs.NewS3Env(
|
||||||
config.S3.Prefix,
|
config.S3.Bucket,
|
||||||
config.S3.Endpoint,
|
config.S3.Prefix,
|
||||||
config.S3.PathStyle,
|
config.S3.Endpoint,
|
||||||
)
|
config.S3.PathStyle,
|
||||||
return logs.NewCombined(p, s)
|
)
|
||||||
|
return logs.NewCombined(p, s)
|
||||||
|
}
|
||||||
|
if config.AzureBlob.ContainerName != "" {
|
||||||
|
p := logs.NewAzureBlobEnv(
|
||||||
|
config.AzureBlob.ContainerName,
|
||||||
|
config.AzureBlob.StorageAccountName,
|
||||||
|
config.AzureBlob.StorageAccessKey,
|
||||||
|
)
|
||||||
|
return logs.NewCombined(p, s)
|
||||||
|
}
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// provideStageStore is a Wire provider function that provides a
|
// provideStageStore is a Wire provider function that provides a
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -3,6 +3,7 @@ module github.com/drone/drone
|
||||||
require (
|
require (
|
||||||
docker.io/go-docker v1.0.0
|
docker.io/go-docker v1.0.0
|
||||||
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e
|
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e
|
||||||
|
github.com/Azure/azure-storage-blob-go v0.7.0
|
||||||
github.com/Microsoft/go-winio v0.4.11
|
github.com/Microsoft/go-winio v0.4.11
|
||||||
github.com/asaskevich/govalidator v0.0.0-20180315120708-ccb8e960c48f
|
github.com/asaskevich/govalidator v0.0.0-20180315120708-ccb8e960c48f
|
||||||
github.com/aws/aws-sdk-go v1.15.57
|
github.com/aws/aws-sdk-go v1.15.57
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -2,6 +2,10 @@ docker.io/go-docker v1.0.0 h1:VdXS/aNYQxyA9wdLD5z8Q8Ro688/hG8HzKxYVEVbE6s=
|
||||||
docker.io/go-docker v1.0.0/go.mod h1:7tiAn5a0LFmjbPDbyTPOaTTOuG1ZRNXdPA6RvKY+fpY=
|
docker.io/go-docker v1.0.0/go.mod h1:7tiAn5a0LFmjbPDbyTPOaTTOuG1ZRNXdPA6RvKY+fpY=
|
||||||
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e h1:rl2Aq4ZODqTDkeSqQBy+fzpZPamacO1Srp8zq7jf2Sc=
|
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e h1:rl2Aq4ZODqTDkeSqQBy+fzpZPamacO1Srp8zq7jf2Sc=
|
||||||
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e/go.mod h1:Xa6lInWHNQnuWoF0YPSsx+INFA9qk7/7pTjwb3PInkY=
|
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e/go.mod h1:Xa6lInWHNQnuWoF0YPSsx+INFA9qk7/7pTjwb3PInkY=
|
||||||
|
github.com/Azure/azure-pipeline-go v0.2.1 h1:OLBdZJ3yvOn2MezlWvbrBMTEUQC72zAftRZOMdj5HYo=
|
||||||
|
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
|
||||||
|
github.com/Azure/azure-storage-blob-go v0.7.0 h1:MuueVOYkufCxJw5YZzF842DY2MBsp+hLuh2apKY0mck=
|
||||||
|
github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4=
|
||||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
@ -178,6 +182,8 @@ github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uP
|
||||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||||
github.com/hashicorp/go-retryablehttp v0.0.0-20180718195005-e651d75abec6 h1:qCv4319q2q7XKn0MQbi8p37hsJ+9Xo8e6yojA73JVxk=
|
github.com/hashicorp/go-retryablehttp v0.0.0-20180718195005-e651d75abec6 h1:qCv4319q2q7XKn0MQbi8p37hsJ+9Xo8e6yojA73JVxk=
|
||||||
github.com/hashicorp/go-retryablehttp v0.0.0-20180718195005-e651d75abec6/go.mod h1:fXcdFsQoipQa7mwORhKad5jmDCeSy/RCGzWA08PO0lM=
|
github.com/hashicorp/go-retryablehttp v0.0.0-20180718195005-e651d75abec6/go.mod h1:fXcdFsQoipQa7mwORhKad5jmDCeSy/RCGzWA08PO0lM=
|
||||||
|
github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI=
|
||||||
|
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||||
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/nomad v0.0.0-20190125003214-134391155854 h1:L7WhLZt2ory/kQWxqkMwOiBpIoa4BWoadN7yx8LHEtk=
|
github.com/hashicorp/nomad v0.0.0-20190125003214-134391155854 h1:L7WhLZt2ory/kQWxqkMwOiBpIoa4BWoadN7yx8LHEtk=
|
||||||
|
@ -200,6 +206,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
|
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 h1:HfxbT6/JcvIljmERptWhwa8XzP7H3T+Z2N26gTsaDaA=
|
||||||
|
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
|
||||||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
|
||||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
|
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
|
||||||
|
|
100
store/logs/azureblob.go
Normal file
100
store/logs/azureblob.go
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||||
|
// Use of this source code is governed by the Drone Non-Commercial License
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build !oss
|
||||||
|
|
||||||
|
package logs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/Azure/azure-storage-blob-go/azblob"
|
||||||
|
"github.com/drone/drone/core"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewAzureBlobEnv returns a new Azure blob log store.
|
||||||
|
func NewAzureBlobEnv(containerName, storageAccountName, storageAccessKey string) core.LogStore {
|
||||||
|
return &azureBlobStore{
|
||||||
|
containerName: containerName,
|
||||||
|
storageAccountName: storageAccountName,
|
||||||
|
storageAccessKey: storageAccessKey,
|
||||||
|
containerURL: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type azureBlobStore struct {
|
||||||
|
containerName string
|
||||||
|
storageAccountName string
|
||||||
|
storageAccessKey string
|
||||||
|
containerURL *azblob.ContainerURL
|
||||||
|
}
|
||||||
|
|
||||||
|
func (az *azureBlobStore) Find(ctx context.Context, step int64) (io.ReadCloser, error) {
|
||||||
|
err := az.getContainerURL()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
blobURL := az.containerURL.NewBlockBlobURL(fmt.Sprintf("%d", step))
|
||||||
|
out, err := blobURL.Download(ctx, 0, azblob.CountToEnd, azblob.BlobAccessConditions{}, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out.Body(azblob.RetryReaderOptions{}), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (az *azureBlobStore) Create(ctx context.Context, step int64, r io.Reader) error {
|
||||||
|
err := az.getContainerURL()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
opts := &azblob.UploadStreamToBlockBlobOptions{
|
||||||
|
BufferSize: 4 * 1024 * 1024,
|
||||||
|
MaxBuffers: 5,
|
||||||
|
}
|
||||||
|
blobURL := az.containerURL.NewBlockBlobURL(fmt.Sprintf("%d", step))
|
||||||
|
_, err = azblob.UploadStreamToBlockBlob(ctx, r, blobURL, *opts)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (az *azureBlobStore) Update(ctx context.Context, step int64, r io.Reader) error {
|
||||||
|
return az.Create(ctx, step, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (az *azureBlobStore) Delete(ctx context.Context, step int64) error {
|
||||||
|
err := az.getContainerURL()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
blobURL := az.containerURL.NewBlockBlobURL(fmt.Sprintf("%d", step))
|
||||||
|
_, err = blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionInclude, azblob.BlobAccessConditions{})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (az *azureBlobStore) getContainerURL() error {
|
||||||
|
if az.containerURL != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(az.storageAccountName) == 0 || len(az.storageAccessKey) == 0 {
|
||||||
|
return fmt.Errorf("Either the storage account or storage access key environment variable is not set")
|
||||||
|
}
|
||||||
|
credential, err := azblob.NewSharedKeyCredential(az.storageAccountName, az.storageAccessKey)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p := azblob.NewPipeline(credential, azblob.PipelineOptions{})
|
||||||
|
URL, err := url.Parse(fmt.Sprintf("https://%s.blob.core.windows.net/%s", az.storageAccountName, az.containerName))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
containerURL := azblob.NewContainerURL(*URL, p)
|
||||||
|
az.containerURL = &containerURL
|
||||||
|
return nil
|
||||||
|
}
|
24
store/logs/azureblob_oss.go
Normal file
24
store/logs/azureblob_oss.go
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright 2019 Drone IO, Inc.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// +build oss
|
||||||
|
|
||||||
|
package logs
|
||||||
|
|
||||||
|
import "github.com/drone/drone/core"
|
||||||
|
|
||||||
|
// New returns a zero value LogStore.
|
||||||
|
func NewAzureBlobEnv(containerName, storageAccountName, storageAccessKey string) core.LogStore {
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in a new issue