mirror of
https://github.com/goharbor/harbor.git
synced 2025-01-10 01:48:07 +01:00
mount data directory to adminserver
This commit is contained in:
parent
37ea4273e1
commit
3a167ddfce
@ -19,40 +19,13 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
|
|
||||||
cfg "github.com/vmware/harbor/src/adminserver/systemcfg"
|
cfg "github.com/vmware/harbor/src/adminserver/systemcfg"
|
||||||
"github.com/vmware/harbor/src/common/utils/log"
|
"github.com/vmware/harbor/src/common/utils/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func isAuthenticated(r *http.Request) (bool, error) {
|
|
||||||
uiSecret := os.Getenv("UI_SECRET")
|
|
||||||
jobserviceSecret := os.Getenv("JOBSERVICE_SECRET")
|
|
||||||
c, err := r.Cookie("secret")
|
|
||||||
if err != nil {
|
|
||||||
if err == http.ErrNoCookie {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return c != nil && (c.Value == uiSecret ||
|
|
||||||
c.Value == jobserviceSecret), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListCfgs lists configurations
|
// ListCfgs lists configurations
|
||||||
func ListCfgs(w http.ResponseWriter, r *http.Request) {
|
func ListCfgs(w http.ResponseWriter, r *http.Request) {
|
||||||
authenticated, err := isAuthenticated(r)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed to check whether the request is authenticated or not: %v", err)
|
|
||||||
handleInternalServerError(w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !authenticated {
|
|
||||||
handleUnauthorized(w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg, err := cfg.GetSystemCfg()
|
cfg, err := cfg.GetSystemCfg()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed to get system configurations: %v", err)
|
log.Errorf("failed to get system configurations: %v", err)
|
||||||
@ -73,18 +46,6 @@ func ListCfgs(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// UpdateCfgs updates configurations
|
// UpdateCfgs updates configurations
|
||||||
func UpdateCfgs(w http.ResponseWriter, r *http.Request) {
|
func UpdateCfgs(w http.ResponseWriter, r *http.Request) {
|
||||||
authenticated, err := isAuthenticated(r)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed to check whether the request is authenticated or not: %v", err)
|
|
||||||
handleInternalServerError(w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !authenticated {
|
|
||||||
handleUnauthorized(w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := ioutil.ReadAll(r.Body)
|
b, err := ioutil.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("failed to read request body: %v", err)
|
log.Errorf("failed to read request body: %v", err)
|
||||||
@ -107,19 +68,7 @@ func UpdateCfgs(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// ResetCfgs resets configurations from environment variables
|
// ResetCfgs resets configurations from environment variables
|
||||||
func ResetCfgs(w http.ResponseWriter, r *http.Request) {
|
func ResetCfgs(w http.ResponseWriter, r *http.Request) {
|
||||||
authenticated, err := isAuthenticated(r)
|
if err := cfg.Reset(); err != nil {
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed to check whether the request is authenticated or not: %v", err)
|
|
||||||
handleInternalServerError(w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !authenticated {
|
|
||||||
handleUnauthorized(w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = cfg.Reset(); err != nil {
|
|
||||||
log.Errorf("failed to reset system configurations: %v", err)
|
log.Errorf("failed to reset system configurations: %v", err)
|
||||||
handleInternalServerError(w)
|
handleInternalServerError(w)
|
||||||
return
|
return
|
||||||
|
@ -79,19 +79,12 @@ func TestConfigAPI(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
ListCfgs(w, r)
|
|
||||||
if w.Code != http.StatusUnauthorized {
|
|
||||||
t.Errorf("unexpected status code: %d != %d", w.Code, http.StatusUnauthorized)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
r.AddCookie(&http.Cookie{
|
r.AddCookie(&http.Cookie{
|
||||||
Name: "secret",
|
Name: "secret",
|
||||||
Value: secret,
|
Value: secret,
|
||||||
})
|
})
|
||||||
|
|
||||||
w = httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
ListCfgs(w, r)
|
ListCfgs(w, r)
|
||||||
if w.Code != http.StatusOK {
|
if w.Code != http.StatusOK {
|
||||||
t.Errorf("unexpected status code: %d != %d", w.Code, http.StatusOK)
|
t.Errorf("unexpected status code: %d != %d", w.Code, http.StatusOK)
|
||||||
|
45
src/adminserver/api/systeminfo.go
Normal file
45
src/adminserver/api/systeminfo.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/vmware/harbor/src/adminserver/systeminfo/imagestorage"
|
||||||
|
"github.com/vmware/harbor/src/common/utils/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Capacity handles /api/systeminfo/capacity and returns system capacity
|
||||||
|
func Capacity(w http.ResponseWriter, r *http.Request) {
|
||||||
|
capacity, err := imagestorage.GlobalDriver.Cap()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to get capacity: %v", err)
|
||||||
|
handleInternalServerError(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := json.Marshal(capacity)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to marshal capacity: %v", err)
|
||||||
|
handleInternalServerError(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = w.Write(b); err != nil {
|
||||||
|
log.Errorf("failed to write response: %v", err)
|
||||||
|
}
|
||||||
|
}
|
74
src/adminserver/api/systeminfo_test.go
Normal file
74
src/adminserver/api/systeminfo_test.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/vmware/harbor/src/adminserver/systeminfo/imagestorage"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fakeImageStorageDriver struct {
|
||||||
|
capacity *imagestorage.Capacity
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeImageStorageDriver) Name() string {
|
||||||
|
return "fake"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeImageStorageDriver) Cap() (*imagestorage.Capacity, error) {
|
||||||
|
return f.capacity, f.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapacity(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
driver imagestorage.Driver
|
||||||
|
responseCode int
|
||||||
|
capacity *imagestorage.Capacity
|
||||||
|
}{
|
||||||
|
{&fakeImageStorageDriver{nil, errors.New("error")}, http.StatusInternalServerError, nil},
|
||||||
|
{&fakeImageStorageDriver{&imagestorage.Capacity{100, 90}, nil}, http.StatusOK, &imagestorage.Capacity{100, 90}},
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("", "", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create request: %v", err)
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
imagestorage.GlobalDriver = c.driver
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
Capacity(w, req)
|
||||||
|
assert.Equal(t, c.responseCode, w.Code, "unexpected response code")
|
||||||
|
if c.responseCode == http.StatusOK {
|
||||||
|
b, err := ioutil.ReadAll(w.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to read from response body: %v", err)
|
||||||
|
}
|
||||||
|
capacity := &imagestorage.Capacity{}
|
||||||
|
if err = json.Unmarshal(b, capacity); err != nil {
|
||||||
|
t.Fatalf("failed to unmarshal: %v", err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, c.capacity, capacity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
65
src/adminserver/auth/auth.go
Normal file
65
src/adminserver/auth/auth.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Authenticator defines Authenticate function to authenticate requests
|
||||||
|
type Authenticator interface {
|
||||||
|
// Authenticate the request, if there is no error, the bool value
|
||||||
|
// determines whether the request is authenticated or not
|
||||||
|
Authenticate(req *http.Request) (bool, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type secretAuthenticator struct {
|
||||||
|
secrets map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSecretAuthenticator returns an instance of secretAuthenticator
|
||||||
|
func NewSecretAuthenticator(secrets map[string]string) Authenticator {
|
||||||
|
return &secretAuthenticator{
|
||||||
|
secrets: secrets,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authenticate the request according the secret
|
||||||
|
func (s *secretAuthenticator) Authenticate(req *http.Request) (bool, error) {
|
||||||
|
if len(s.secrets) == 0 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
secret, err := req.Cookie("secret")
|
||||||
|
if err != nil {
|
||||||
|
if err == http.ErrNoCookie {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if secret == nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range s.secrets {
|
||||||
|
if secret.Value == v {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
57
src/adminserver/auth/auth_test.go
Normal file
57
src/adminserver/auth/auth_test.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAuthenticate(t *testing.T) {
|
||||||
|
secret := "correct"
|
||||||
|
req1, err := http.NewRequest("", "", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create request: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req2, err := http.NewRequest("", "", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create request: %v", err)
|
||||||
|
}
|
||||||
|
req2.AddCookie(&http.Cookie{
|
||||||
|
Name: "secret",
|
||||||
|
Value: secret,
|
||||||
|
})
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
secrets map[string]string
|
||||||
|
req *http.Request
|
||||||
|
result bool
|
||||||
|
}{
|
||||||
|
{nil, req1, true},
|
||||||
|
{map[string]string{"secret1": "incorrect"}, req2, false},
|
||||||
|
{map[string]string{"secret1": "incorrect", "secret2": secret}, req2, true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
authenticator := NewSecretAuthenticator(c.secrets)
|
||||||
|
authenticated, err := authenticator.Authenticate(c.req)
|
||||||
|
assert.Nil(t, err, "unexpected error")
|
||||||
|
assert.Equal(t, c.result, authenticated, "unexpected result")
|
||||||
|
}
|
||||||
|
}
|
76
src/adminserver/handlers/handler.go
Normal file
76
src/adminserver/handlers/handler.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
gorilla_handlers "github.com/gorilla/handlers"
|
||||||
|
"github.com/vmware/harbor/src/adminserver/auth"
|
||||||
|
"github.com/vmware/harbor/src/common/utils/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewHandler() http.Handler {
|
||||||
|
h := newRouter()
|
||||||
|
secrets := map[string]string{
|
||||||
|
"uiSecret": os.Getenv("UI_SECRET"),
|
||||||
|
"jobserviceSecret": os.Getenv("JOBSERVICE_SECRET"),
|
||||||
|
}
|
||||||
|
h = newAuthHandler(auth.NewSecretAuthenticator(secrets), h)
|
||||||
|
h = gorilla_handlers.LoggingHandler(os.Stdout, h)
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
type authHandler struct {
|
||||||
|
authenticator auth.Authenticator
|
||||||
|
handler http.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
func newAuthHandler(authenticator auth.Authenticator, handler http.Handler) http.Handler {
|
||||||
|
return &authHandler{
|
||||||
|
authenticator: authenticator,
|
||||||
|
handler: handler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *authHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if a.authenticator == nil {
|
||||||
|
if a.handler != nil {
|
||||||
|
a.handler.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
valid, err := a.authenticator.Authenticate(r)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to authenticate request: %v", err)
|
||||||
|
http.Error(w, http.StatusText(http.StatusInternalServerError),
|
||||||
|
http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !valid {
|
||||||
|
http.Error(w, http.StatusText(http.StatusUnauthorized),
|
||||||
|
http.StatusUnauthorized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.handler != nil {
|
||||||
|
a.handler.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
73
src/adminserver/handlers/handlers_test.go
Normal file
73
src/adminserver/handlers/handlers_test.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/vmware/harbor/src/adminserver/auth"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fakeAuthenticator struct {
|
||||||
|
authenticated bool
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeAuthenticator) Authenticate(req *http.Request) (bool, error) {
|
||||||
|
return f.authenticated, f.err
|
||||||
|
}
|
||||||
|
|
||||||
|
type fakeHandler struct {
|
||||||
|
responseCode int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(f.responseCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewAuthHandler(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
authenticator auth.Authenticator
|
||||||
|
handler http.Handler
|
||||||
|
responseCode int
|
||||||
|
}{
|
||||||
|
|
||||||
|
{nil, nil, http.StatusOK},
|
||||||
|
{&fakeAuthenticator{
|
||||||
|
authenticated: false,
|
||||||
|
err: nil,
|
||||||
|
}, nil, http.StatusUnauthorized},
|
||||||
|
{&fakeAuthenticator{
|
||||||
|
authenticated: false,
|
||||||
|
err: errors.New("error"),
|
||||||
|
}, nil, http.StatusInternalServerError},
|
||||||
|
{&fakeAuthenticator{
|
||||||
|
authenticated: true,
|
||||||
|
err: nil,
|
||||||
|
}, &fakeHandler{http.StatusNotFound}, http.StatusNotFound},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
handler := newAuthHandler(c.authenticator, c.handler)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
handler.ServeHTTP(w, nil)
|
||||||
|
assert.Equal(t, c.responseCode, w.Code, "unexpected response code")
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,7 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package main
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -22,10 +22,11 @@ import (
|
|||||||
"github.com/vmware/harbor/src/adminserver/api"
|
"github.com/vmware/harbor/src/adminserver/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newHandler() http.Handler {
|
func newRouter() http.Handler {
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
r.HandleFunc("/api/configurations", api.ListCfgs).Methods("GET")
|
r.HandleFunc("/api/configurations", api.ListCfgs).Methods("GET")
|
||||||
r.HandleFunc("/api/configurations", api.UpdateCfgs).Methods("PUT")
|
r.HandleFunc("/api/configurations", api.UpdateCfgs).Methods("PUT")
|
||||||
r.HandleFunc("/api/configurations/reset", api.ResetCfgs).Methods("POST")
|
r.HandleFunc("/api/configurations/reset", api.ResetCfgs).Methods("POST")
|
||||||
|
r.HandleFunc("/api/systeminfo/capacity", api.Capacity).Methods("GET")
|
||||||
return r
|
return r
|
||||||
}
|
}
|
@ -19,8 +19,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/gorilla/handlers"
|
"github.com/vmware/harbor/src/adminserver/handlers"
|
||||||
syscfg "github.com/vmware/harbor/src/adminserver/systemcfg"
|
syscfg "github.com/vmware/harbor/src/adminserver/systemcfg"
|
||||||
|
sysinfo "github.com/vmware/harbor/src/adminserver/systeminfo"
|
||||||
"github.com/vmware/harbor/src/common/utils/log"
|
"github.com/vmware/harbor/src/common/utils/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -47,13 +48,15 @@ func main() {
|
|||||||
}
|
}
|
||||||
log.Info("system initialization completed")
|
log.Info("system initialization completed")
|
||||||
|
|
||||||
|
sysinfo.Init()
|
||||||
|
|
||||||
port := os.Getenv("PORT")
|
port := os.Getenv("PORT")
|
||||||
if len(port) == 0 {
|
if len(port) == 0 {
|
||||||
port = "80"
|
port = "80"
|
||||||
}
|
}
|
||||||
server := &Server{
|
server := &Server{
|
||||||
Port: port,
|
Port: port,
|
||||||
Handler: handlers.LoggingHandler(os.Stdout, newHandler()),
|
Handler: handlers.NewHandler(),
|
||||||
}
|
}
|
||||||
if err := server.Serve(); err != nil {
|
if err := server.Serve(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
35
src/adminserver/systeminfo/imagestorage/driver.go
Normal file
35
src/adminserver/systeminfo/imagestorage/driver.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package imagestorage
|
||||||
|
|
||||||
|
// GlobalDriver is a global image storage driver
|
||||||
|
var GlobalDriver Driver
|
||||||
|
|
||||||
|
// Capacity holds information about capaticy of image storage
|
||||||
|
type Capacity struct {
|
||||||
|
// total size(byte)
|
||||||
|
Total uint64 `json:"total"`
|
||||||
|
// available size(byte)
|
||||||
|
Free uint64 `json:"free"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Driver defines methods that an image storage driver must implement
|
||||||
|
type Driver interface {
|
||||||
|
// Name returns a human-readable name of the driver
|
||||||
|
Name() string
|
||||||
|
// Cap returns the capacity of the image storage
|
||||||
|
Cap() (*Capacity, error)
|
||||||
|
}
|
56
src/adminserver/systeminfo/imagestorage/filesystem/driver.go
Normal file
56
src/adminserver/systeminfo/imagestorage/filesystem/driver.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package filesystem
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
storage "github.com/vmware/harbor/src/adminserver/systeminfo/imagestorage"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
driverName = "filesystem"
|
||||||
|
)
|
||||||
|
|
||||||
|
type driver struct {
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDriver returns an instance of filesystem driver
|
||||||
|
func NewDriver(path string) storage.Driver {
|
||||||
|
return &driver{
|
||||||
|
path: path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns a human-readable name of the fielsystem driver
|
||||||
|
func (d *driver) Name() string {
|
||||||
|
return driverName
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cap returns the capacity of the filesystem storage
|
||||||
|
func (d *driver) Cap() (*storage.Capacity, error) {
|
||||||
|
var stat syscall.Statfs_t
|
||||||
|
err := syscall.Statfs(d.path, &stat)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &storage.Capacity{
|
||||||
|
Total: stat.Blocks * uint64(stat.Bsize),
|
||||||
|
Free: stat.Bavail * uint64(stat.Bsize),
|
||||||
|
}, nil
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package filesystem
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestName(t *testing.T) {
|
||||||
|
path := "/tmp"
|
||||||
|
driver := NewDriver(path)
|
||||||
|
assert.Equal(t, driver.Name(), driverName, "unexpected driver name")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCap(t *testing.T) {
|
||||||
|
path := "/tmp"
|
||||||
|
driver := NewDriver(path)
|
||||||
|
_, err := driver.Cap()
|
||||||
|
assert.Nil(t, err, "unexpected error")
|
||||||
|
}
|
32
src/adminserver/systeminfo/systeminfo.go
Normal file
32
src/adminserver/systeminfo/systeminfo.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package systeminfo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/vmware/harbor/src/adminserver/systeminfo/imagestorage"
|
||||||
|
"github.com/vmware/harbor/src/adminserver/systeminfo/imagestorage/filesystem"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Init image storage driver
|
||||||
|
func Init() {
|
||||||
|
path := os.Getenv("IMAGE_STORE_PATH")
|
||||||
|
if len(path) == 0 {
|
||||||
|
path = "/data"
|
||||||
|
}
|
||||||
|
imagestorage.GlobalDriver = filesystem.NewDriver(path)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user