Skip to content

Commit

Permalink
refactoring basic service; Delete() now takes multiple names; removin…
Browse files Browse the repository at this point in the history
…g function that will exist in the panos provider
  • Loading branch information
shinmog committed Apr 9, 2024
1 parent 8de38b5 commit 300d091
Showing 1 changed file with 71 additions and 235 deletions.
306 changes: 71 additions & 235 deletions objects/address/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,49 +65,17 @@ func (s *Service) Create(ctx context.Context, loc Location, entry Entry) (*Entry
//
// Param action should be either "get" or "show".
func (s *Service) Read(ctx context.Context, loc Location, name, action string) (*Entry, error) {
if name == "" {
return nil, errors.NameNotSpecifiedError
}

vn := s.client.Versioning()
_, normalizer, err := Versioning(vn)
if err != nil {
return nil, err
}

path, err := loc.Xpath(vn, name)
if err != nil {
return nil, err
}

cmd := &xmlapi.Config{
Action: action,
Xpath: util.AsXpath(path),
Target: s.client.GetTarget(),
}

if _, _, err = s.client.Communicate(ctx, cmd, true, normalizer); err != nil {
// action=show returns empty config like this
if err.Error() == "No such node" && action == "show" {
return nil, errors.ObjectNotFound()
}
return nil, err
}

list, err := normalizer.Normalize()
if err != nil {
return nil, err
} else if len(list) != 1 {
return nil, fmt.Errorf("expected to %q 1 entry, got %d", action, len(list))
}

return &list[0], nil
return s.doRead(ctx, loc, name, action, true)
}

// ReadFromConfig returns the given config object from the loaded XML config.
//
// Requires that client.LoadPanosConfig() has been invoked.
func (s *Service) ReadFromConfig(ctx context.Context, loc Location, name string) (*Entry, error) {
return s.doRead(ctx, loc, name, "", false)
}

func (s *Service) doRead(ctx context.Context, loc Location, name, action string, fromPanos bool) (*Entry, error) {
if name == "" {
return nil, errors.NameNotSpecifiedError
}
Expand All @@ -123,8 +91,24 @@ func (s *Service) ReadFromConfig(ctx context.Context, loc Location, name string)
return nil, err
}

if _, err = s.client.ReadFromConfig(ctx, path, true, normalizer); err != nil {
return nil, err
if fromPanos {
cmd := &xmlapi.Config{
Action: action,
Xpath: util.AsXpath(path),
Target: s.client.GetTarget(),
}

if _, _, err := s.client.Communicate(ctx, cmd, true, normalizer); err != nil {
// action=show returns empty config like this
if err.Error() == "No such node" && action == "show" {
return nil, errors.ObjectNotFound()
}
return nil, err
}
} else {
if _, err := s.client.ReadFromConfig(ctx, path, true, normalizer); err != nil {
return nil, err
}
}

list, err := normalizer.Normalize()
Expand Down Expand Up @@ -207,26 +191,34 @@ func (s *Service) Update(ctx context.Context, loc Location, entry Entry, oldName
}

// Delete deletes the given item.
func (s *Service) Delete(ctx context.Context, loc Location, name string) error {
if name == "" {
return errors.NameNotSpecifiedError
func (s *Service) Delete(ctx context.Context, loc Location, names ...string) error {
if len(names) == 0 {
return nil
} else {
for _, name := range names {
if name == "" {
return errors.NameNotSpecifiedError
}
}
}

vn := s.client.Versioning()

path, err := loc.Xpath(vn, name)
if err != nil {
return err
}
updates := xmlapi.NewMultiConfig(len(names))
for _, name := range names {
path, err := loc.Xpath(vn, name)
if err != nil {
return err
}

cmd := &xmlapi.Config{
Action: "delete",
Xpath: util.AsXpath(path),
Target: s.client.GetTarget(),
updates.Add(&xmlapi.Config{
Action: "delete",
Xpath: util.AsXpath(path),
Target: s.client.GetTarget(),
})
}

_, _, err = s.client.Communicate(ctx, cmd, false, nil)

_, _, _, err := s.client.MultiConfig(ctx, updates, false, nil)
return err
}

Expand All @@ -236,59 +228,7 @@ func (s *Service) Delete(ctx context.Context, loc Location, name string) error {
//
// Params filter and quote are for client side filtering.
func (s *Service) List(ctx context.Context, loc Location, action, filter, quote string) ([]Entry, error) {
var err error

var logic *filtering.Group
if filter != "" {
logic, err = filtering.Parse(filter, quote)
if err != nil {
return nil, err
}
}

vn := s.client.Versioning()

_, normalizer, err := Versioning(vn)
if err != nil {
return nil, err
}

path, err := loc.Xpath(vn, "")
if err != nil {
return nil, err
}

cmd := &xmlapi.Config{
Action: action,
Xpath: util.AsXpath(path),
Target: s.client.GetTarget(),
}

if _, _, err = s.client.Communicate(ctx, cmd, true, normalizer); err != nil {
// action=show returns empty config like this, it is not an error.
if err.Error() == "No such node" && action == "show" {
return nil, nil
}
return nil, err
}

listing, err := normalizer.Normalize()
if err != nil || logic == nil {
return listing, err
}

filtered := make([]Entry, 0, len(listing))
for _, x := range listing {
ok, err := logic.Matches(&x)
if err != nil {
return nil, err
}
if ok {
filtered = append(filtered, x)
}
}

return filtered, nil
return s.doList(ctx, loc, action, filter, quote, true)
}

// ListFromConfig returns a list of objects at the given location.
Expand All @@ -297,14 +237,13 @@ func (s *Service) List(ctx context.Context, loc Location, action, filter, quote
//
// Params filter and quote are for client side filtering.
func (s *Service) ListFromConfig(ctx context.Context, loc Location, filter, quote string) ([]Entry, error) {
var err error
return s.doList(ctx, loc, "", filter, quote, false)
}

var logic *filtering.Group
if filter != "" {
logic, err = filtering.Parse(filter, quote)
if err != nil {
return nil, err
}
func (s *Service) doList(ctx context.Context, loc Location, action, filter, quote string, fromPanos bool) ([]Entry, error) {
logic, err := filtering.Parse(filter, quote)
if err != nil {
return nil, err
}

vn := s.client.Versioning()
Expand All @@ -318,10 +257,27 @@ func (s *Service) ListFromConfig(ctx context.Context, loc Location, filter, quot
if err != nil {
return nil, err
}
path = path[:len(path)-1]

if _, err = s.client.ReadFromConfig(ctx, path, false, normalizer); err != nil {
return nil, err
if fromPanos {
cmd := &xmlapi.Config{
Action: action,
Xpath: util.AsXpath(path),
Target: s.client.GetTarget(),
}

if _, _, err = s.client.Communicate(ctx, cmd, true, normalizer); err != nil {
// action=show returns empty config like this, it is not an error.
if err.Error() == "No such node" && action == "show" {
return nil, nil
}
return nil, err
}
} else {
path = path[:len(path)-1]

if _, err = s.client.ReadFromConfig(ctx, path, false, normalizer); err != nil {
return nil, err
}
}

listing, err := normalizer.Normalize()
Expand All @@ -342,123 +298,3 @@ func (s *Service) ListFromConfig(ctx context.Context, loc Location, filter, quot

return filtered, nil
}

// ConfigureGroup performs all necessary set / edit / delete commands to ensure that the
// objects are configured as specified.
func (s *Service) ConfigureGroup(ctx context.Context, loc Location, entries []Entry, prevNames []string) ([]Entry, error) {
var err error

vn := s.client.Versioning()
updates := xmlapi.NewMultiConfig(len(prevNames) + len(entries))
specifier, _, err := Versioning(vn)
if err != nil {
return nil, err
}

curObjs, err := s.List(ctx, loc, "get", "", "")
if err != nil {
return nil, err
}

//unfound := make([]Entry, 0, len(entries))

// Determine set vs edit for desired objects.
for _, entry := range entries {
var found bool
for _, live := range curObjs {
if entry.Name == live.Name {
found = true
if !SpecMatches(&entry, &live) {
path, err := loc.Xpath(vn, entry.Name)
if err != nil {
return nil, err
}

// Copy over the misc stuff.
entry.CopyMiscFrom(&live)

elm, err := specifier(entry)
if err != nil {
return nil, err
}

updates.Add(&xmlapi.Config{
Action: "edit",
Xpath: util.AsXpath(path),
Element: elm,
})
}
break
}
}

if !found {
path, err := loc.Xpath(vn, entry.Name)
if err != nil {
return nil, err
}

elm, err := specifier(entry)
if err != nil {
return nil, err
}

updates.Add(&xmlapi.Config{
Action: "set",
Xpath: util.AsXpath(path),
Element: elm,
})
}
}

// Determine which old objects need to be removed.
if len(prevNames) != 0 {
for _, name := range prevNames {
var found bool
for _, entry := range entries {
if entry.Name == name {
found = true
break
}
}

if !found {
path, err := loc.Xpath(vn, name)
if err != nil {
return nil, err
}

updates.Add(&xmlapi.Config{
Action: "delete",
Xpath: util.AsXpath(path),
})
}
}
}

// Perform the multi-config if there was stuff to do.
if len(updates.Operations) != 0 {
if _, _, _, err = s.client.MultiConfig(ctx, updates, false, nil); err != nil {
return nil, err
}
}

// Get the live version of the entries passed in.
curObjs, err = s.List(ctx, loc, "get", "", "")
if err != nil {
return nil, err
}

ans := make([]Entry, 0, len(entries))
for _, entry := range entries {
for _, live := range curObjs {
if entry.Name == live.Name {
ans = append(ans, live)
break
}
}
}

// Done.
return ans, nil
}

0 comments on commit 300d091

Please sign in to comment.