[#364] Support placement policy overriding

Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
Denis Kirillov 2022-03-03 15:43:56 +03:00 committed by LeL
parent 4454821285
commit 6a4fba4d09
2 changed files with 54 additions and 69 deletions

View file

@ -54,8 +54,7 @@ type (
// IssueSecretOptions contains options for passing to Agent.IssueSecret method.
IssueSecretOptions struct {
ContainerID *cid.ID
ContainerFriendlyName string
Container ContainerOptions
NeoFSKey *keys.PrivateKey
GatesPublicKeys []*keys.PublicKey
EACLRules []byte
@ -65,6 +64,13 @@ type (
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 struct {
SecretAddress string
@ -98,14 +104,14 @@ type (
}
)
func (a *Agent) checkContainer(ctx context.Context, cid *cid.ID, friendlyName string) (*cid.ID, error) {
if cid != nil {
func (a *Agent) checkContainer(ctx context.Context, opts ContainerOptions) (*cid.ID, error) {
if opts.ID != nil {
// check that container exists
_, err := a.pool.GetContainer(ctx, cid)
return cid, err
_, err := a.pool.GetContainer(ctx, opts.ID)
return opts.ID, err
}
pp, err := buildPlacementPolicy("")
pp, err := policy.Parse(opts.PlacementPolicy)
if err != nil {
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.WithAttribute(container.AttributeTimestamp, strconv.FormatInt(time.Now().Unix(), 10)),
}
if friendlyName != "" {
cnrOptions = append(cnrOptions, container.WithAttribute(container.AttributeName, friendlyName))
if opts.FriendlyName != "" {
cnrOptions = append(cnrOptions, container.WithAttribute(container.AttributeName, opts.FriendlyName))
}
cnr := container.New(cnrOptions...)
if friendlyName != "" {
container.SetNativeName(cnr, friendlyName)
if opts.FriendlyName != "" {
container.SetNativeName(cnr, opts.FriendlyName)
}
cid, err = a.pool.PutContainer(ctx, cnr)
cnrID, err := a.pool.PutContainer(ctx, cnr)
if err != nil {
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 cid, nil
return cnrID, nil
}
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
}
a.log.Info("check container", zap.Stringer("cid", options.ContainerID))
if cid, err = a.checkContainer(ctx, options.ContainerID, options.ContainerFriendlyName); err != nil {
a.log.Info("check container or create", zap.Stringer("cid", options.Container.ID),
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
}
@ -321,40 +329,6 @@ func (a *Agent) ObtainSecret(ctx context.Context, w io.Writer, options *ObtainSe
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) {
table := eacl.NewTable()
if len(eaclTable) != 0 {

View file

@ -41,6 +41,7 @@ var (
accessKeyIDFlag string
containerIDFlag string
containerFriendlyName string
containerPlacementPolicy string
gatesPublicKeysFlag cli.StringSlice
logEnabledFlag bool
logDebugEnabledFlag bool
@ -191,6 +192,13 @@ func issueSecret() *cli.Command {
Required: false,
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{
Name: "session-token",
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{
ContainerID: containerID,
ContainerFriendlyName: containerFriendlyName,
Container: authmate.ContainerOptions{
ID: containerID,
FriendlyName: containerFriendlyName,
PlacementPolicy: containerPlacementPolicy,
},
NeoFSKey: key,
GatesPublicKeys: gatesPublicKeys,
EACLRules: getJSONRules(eaclRulesFlag),