Skip to content

Commit

Permalink
nfs-shares: add upper limit support for MaxSize
Browse files Browse the repository at this point in the history
  • Loading branch information
talal committed Sep 24, 2020
1 parent 12aac82 commit 1448449
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 8 deletions.
5 changes: 3 additions & 2 deletions internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
)

type handler struct {
Config *core.Config
DB *gorp.DbMap
Team core.AssetManagerTeam
Validator gopherpolicy.Validator
Expand All @@ -49,8 +50,8 @@ type handler struct {
}

//NewHandler constructs the main http.Handler for this package.
func NewHandler(dbi *gorp.DbMap, team core.AssetManagerTeam, validator gopherpolicy.Validator, provider core.ProviderClientInterface) http.Handler {
h := &handler{DB: dbi, Team: team, Validator: validator, Provider: provider, TimeNow: time.Now}
func NewHandler(cfg *core.Config, dbi *gorp.DbMap, team core.AssetManagerTeam, validator gopherpolicy.Validator, provider core.ProviderClientInterface) http.Handler {
h := &handler{Config: cfg, DB: dbi, Team: team, Validator: validator, Provider: provider, TimeNow: time.Now}
return h.BuildRouter()
}

Expand Down
18 changes: 16 additions & 2 deletions internal/api/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package api

import (
"fmt"
"net/http"
"strings"
"time"
Expand Down Expand Up @@ -115,7 +116,7 @@ func (h handler) ResourceFromDB(res db.Resource) (Resource, error) {

//UpdateDBResource updates the given db.Resource with the values provided in
//this api.Resource.
func (r Resource) UpdateDBResource(res *db.Resource, info core.AssetTypeInfo) (errors []string) {
func (r Resource) UpdateDBResource(res *db.Resource, info core.AssetTypeInfo, maxAssetSize *uint64) (errors []string) {
complain := func(msg string) { errors = append(errors, msg) }

if r.ScrapedAtUnix != nil {
Expand Down Expand Up @@ -203,11 +204,23 @@ func (r Resource) UpdateDBResource(res *db.Resource, info core.AssetTypeInfo) (e
}
}

isNFS := string(info.AssetType) == "nfs-shares"
if r.SizeConstraints == nil {
if isNFS {
complain("maximum size must be configured for nfs-shares")
}
res.MinimumSize = nil
res.MaximumSize = nil
res.MinimumFreeSize = nil
} else {
if isNFS {
if res.MaximumSize == nil {
complain("maximum size must be configured for nfs-shares")
} else if maxAssetSize != nil && *res.MaximumSize > *maxAssetSize {
complain(fmt.Sprintf("maximum size must be less than %d", *maxAssetSize))
}
}

res.MinimumSize = r.SizeConstraints.Minimum
if res.MinimumSize != nil && *res.MinimumSize == 0 {
res.MinimumSize = nil
Expand Down Expand Up @@ -309,6 +322,7 @@ func (h handler) PutResource(w http.ResponseWriter, r *http.Request) {
}

manager, info := h.Team.ForAssetType(dbResource.AssetType)
maxAssetSize := h.Config.MaxAssetSize[info.AssetType]
err := manager.CheckResourceAllowed(dbResource.AssetType, dbResource.ScopeUUID)
if err != nil {
http.Error(w, err.Error(), http.StatusUnprocessableEntity)
Expand All @@ -335,7 +349,7 @@ func (h handler) PutResource(w http.ResponseWriter, r *http.Request) {
})
}

errs := input.UpdateDBResource(dbResource, info)
errs := input.UpdateDBResource(dbResource, info, maxAssetSize)
if len(errs) > 0 {
doAudit(http.StatusUnprocessableEntity)
http.Error(w, strings.Join(errs, "\n"), http.StatusUnprocessableEntity)
Expand Down
2 changes: 1 addition & 1 deletion internal/api/shared_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func withHandler(t test.T, timeNow func() time.Time, action func(*handler, http.
if timeNow == nil {
timeNow = time.Now
}
h := &handler{DB: dbi, Team: team, Validator: mv, Provider: MockProviderClient{}, TimeNow: timeNow}
h := &handler{Config: &core.Config{}, DB: dbi, Team: team, Validator: mv, Provider: MockProviderClient{}, TimeNow: timeNow}
action(h, h.BuildRouter(), mv, resources, assets)
})
}
Expand Down
28 changes: 28 additions & 0 deletions internal/core/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/******************************************************************************
*
* Copyright 2020 SAP SE
*
* 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 core

import (
"github.com/sapcc/castellum/internal/db"
)

//Config contains the app-level configuration options.
type Config struct {
MaxAssetSize map[db.AssetType]*uint64
}
36 changes: 33 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,36 @@ func main() {
logg.Fatal(err.Error())
}

//get max asset sizes
cfg := core.Config{
MaxAssetSize: make(map[db.AssetType]*uint64),
}
maxAssetSizes := strings.Split(mustGetenv("CASTELLUM_MAX_ASSET_SIZES"), ",")
for _, v := range maxAssetSizes {
sL := strings.Split(v, "=")
if len(sL) != 2 {
logg.Fatal("expected a max asset size configuration value in the format: '<asset-type>:<max-asset-size>', got: %s", v)
}
assetType := sL[0]
maxSize, err := strconv.ParseUint(sL[1], 10, 64)
if err != nil {
logg.Fatal(err.Error())
}

found := false
for _, assetManager := range team {
for _, info := range assetManager.AssetTypes() {
if assetType == string(info.AssetType) {
found = true
cfg.MaxAssetSize[info.AssetType] = &maxSize
}
}
}
if !found {
logg.Fatal("unknown asset type: %s", assetType)
}
}

if len(os.Args) < 2 {
usage()
}
Expand All @@ -112,7 +142,7 @@ func main() {
if len(os.Args) != 2 {
usage()
}
runAPI(dbi, team, providerClient, eo, httpListenAddr)
runAPI(&cfg, dbi, team, providerClient, eo, httpListenAddr)
case "observer":
if len(os.Args) != 2 {
usage()
Expand Down Expand Up @@ -144,7 +174,7 @@ func mustGetenv(key string) string {
////////////////////////////////////////////////////////////////////////////////
// task: API

func runAPI(dbi *gorp.DbMap, team core.AssetManagerTeam, providerClient *core.ProviderClient, eo gophercloud.EndpointOpts, httpListenAddr string) {
func runAPI(cfg *core.Config, dbi *gorp.DbMap, team core.AssetManagerTeam, providerClient *core.ProviderClient, eo gophercloud.EndpointOpts, httpListenAddr string) {
tv := gopherpolicy.TokenValidator{
IdentityV3: providerClient.KeystoneV3,
Cacher: gopherpolicy.InMemoryCacher(),
Expand All @@ -157,7 +187,7 @@ func runAPI(dbi *gorp.DbMap, team core.AssetManagerTeam, providerClient *core.Pr
//wrap the main API handler in several layers of middleware (CORS is
//deliberately the outermost middleware, to exclude preflight checks from
//logging)
handler := api.NewHandler(dbi, team, &tv, providerClient)
handler := api.NewHandler(cfg, dbi, team, &tv, providerClient)
handler = logg.Middleware{}.Wrap(handler)
handler = cors.New(cors.Options{
AllowedOrigins: []string{"*"},
Expand Down

0 comments on commit 1448449

Please sign in to comment.