├── codecov.yml ├── .gitignore ├── charts └── minio │ ├── values.yaml │ ├── templates │ ├── minio-service-account.yaml │ ├── minio-user-secret.yaml │ ├── minio-service.yaml │ └── minio-deployment.yaml │ └── Chart.yaml ├── MAINTAINERS.md ├── CONTRIBUTING.md ├── _tests └── README.md ├── _docs ├── users.json └── README.md ├── boot_test.go ├── src ├── storage │ └── bucket_lister.go └── healthsrv │ ├── server.go │ ├── healthz_handler.go │ └── healthz_handler_test.go ├── rootfs ├── Dockerfile └── README.md ├── versioning.mk ├── glide.yaml ├── glide.lock ├── LICENSE ├── Makefile ├── DCO ├── boot.go └── README.md /codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | branch: master 3 | slug: "deis/minio" 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | rootfs/bin/minio 2 | rootfs/bin/boot 3 | vendor/ 4 | coverage.txt 5 | -------------------------------------------------------------------------------- /charts/minio/values.yaml: -------------------------------------------------------------------------------- 1 | org: "deisci" 2 | pull_policy: "Always" 3 | docker_tag: canary 4 | global: 5 | storage: minio 6 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | # Deis Maintainers 2 | 3 | This project is part of Deis. The official maintainers documentation is 4 | located [in the main project](https://github.com/deis/deis/blob/master/MAINTAINERS.md). 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | This project is part of Deis. You can find the latest contribution 4 | guidelines [at the Deis project](https://github.com/deis/deis/blob/master/CONTRIBUTING.md). 5 | 6 | -------------------------------------------------------------------------------- /_tests/README.md: -------------------------------------------------------------------------------- 1 | # Tests 2 | 3 | This directory is used for functional tests. 4 | 5 | The directory is prefixed with an underscore (`_tests`) to prevent Go 6 | tools from automatically running Go code found in this directory. 7 | -------------------------------------------------------------------------------- /charts/minio/templates/minio-service-account.yaml: -------------------------------------------------------------------------------- 1 | {{- if eq .Values.global.storage "minio" }} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: deis-minio 6 | labels: 7 | heritage: deis 8 | {{- end }} 9 | -------------------------------------------------------------------------------- /charts/minio/Chart.yaml: -------------------------------------------------------------------------------- 1 | name: minio 2 | home: https://github.com/deis/minio 3 | version: 4 | description: Minio Object Storage in Kubernetes, used by Deis Workflow. 5 | maintainers: 6 | - name: Deis Team 7 | email: engineering@deis.com 8 | -------------------------------------------------------------------------------- /charts/minio/templates/minio-user-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: minio-user 5 | labels: 6 | heritage: deis 7 | type: Opaque 8 | data: 9 | accesskey: OFRaUlkySlJXTVBUNlVNWFI2STU= 10 | secretkey: Z2JzdHJPdm90TU1jZzJzTWZHVWhBNWE2RXQvRUk1QUx0SUhzb2JZaw== 11 | -------------------------------------------------------------------------------- /charts/minio/templates/minio-service.yaml: -------------------------------------------------------------------------------- 1 | {{- if eq .Values.global.storage "minio" }} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: deis-minio 6 | labels: 7 | heritage: deis 8 | spec: 9 | ports: 10 | - name: s3 11 | port: 9000 12 | selector: 13 | app: deis-minio 14 | {{- end }} 15 | -------------------------------------------------------------------------------- /_docs/users.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "0.0.1", 3 | "Users": { 4 | "admin": { 5 | "name": "admin", 6 | "accessKeyId": "admin", 7 | "secretAccessKey": "pdG8Rpw0h8QtxybHsMHlkJtzJzZ2sC7b2cFBEgn+" 8 | }, 9 | "user": { 10 | "name": "user", 11 | "accessKeyId": "8TZRY2JRWMPT6UMXR6I5", 12 | "secretAccessKey": "gbstrOvotMMcg2sMfGUhA5a6Et/EI5ALtIHsobYk" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /boot_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestNewMinioClient(t *testing.T) { 8 | client, err := newMinioClient("localhost", "8095", "access_key", "access_secret_key", false) 9 | if err != nil { 10 | t.Fatalf("unexpected error creating minio client (%s)", err) 11 | } 12 | if client == nil { 13 | t.Fatalf("returned client was nil but not expected to be") 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/storage/bucket_lister.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import ( 4 | minio "github.com/minio/minio-go" 5 | ) 6 | 7 | // BucketLister is an interface that knows how to list buckets on object storage 8 | type BucketLister interface { 9 | ListBuckets() ([]minio.BucketInfo, error) 10 | } 11 | 12 | type fakeBucketLister struct { 13 | bucketInfos []minio.BucketInfo 14 | } 15 | 16 | func NewFakeBucketLister(buckets []minio.BucketInfo) BucketLister { 17 | return &fakeBucketLister{bucketInfos: buckets} 18 | } 19 | 20 | func (b *fakeBucketLister) ListBuckets() ([]minio.BucketInfo, error) { 21 | return b.bucketInfos, nil 22 | } 23 | -------------------------------------------------------------------------------- /rootfs/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM quay.io/deis/base:v0.3.6 2 | 3 | RUN adduser --system \ 4 | --shell /bin/bash \ 5 | --disabled-password \ 6 | --home /home/minio \ 7 | --group \ 8 | minio 9 | 10 | COPY . / 11 | 12 | RUN curl -f -SL https://dl.minio.io/client/mc/release/linux-amd64/archive/mc.OFFICIAL.2015-09-05T23-43-46Z -o /usr/bin/mc \ 13 | && chmod 755 /usr/bin/mc \ 14 | && mkdir /home/minio/.minio \ 15 | && chown minio:minio /home/minio/.minio 16 | ADD https://storage.googleapis.com/minio-mirror/linux-amd64/minio-2016-06-03T19-32-05Z /bin/minio 17 | RUN chmod 755 /bin/minio 18 | 19 | USER minio 20 | 21 | CMD ["/bin/boot"] 22 | -------------------------------------------------------------------------------- /src/healthsrv/server.go: -------------------------------------------------------------------------------- 1 | package healthsrv 2 | 3 | import ( 4 | "fmt" 5 | minio "github.com/minio/minio-go" 6 | "net/http" 7 | ) 8 | 9 | const ( 10 | DefaultHost = "0.0.0.0" 11 | DefaultPort = 8082 12 | ) 13 | 14 | // Start starts the healthcheck server on $host:$port and blocks. It only returns if the server fails, with the indicative error 15 | func Start(host string, port int, minioClient minio.CloudStorageClient) error { 16 | mux := http.NewServeMux() 17 | mux.Handle("/healthz", healthZHandler(minioClient)) 18 | 19 | hostStr := fmt.Sprintf("%s:%d", host, port) 20 | return http.ListenAndServe(hostStr, mux) 21 | } 22 | -------------------------------------------------------------------------------- /rootfs/README.md: -------------------------------------------------------------------------------- 1 | # RootFS 2 | 3 | This directory stores all files that should be copied to the rootfs of a 4 | Docker container. The files should be stored according to the correct 5 | directory structure of the destination container. For example: 6 | 7 | ``` 8 | rootfs/bin -> /bin 9 | rootfs/usr/local/share -> /usr/local/share 10 | ``` 11 | 12 | ## Dockerfile 13 | 14 | A Dockerfile in the rootfs is used to build the image. Where possible, 15 | compilation should not be done in this Dockerfile, since we are 16 | interested in deploying the smallest possible images. 17 | 18 | Example: 19 | 20 | ```Dockerfile 21 | FROM alpine:3.1 22 | 23 | COPY . / 24 | 25 | ENTRYPOINT ["/bin/boot"] 26 | ``` 27 | -------------------------------------------------------------------------------- /versioning.mk: -------------------------------------------------------------------------------- 1 | MUTABLE_VERSION ?= canary 2 | VERSION ?= git-$(shell git rev-parse --short HEAD) 3 | 4 | IMAGE := ${DEIS_REGISTRY}${IMAGE_PREFIX}/${SHORT_NAME}:${VERSION} 5 | MUTABLE_IMAGE := ${DEIS_REGISTRY}${IMAGE_PREFIX}/${SHORT_NAME}:${MUTABLE_VERSION} 6 | 7 | info: 8 | @echo "Build tag: ${VERSION}" 9 | @echo "Registry: ${DEIS_REGISTRY}" 10 | @echo "Immutable tag: ${IMAGE}" 11 | @echo "Mutable tag: ${MUTABLE_IMAGE}" 12 | 13 | .PHONY: docker-push 14 | docker-push: docker-immutable-push docker-mutable-push 15 | 16 | .PHONY: docker-immutable-push 17 | docker-immutable-push: 18 | docker push ${IMAGE} 19 | 20 | .PHONY: docker-mutable-push 21 | docker-mutable-push: 22 | docker push ${MUTABLE_IMAGE} 23 | -------------------------------------------------------------------------------- /glide.yaml: -------------------------------------------------------------------------------- 1 | package: github.com/deis/minio 2 | ignore: 3 | - appengine 4 | - appengine/datastore 5 | - appengine/memcache 6 | - appengine/user 7 | import: 8 | - package: gopkg.in/natefinch/lumberjack.v2 9 | version: 600ceb4523e5b7ff745f91083c8a023c2bf73af5 10 | - package: gopkg.in/olivere/elastic.v2 11 | version: 444684342d4c12c7c05bed13bd249034370840a9 12 | - package: gopkg.in/tomb.v1 13 | version: dd632973f1e7218eb1089048e0798ec9ae7dceb8 14 | - package: gopkg.in/v2/yaml 15 | version: a83829b6f1293c91addabc89d0571c246397bbf4 16 | - package: gopkg.in/yaml.v2 17 | version: a83829b6f1293c91addabc89d0571c246397bbf4 18 | - package: github.com/deis/pkg 19 | version: 189ed6bd6b6aa6629b72c2c5472095e176eec8a6 20 | subpackages: 21 | - /utils 22 | - package: github.com/minio/minio-go 23 | version: c5884ce9ce3ac73b025d0bc58c4d3d72870edc0b 24 | - package: speter.net/go/exp/math/dec/inf 25 | repo: https://github.com/belua/inf 26 | vcs: git 27 | -------------------------------------------------------------------------------- /glide.lock: -------------------------------------------------------------------------------- 1 | hash: 37a44159f052019502e3fa7379f5fb92b9a9a5fa7bbc2dbaf7d4d3aa0c44f695 2 | updated: 2016-09-06T17:49:12.271668528-06:00 3 | imports: 4 | - name: github.com/deis/pkg 5 | version: 189ed6bd6b6aa6629b72c2c5472095e176eec8a6 6 | subpackages: 7 | - utils 8 | - name: github.com/minio/minio-go 9 | version: c5884ce9ce3ac73b025d0bc58c4d3d72870edc0b 10 | - name: gopkg.in/natefinch/lumberjack.v2 11 | version: 600ceb4523e5b7ff745f91083c8a023c2bf73af5 12 | - name: gopkg.in/olivere/elastic.v2 13 | version: 444684342d4c12c7c05bed13bd249034370840a9 14 | - name: gopkg.in/tomb.v1 15 | version: dd632973f1e7218eb1089048e0798ec9ae7dceb8 16 | - name: gopkg.in/v2/yaml 17 | version: a83829b6f1293c91addabc89d0571c246397bbf4 18 | - name: gopkg.in/yaml.v2 19 | version: a83829b6f1293c91addabc89d0571c246397bbf4 20 | - name: speter.net/go/exp/math/dec/inf 21 | version: 46a40649338836f5d25521ce343379da79ef2184 22 | repo: https://github.com/belua/inf 23 | vcs: git 24 | testImports: [] 25 | -------------------------------------------------------------------------------- /src/healthsrv/healthz_handler.go: -------------------------------------------------------------------------------- 1 | package healthsrv 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | 9 | "github.com/deis/minio/src/storage" 10 | minio "github.com/minio/minio-go" 11 | ) 12 | 13 | type healthZResp struct { 14 | Buckets []minio.BucketInfo `json:"buckets"` 15 | } 16 | 17 | func healthZHandler(bucketLister storage.BucketLister) http.Handler { 18 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 19 | buckets, err := bucketLister.ListBuckets() 20 | if err != nil { 21 | str := fmt.Sprintf("Probe error: listing buckets (%s)", err) 22 | log.Println(str) 23 | http.Error(w, str, http.StatusInternalServerError) 24 | return 25 | } 26 | if err := json.NewEncoder(w).Encode(healthZResp{Buckets: buckets}); err != nil { 27 | str := fmt.Sprintf("Probe error: encoding buckets json (%s)", err) 28 | log.Println(str) 29 | http.Error(w, str, http.StatusInternalServerError) 30 | return 31 | } 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /_docs/README.md: -------------------------------------------------------------------------------- 1 | # Minio on Kubernetes 2 | 3 | Please see [the top level README](https://github.com/deis/minio/blob/master/README.md) for a description of what this project does. 4 | 5 | # Example Client Usage 6 | 7 | Assuming you've installed the Kubernetes service and replication controller (run `make kube-secrets kube-service kube-rc` to do so), you can access the Minio server via the Kubernetes service IP and port. Assuming you have the Minio [`mc`](https://github.com/minio/mc) CLI, installed in your container, here's how you'd configure the CLI and create a new bucket, all from inside Kubernetes: 8 | 9 | ```bash 10 | # The following two commands assume that you've mounted the 'minio-user' secret under /var/run/secrets/object/store. 11 | # If you've mounted the secret elsewhere, adjust as necessary. 12 | ACCESS_KEY_ID=`cat /var/run/secrets/object/store/access-key-id` 13 | ACCESS_SECRET_KEY=`cat /var/run/secrets/object/store/access-secret-key` 14 | BASE_SERVER="http://${DEIS_MINIO_SERVICE_HOST}:${DEIS_MINIO_SERVICE_PORT}" 15 | mc config host add $BASE_SERVER $ACCESS_KEY_ID $ACCESS_KEY_SECRET 16 | mc mb "${BASE_SERVER}/mybucket" 17 | ``` 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHORT_NAME := minio 2 | 3 | # dockerized development environment variables 4 | REPO_PATH := github.com/deis/${SHORT_NAME} 5 | DEV_ENV_IMAGE := quay.io/deis/go-dev:0.20.0 6 | DEV_ENV_WORK_DIR := /go/src/${REPO_PATH} 7 | DEV_ENV_PREFIX := docker run --rm -v ${CURDIR}:${DEV_ENV_WORK_DIR} -w ${DEV_ENV_WORK_DIR} 8 | DEV_ENV_CMD := ${DEV_ENV_PREFIX} ${DEV_ENV_IMAGE} 9 | 10 | LDFLAGS := "-s -X main.version=${VERSION}" 11 | BINDIR := ./rootfs/bin 12 | DEV_REGISTRY ?= $(docker-machine ip deis):5000 13 | DEIS_REGISTRY ?= ${DEV_REGISTRY} 14 | 15 | IMAGE_PREFIX ?= deis 16 | 17 | include versioning.mk 18 | 19 | TEST_PACKAGES := $(shell ${DEV_ENV_CMD} glide nv) 20 | 21 | all: build docker-build docker-push 22 | 23 | bootstrap: 24 | ${DEV_ENV_CMD} glide install 25 | 26 | glideup: 27 | ${DEV_ENV_CMD} glide up 28 | 29 | build: 30 | mkdir -p ${BINDIR} 31 | ${DEV_ENV_CMD} go build -ldflags '-s' -o $(BINDIR)/boot boot.go || exit 1 32 | 33 | test: 34 | ${DEV_ENV_CMD} go test ${TEST_PACKAGES} 35 | 36 | test-cover: 37 | ${DEV_ENV_CMD} test-cover.sh 38 | 39 | docker-build: build 40 | # build the main image 41 | docker build ${DOCKER_BUILD_FLAGS} -t ${IMAGE} rootfs 42 | docker tag ${IMAGE} ${MUTABLE_IMAGE} 43 | 44 | deploy: build docker-build docker-push 45 | 46 | .PHONY: all bootstrap glideup build test docker-build deploy 47 | -------------------------------------------------------------------------------- /DCO: -------------------------------------------------------------------------------- 1 | Developer Certificate of Origin 2 | Version 1.1 3 | 4 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 5 | 660 York Street, Suite 102, 6 | San Francisco, CA 94110 USA 7 | 8 | Everyone is permitted to copy and distribute verbatim copies of this 9 | license document, but changing it is not allowed. 10 | 11 | 12 | Developer's Certificate of Origin 1.1 13 | 14 | By making a contribution to this project, I certify that: 15 | 16 | (a) The contribution was created in whole or in part by me and I 17 | have the right to submit it under the open source license 18 | indicated in the file; or 19 | 20 | (b) The contribution is based upon previous work that, to the best 21 | of my knowledge, is covered under an appropriate open source 22 | license and I have the right under that license to submit that 23 | work with modifications, whether created in whole or in part 24 | by me, under the same open source license (unless I am 25 | permitted to submit under a different license), as indicated 26 | in the file; or 27 | 28 | (c) The contribution was provided directly to me by some other 29 | person who certified (a), (b) or (c) and I have not modified 30 | it. 31 | 32 | (d) I understand and agree that this project and the contribution 33 | are public and that a record of the contribution (including all 34 | personal information I submit with it, including my sign-off) is 35 | maintained indefinitely and may be redistributed consistent with 36 | this project or the open source license(s) involved. 37 | -------------------------------------------------------------------------------- /src/healthsrv/healthz_handler_test.go: -------------------------------------------------------------------------------- 1 | package healthsrv 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "net/http" 7 | "net/http/httptest" 8 | "testing" 9 | "time" 10 | 11 | "github.com/deis/minio/src/storage" 12 | minio "github.com/minio/minio-go" 13 | ) 14 | 15 | func TestHealthzHandler(t *testing.T) { 16 | buckets := []minio.BucketInfo{ 17 | minio.BucketInfo{Name: "bucket1", CreationDate: time.Now()}, 18 | minio.BucketInfo{Name: "bucket2", CreationDate: time.Now()}, 19 | } 20 | bucketLister := storage.NewFakeBucketLister(buckets) 21 | handler := healthZHandler(bucketLister) 22 | 23 | w := httptest.NewRecorder() 24 | r, err := http.NewRequest("GET", "/healthz", bytes.NewReader(nil)) 25 | if err != nil { 26 | t.Fatalf("unexpected error creating request (%s)", err) 27 | } 28 | handler.ServeHTTP(w, r) 29 | if w.Code != http.StatusOK { 30 | t.Fatalf("unexpected response code %d", w.Code) 31 | } 32 | 33 | rsp := new(healthZResp) 34 | if err := json.NewDecoder(w.Body).Decode(rsp); err != nil { 35 | t.Fatalf("error decoding json (%s)", err) 36 | } 37 | if len(rsp.Buckets) != len(buckets) { 38 | t.Fatalf("received %d bucket(s), expected %d", len(rsp.Buckets), len(buckets)) 39 | } 40 | 41 | for i, bucket := range buckets { 42 | actual := rsp.Buckets[i] 43 | if actual.Name != bucket.Name { 44 | t.Fatalf("expected name %s for bucket %d, got %s", bucket.Name, i, actual.Name) 45 | } 46 | if !actual.CreationDate.Equal(bucket.CreationDate) { 47 | t.Fatalf("expected creation date %s for bucket %d, got %s", bucket.CreationDate, i, actual.CreationDate) 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /charts/minio/templates/minio-deployment.yaml: -------------------------------------------------------------------------------- 1 | {{- if eq .Values.global.storage "minio" }} 2 | apiVersion: extensions/v1beta1 3 | kind: Deployment 4 | metadata: 5 | name: deis-minio 6 | labels: 7 | heritage: deis 8 | annotations: 9 | component.deis.io/version: {{ .Values.docker_tag }} 10 | spec: 11 | replicas: 1 12 | strategy: 13 | type: Recreate 14 | selector: 15 | matchLabels: 16 | app: deis-minio 17 | template: 18 | metadata: 19 | labels: 20 | app: deis-minio 21 | spec: 22 | serviceAccount: deis-minio 23 | containers: 24 | - name: deis-minio 25 | image: quay.io/{{.Values.org}}/minio:{{.Values.docker_tag}} 26 | imagePullPolicy: {{.Values.pull_policy}} 27 | env: 28 | - name: HEALTH_SERVER_PORT 29 | value: "8082" 30 | ports: 31 | - containerPort: 9000 32 | - containerPort: 8082 33 | livenessProbe: 34 | httpGet: 35 | path: /healthz 36 | port: 8082 37 | initialDelaySeconds: 30 38 | timeoutSeconds: 1 39 | readinessProbe: 40 | httpGet: 41 | path: /healthz 42 | port: 8082 43 | initialDelaySeconds: 30 44 | timeoutSeconds: 1 45 | command: 46 | - boot 47 | args: 48 | - "server /home/minio/" 49 | volumeMounts: 50 | - name: minio-user 51 | mountPath: /var/run/secrets/deis/minio/user 52 | readOnly: true 53 | volumes: 54 | - name: minio-user 55 | secret: 56 | secretName: minio-user 57 | {{- end }} 58 | -------------------------------------------------------------------------------- /boot.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "fmt" 7 | "io/ioutil" 8 | "log" 9 | "os" 10 | "os/exec" 11 | "strconv" 12 | "strings" 13 | "text/template" 14 | 15 | "github.com/deis/minio/src/healthsrv" 16 | "github.com/deis/pkg/utils" 17 | minio "github.com/minio/minio-go" 18 | ) 19 | 20 | const ( 21 | localMinioInsecure = true 22 | defaultMinioHost = "localhost" 23 | defaultMinioPort = "9000" 24 | ) 25 | 26 | var ( 27 | errHealthSrvExited = errors.New("healthcheck server exited with unknown status") 28 | errMinioExited = errors.New("Minio server exited with unknown status") 29 | ) 30 | 31 | // Secret is a secret for the remote object storage 32 | type Secret struct { 33 | Host string 34 | KeyID string 35 | AccessKey string 36 | Region string 37 | } 38 | 39 | const configdir = "/home/minio/.minio/" 40 | 41 | const templv2 = `{ 42 | "version": "2", 43 | "credentials": { 44 | {{range .}} 45 | "accessKeyId": "{{.KeyID}}", 46 | "secretAccessKey": "{{.AccessKey}}", 47 | "region": "{{.Region}}" 48 | {{end}} 49 | }, 50 | "mongoLogger": { 51 | "addr": "", 52 | "db": "", 53 | "collection": "" 54 | }, 55 | "syslogLogger": { 56 | "network": "", 57 | "addr": "" 58 | }, 59 | "fileLogger": { 60 | "filename": "" 61 | } 62 | }` 63 | 64 | func run(cmd string) error { 65 | var cmdBuf bytes.Buffer 66 | tmpl := template.Must(template.New("cmd").Parse(cmd)) 67 | if err := tmpl.Execute(&cmdBuf, nil); err != nil { 68 | log.Fatal(err) 69 | } 70 | cmdString := cmdBuf.String() 71 | fmt.Println(cmdString) 72 | var cmdl *exec.Cmd 73 | cmdl = exec.Command("sh", "-c", cmdString) 74 | if _, _, err := utils.RunCommandWithStdoutStderr(cmdl); err != nil { 75 | return err 76 | } 77 | return nil 78 | } 79 | 80 | func readSecrets() (string, string) { 81 | keyID, err := ioutil.ReadFile("/var/run/secrets/deis/minio/user/accesskey") 82 | checkError(err) 83 | accessKey, err := ioutil.ReadFile("/var/run/secrets/deis/minio/user/secretkey") 84 | checkError(err) 85 | return strings.TrimSpace(string(keyID)), strings.TrimSpace(string(accessKey)) 86 | } 87 | 88 | func newMinioClient(host, port, accessKey, accessSecret string, insecure bool) (minio.CloudStorageClient, error) { 89 | return minio.New( 90 | fmt.Sprintf("%s:%s", host, port), 91 | accessKey, 92 | accessSecret, 93 | insecure, 94 | ) 95 | } 96 | 97 | func main() { 98 | key, access := readSecrets() 99 | 100 | minioHost := os.Getenv("MINIO_HOST") 101 | if minioHost == "" { 102 | minioHost = defaultMinioHost 103 | } 104 | minioPort := os.Getenv("MINIO_PORT") 105 | if minioPort == "" { 106 | minioPort = defaultMinioPort 107 | } 108 | minioClient, err := newMinioClient(minioHost, minioPort, key, access, localMinioInsecure) 109 | if err != nil { 110 | log.Printf("Error creating minio client (%s)", err) 111 | os.Exit(1) 112 | } 113 | 114 | secrets := []Secret{ 115 | { 116 | KeyID: key, 117 | AccessKey: access, 118 | Region: "us-east-1", 119 | }, 120 | } 121 | t := template.New("MinioTpl") 122 | t, err = t.Parse(templv2) 123 | checkError(err) 124 | 125 | err = os.MkdirAll(configdir, 0755) 126 | checkError(err) 127 | output, err := os.Create(configdir + "config.json") 128 | checkError(err) 129 | err = t.Execute(output, secrets) 130 | checkError(err) 131 | os.Args[0] = "minio" 132 | mc := strings.Join(os.Args, " ") 133 | runErrCh := make(chan error) 134 | log.Printf("starting Minio server") 135 | go func() { 136 | if err := run(mc); err != nil { 137 | runErrCh <- err 138 | } else { 139 | runErrCh <- errMinioExited 140 | } 141 | }() 142 | 143 | healthSrvHost := os.Getenv("HEALTH_SERVER_HOST") 144 | if healthSrvHost == "" { 145 | healthSrvHost = healthsrv.DefaultHost 146 | } 147 | healthSrvPort, err := strconv.Atoi(os.Getenv("HEALTH_SERVER_PORT")) 148 | if err != nil { 149 | healthSrvPort = healthsrv.DefaultPort 150 | } 151 | 152 | log.Printf("starting health check server on %s:%d", healthSrvHost, healthSrvPort) 153 | 154 | healthSrvErrCh := make(chan error) 155 | go func() { 156 | if err := healthsrv.Start(healthSrvHost, healthSrvPort, minioClient); err != nil { 157 | healthSrvErrCh <- err 158 | } else { 159 | healthSrvErrCh <- errHealthSrvExited 160 | } 161 | }() 162 | 163 | select { 164 | case err := <-runErrCh: 165 | log.Printf("Minio server error (%s)", err) 166 | os.Exit(1) 167 | case err := <-healthSrvErrCh: 168 | log.Printf("Healthcheck server error (%s)", err) 169 | os.Exit(1) 170 | } 171 | } 172 | 173 | func checkError(err error) { 174 | if err != nil { 175 | fmt.Println("Fatal error ", err.Error()) 176 | os.Exit(1) 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | |![](https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Warning.svg/156px-Warning.svg.png) | Deis Workflow is no longer maintained.
Please [read the announcement](https://deis.com/blog/2017/deis-workflow-final-release/) for more detail. | 3 | |---:|---| 4 | | 09/07/2017 | Deis Workflow [v2.18][] final release before entering maintenance mode | 5 | | 03/01/2018 | End of Workflow maintenance: critical patches no longer merged | 6 | | | [Hephy](https://github.com/teamhephy/workflow) is a fork of Workflow that is actively developed and accepts code contributions. | 7 | 8 | # Deis Minio v2 9 | 10 | [![Build Status](https://ci.deis.io/job/minio/badge/icon)](https://ci.deis.io/job/minio) 11 | [![Go Report Card](http://goreportcard.com/badge/deis/minio)](http://goreportcard.com/report/deis/minio) 12 | [![Docker Repository on Quay](https://quay.io/repository/deisci/minio/status "Docker Repository on Quay")](https://quay.io/repository/deisci/minio) 13 | 14 | Deis (pronounced DAY-iss) Workflow is an open source Platform as a Service (PaaS) that adds a developer-friendly layer to any [Kubernetes](http://kubernetes.io) cluster, making it easy to deploy and manage applications on your own servers. 15 | 16 | For more information about the Deis workflow, please visit the main project page at https://github.com/deis/workflow. 17 | 18 | We welcome your input! If you have feedback, please submit an [issue][issues]. If you'd like to participate in development, please read the "Development" section below and submit a [pull request][prs]. 19 | 20 | # About 21 | 22 | The Deis minio component provides an [S3 API][s3-api] compatible object storage server, based on [Minio](http://minio.io), that can be run on Kubernetes. It's intended for use within the [Deis v2 platform][deis-docs] as an object storage server, but it's flexible enough to be run as a standalone pod on any Kubernetes cluster. 23 | 24 | Note that in the default [Helm chart for the Deis platform](https://github.com/deis/charts/tree/master/deis-dev), this component is used as a storage location for the following components: 25 | 26 | - [deis/postgres](https://github.com/deis/postgres) 27 | - [deis/registry](https://github.com/deis/registry) 28 | - [deis/builder](https://github.com/deis/builder) 29 | 30 | Also note that we aren't currently providing this component with any kind of persistent storage, but it may work with [persistent volumes](http://kubernetes.io/docs/user-guide/volumes/). 31 | 32 | # Development 33 | 34 | The Deis project welcomes contributions from all developers. The high level process for development matches many other open source projects. See below for an outline. 35 | 36 | * Fork this repository 37 | * Make your changes 38 | * Submit a [pull request][prs] (PR) to this repository with your changes, and unit tests whenever possible. 39 | * If your PR fixes any [issues][issues], make sure you write Fixes #1234 in your PR description (where #1234 is the number of the issue you're closing) 40 | * The Deis core contributors will review your code. After each of them sign off on your code, they'll label your PR with `LGTM1` and `LGTM2` (respectively). Once that happens, you may merge. 41 | 42 | ## Minio Binary Mirror 43 | 44 | Also, note that the [Dockerfile](rootfs/Dockerfile) uses an `ADD` directive to download pre-built Minio binaries from a [Google Cloud Storage bucket](https://console.cloud.google.com/storage/browser/minio-mirror/?project=deis-mirrors). The bucket is in the `deis-mirrors` project, and if you have access to that project, [this link](https://console.cloud.google.com/storage/browser/minio-mirror/?project=deis-mirrors) should take you directly to that bucket. 45 | 46 | To bump this component to use a newer build of Minio, simply add a new binary to the bucket (under the `linux-amd64` folder), check the checkbox under the `Share publicly` column, and update the URL in the `ADD` directive in the aforementioned `Dockerfile`. 47 | 48 | ## Docker Based Development Environment 49 | 50 | The preferred environment for development uses the [`go-dev` Docker image](https://github.com/deis/docker-go-dev). The tools described in this section are used to build, test, package and release each version of Deis. 51 | 52 | To use it yourself, you must have [make](https://www.gnu.org/software/make/) installed and Docker installed and running on your local development machine. 53 | 54 | If you don't have Docker installed, please go to https://www.docker.com/ to install it. 55 | 56 | After you have those dependencies, build your code with `make build` and execute unit tests with `make test`. 57 | 58 | ## Native Go Development Environment 59 | 60 | You can also use the standard go toolchain to build and test if you prefer. To do so, you'll need [glide](https://github.com/Masterminds/glide) 0.9 or above and [Go](http://golang.org/) 1.6 or above installed. 61 | 62 | After you have those dependencies, you can build and unit-test your code with `go build` and `go test $(glide nv)`, respectively. 63 | 64 | Note that you will not be able to build or push Docker images using this method of development. 65 | 66 | 67 | ## Testing 68 | 69 | The Deis project requires that as much code as possible is unit tested, but the core contributors also recognize that some code must be tested at a higher level (functional or integration tests, for example). 70 | 71 | The [end-to-end tests](https://github.com/deis/workflow-e2e) repository has our integration tests. Additionally, the core contributors and members of the community also regularly [dogfood](https://en.wikipedia.org/wiki/Eating_your_own_dog_food) the platform. 72 | 73 | ## Running End-to-End Tests 74 | 75 | Please see [README.md](https://github.com/deis/workflow-e2e/blob/master/README.md) on the end-to-end tests reposotory for instructions on how to set up your testing environment and run the tests. 76 | 77 | ## Dogfooding 78 | 79 | Please follow the instructions on the [official Deis docs][deis-docs] to install and configure your Deis cluster and all related tools, and deploy and configure an app on Deis. 80 | 81 | 82 | [install-k8s]: http://kubernetes.io/gettingstarted/ 83 | [s3-api]: http://docs.aws.amazon.com/AmazonS3/latest/API/APIRest.html 84 | [issues]: https://github.com/deis/minio/issues 85 | [prs]: https://github.com/deis/minio/pulls 86 | [deis-docs]: https://deis.com/docs/workflow 87 | [v2.18]: https://github.com/deis/workflow/releases/tag/v2.18.0 88 | --------------------------------------------------------------------------------