diff --git a/objects/address/service.go b/objects/address/service.go index 12a5115..ee3241b 100644 --- a/objects/address/service.go +++ b/objects/address/service.go @@ -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 } @@ -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() @@ -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 } @@ -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. @@ -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() @@ -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() @@ -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 -}