forked from TrueCloudLab/frostfs-s3-gw
[#364] Support placement policy overriding
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
parent
4454821285
commit
6a4fba4d09
2 changed files with 54 additions and 69 deletions
|
@ -54,8 +54,7 @@ type (
|
||||||
|
|
||||||
// IssueSecretOptions contains options for passing to Agent.IssueSecret method.
|
// IssueSecretOptions contains options for passing to Agent.IssueSecret method.
|
||||||
IssueSecretOptions struct {
|
IssueSecretOptions struct {
|
||||||
ContainerID *cid.ID
|
Container ContainerOptions
|
||||||
ContainerFriendlyName string
|
|
||||||
NeoFSKey *keys.PrivateKey
|
NeoFSKey *keys.PrivateKey
|
||||||
GatesPublicKeys []*keys.PublicKey
|
GatesPublicKeys []*keys.PublicKey
|
||||||
EACLRules []byte
|
EACLRules []byte
|
||||||
|
@ -65,6 +64,13 @@ type (
|
||||||
ContainerPolicies ContainerPolicies
|
ContainerPolicies ContainerPolicies
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ContainerOptions groups parameters of auth container to put the secret into.
|
||||||
|
ContainerOptions struct {
|
||||||
|
ID *cid.ID
|
||||||
|
FriendlyName string
|
||||||
|
PlacementPolicy string
|
||||||
|
}
|
||||||
|
|
||||||
// ObtainSecretOptions contains options for passing to Agent.ObtainSecret method.
|
// ObtainSecretOptions contains options for passing to Agent.ObtainSecret method.
|
||||||
ObtainSecretOptions struct {
|
ObtainSecretOptions struct {
|
||||||
SecretAddress string
|
SecretAddress string
|
||||||
|
@ -98,14 +104,14 @@ type (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *Agent) checkContainer(ctx context.Context, cid *cid.ID, friendlyName string) (*cid.ID, error) {
|
func (a *Agent) checkContainer(ctx context.Context, opts ContainerOptions) (*cid.ID, error) {
|
||||||
if cid != nil {
|
if opts.ID != nil {
|
||||||
// check that container exists
|
// check that container exists
|
||||||
_, err := a.pool.GetContainer(ctx, cid)
|
_, err := a.pool.GetContainer(ctx, opts.ID)
|
||||||
return cid, err
|
return opts.ID, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pp, err := buildPlacementPolicy("")
|
pp, err := policy.Parse(opts.PlacementPolicy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to build placement policy: %w", err)
|
return nil, fmt.Errorf("failed to build placement policy: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -115,24 +121,24 @@ func (a *Agent) checkContainer(ctx context.Context, cid *cid.ID, friendlyName st
|
||||||
container.WithCustomBasicACL(defaultAuthContainerBasicACL),
|
container.WithCustomBasicACL(defaultAuthContainerBasicACL),
|
||||||
container.WithAttribute(container.AttributeTimestamp, strconv.FormatInt(time.Now().Unix(), 10)),
|
container.WithAttribute(container.AttributeTimestamp, strconv.FormatInt(time.Now().Unix(), 10)),
|
||||||
}
|
}
|
||||||
if friendlyName != "" {
|
if opts.FriendlyName != "" {
|
||||||
cnrOptions = append(cnrOptions, container.WithAttribute(container.AttributeName, friendlyName))
|
cnrOptions = append(cnrOptions, container.WithAttribute(container.AttributeName, opts.FriendlyName))
|
||||||
}
|
}
|
||||||
|
|
||||||
cnr := container.New(cnrOptions...)
|
cnr := container.New(cnrOptions...)
|
||||||
if friendlyName != "" {
|
if opts.FriendlyName != "" {
|
||||||
container.SetNativeName(cnr, friendlyName)
|
container.SetNativeName(cnr, opts.FriendlyName)
|
||||||
}
|
}
|
||||||
|
|
||||||
cid, err = a.pool.PutContainer(ctx, cnr)
|
cnrID, err := a.pool.PutContainer(ctx, cnr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.pool.WaitForContainerPresence(ctx, cid, pool.DefaultPollingParams()); err != nil {
|
if err := a.pool.WaitForContainerPresence(ctx, cnrID, pool.DefaultPollingParams()); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return cid, nil
|
return cnrID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) getEpochDurations(ctx context.Context) (*epochDurations, error) {
|
func (a *Agent) getEpochDurations(ctx context.Context) (*epochDurations, error) {
|
||||||
|
@ -235,8 +241,10 @@ func (a *Agent) IssueSecret(ctx context.Context, w io.Writer, options *IssueSecr
|
||||||
lifetime.Exp = lifetime.Iat + epochLifetime
|
lifetime.Exp = lifetime.Iat + epochLifetime
|
||||||
}
|
}
|
||||||
|
|
||||||
a.log.Info("check container", zap.Stringer("cid", options.ContainerID))
|
a.log.Info("check container or create", zap.Stringer("cid", options.Container.ID),
|
||||||
if cid, err = a.checkContainer(ctx, options.ContainerID, options.ContainerFriendlyName); err != nil {
|
zap.String("friendly_name", options.Container.FriendlyName),
|
||||||
|
zap.String("placement_policy", options.Container.PlacementPolicy))
|
||||||
|
if cid, err = a.checkContainer(ctx, options.Container); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,40 +329,6 @@ func (a *Agent) ObtainSecret(ctx context.Context, w io.Writer, options *ObtainSe
|
||||||
return enc.Encode(or)
|
return enc.Encode(or)
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildPlacementPolicy(placementRules string) (*netmap.PlacementPolicy, error) {
|
|
||||||
if len(placementRules) != 0 {
|
|
||||||
return policy.Parse(placementRules)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
REP 2 IN X // place two copies of object
|
|
||||||
CBF 3
|
|
||||||
SELECT 2 From * AS X // in container of two nodes
|
|
||||||
*/
|
|
||||||
pp := new(netmap.PlacementPolicy)
|
|
||||||
pp.SetContainerBackupFactor(3)
|
|
||||||
pp.SetReplicas([]*netmap.Replica{newReplica("X", 2)}...)
|
|
||||||
pp.SetSelectors([]*netmap.Selector{newSimpleSelector("X", 2)}...)
|
|
||||||
|
|
||||||
return pp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// selects <count> nodes in container without any additional attributes.
|
|
||||||
func newSimpleSelector(name string, count uint32) (s *netmap.Selector) {
|
|
||||||
s = new(netmap.Selector)
|
|
||||||
s.SetCount(count)
|
|
||||||
s.SetFilter("*")
|
|
||||||
s.SetName(name)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func newReplica(name string, count uint32) (r *netmap.Replica) {
|
|
||||||
r = new(netmap.Replica)
|
|
||||||
r.SetCount(count)
|
|
||||||
r.SetSelector(name)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildEACLTable(cid *cid.ID, eaclTable []byte) (*eacl.Table, error) {
|
func buildEACLTable(cid *cid.ID, eaclTable []byte) (*eacl.Table, error) {
|
||||||
table := eacl.NewTable()
|
table := eacl.NewTable()
|
||||||
if len(eaclTable) != 0 {
|
if len(eaclTable) != 0 {
|
||||||
|
|
|
@ -32,23 +32,24 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
walletPathFlag string
|
walletPathFlag string
|
||||||
accountAddressFlag string
|
accountAddressFlag string
|
||||||
peerAddressFlag string
|
peerAddressFlag string
|
||||||
eaclRulesFlag string
|
eaclRulesFlag string
|
||||||
gateWalletPathFlag string
|
gateWalletPathFlag string
|
||||||
gateAccountAddressFlag string
|
gateAccountAddressFlag string
|
||||||
accessKeyIDFlag string
|
accessKeyIDFlag string
|
||||||
containerIDFlag string
|
containerIDFlag string
|
||||||
containerFriendlyName string
|
containerFriendlyName string
|
||||||
gatesPublicKeysFlag cli.StringSlice
|
containerPlacementPolicy string
|
||||||
logEnabledFlag bool
|
gatesPublicKeysFlag cli.StringSlice
|
||||||
logDebugEnabledFlag bool
|
logEnabledFlag bool
|
||||||
sessionTokenFlag string
|
logDebugEnabledFlag bool
|
||||||
lifetimeFlag time.Duration
|
sessionTokenFlag string
|
||||||
containerPolicies string
|
lifetimeFlag time.Duration
|
||||||
awcCliCredFile string
|
containerPolicies string
|
||||||
timeoutFlag time.Duration
|
awcCliCredFile string
|
||||||
|
timeoutFlag time.Duration
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -191,6 +192,13 @@ func issueSecret() *cli.Command {
|
||||||
Required: false,
|
Required: false,
|
||||||
Destination: &containerFriendlyName,
|
Destination: &containerFriendlyName,
|
||||||
},
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "container-placement-policy",
|
||||||
|
Usage: "placement policy of auth container to put the secret into",
|
||||||
|
Required: false,
|
||||||
|
Destination: &containerPlacementPolicy,
|
||||||
|
Value: "REP 2 IN X CBF 3 SELECT 2 FROM * AS X",
|
||||||
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "session-token",
|
Name: "session-token",
|
||||||
Usage: "create session token with rules, if the rules are set as 'none', no session tokens will be created",
|
Usage: "create session token with rules, if the rules are set as 'none', no session tokens will be created",
|
||||||
|
@ -264,8 +272,11 @@ It will be ceil rounded to the nearest amount of epoch.`,
|
||||||
}
|
}
|
||||||
|
|
||||||
issueSecretOptions := &authmate.IssueSecretOptions{
|
issueSecretOptions := &authmate.IssueSecretOptions{
|
||||||
ContainerID: containerID,
|
Container: authmate.ContainerOptions{
|
||||||
ContainerFriendlyName: containerFriendlyName,
|
ID: containerID,
|
||||||
|
FriendlyName: containerFriendlyName,
|
||||||
|
PlacementPolicy: containerPlacementPolicy,
|
||||||
|
},
|
||||||
NeoFSKey: key,
|
NeoFSKey: key,
|
||||||
GatesPublicKeys: gatesPublicKeys,
|
GatesPublicKeys: gatesPublicKeys,
|
||||||
EACLRules: getJSONRules(eaclRulesFlag),
|
EACLRules: getJSONRules(eaclRulesFlag),
|
||||||
|
|
Loading…
Reference in a new issue