From 1da13c00fbdde41f27edcda1e6c54676c5624c62 Mon Sep 17 00:00:00 2001 From: Yury Tsarev Date: Wed, 12 Feb 2020 09:57:56 +0100 Subject: [PATCH] CRUD operations for zone_delegated (#85) * Initial ZoneDelegated management * Implement UpdateZoneDelegated * Fqdn update is forbidden so only `delegate_to` is in action * DeleteZoneDelegated * GetZoneDelegated by Fqdn * Add GetZoneDelegated tests * Return nil when fqdn is empty With empty object API return list of all existing zones and GetZoneDelegated was picking first from the slice. It could lead to dangerous situation when we are dealing with completely unrelated Ref in further api interactions * No EA required for ZoneDelegated It actually breaks creation in e2e test * Unit tests for UpdateZoneDelegated * Test UpdateZoneDelegated * Reposition test case closer to common semantics * Finalize tests for ZoneDelegated --- object_manager.go | 74 +++++++++++++++++++---- object_manager_test.go | 129 ++++++++++++++++++++++++++++++++++++++--- objects.go | 22 +++++++ objects_test.go | 19 ++++++ 4 files changed, 225 insertions(+), 19 deletions(-) diff --git a/object_manager.go b/object_manager.go index e2a565e4..ae8aba4b 100644 --- a/object_manager.go +++ b/object_manager.go @@ -49,7 +49,6 @@ type ObjectManager struct { tenantID string } - func NewObjectManager(connector IBConnector, cmpType string, tenantID string) *ObjectManager { objMgr := new(ObjectManager) @@ -68,10 +67,10 @@ func (objMgr *ObjectManager) getBasicEA(cloudAPIOwned Bool) EA { return ea } -func (objMgr *ObjectManager) extendEA(ea EA) EA{ +func (objMgr *ObjectManager) extendEA(ea EA) EA { eas := objMgr.getBasicEA(true) - for k,v :=range ea{ - eas[k]=v + for k, v := range ea { + eas[k] = v } return eas } @@ -284,7 +283,7 @@ func (objMgr *ObjectManager) AllocateIP(netview string, cidr string, ipAddr stri Cidr: cidr, Mac: macAddress, Name: name, - Ea: eas}) + Ea: eas}) if ipAddr == "" { fixedAddr.IPAddress = fmt.Sprintf("func:nextavailableip:%s,%s", cidr, netview) @@ -381,7 +380,7 @@ func (objMgr *ObjectManager) UpdateFixedAddress(fixedAddrRef string, matchClient if validateMatchClient(matchClient) { updateFixedAddr.MatchClient = matchClient } else { - return nil , fmt.Errorf("wrong value for match_client passed %s \n ", matchClient) + return nil, fmt.Errorf("wrong value for match_client passed %s \n ", matchClient) } } @@ -514,7 +513,6 @@ func (objMgr *ObjectManager) CreateARecord(netview string, dnsview string, recor eas := objMgr.extendEA(ea) - recordA := NewRecordA(RecordA{ View: dnsview, Name: recordname, @@ -539,7 +537,7 @@ func (objMgr *ObjectManager) DeleteARecord(ref string) (string, error) { return objMgr.connector.DeleteObject(ref) } -func (objMgr *ObjectManager) CreateCNAMERecord(canonical string, recordname string, dnsview string, ea EA)(*RecordCNAME, error) { +func (objMgr *ObjectManager) CreateCNAMERecord(canonical string, recordname string, dnsview string, ea EA) (*RecordCNAME, error) { eas := objMgr.extendEA(ea) @@ -547,7 +545,7 @@ func (objMgr *ObjectManager) CreateCNAMERecord(canonical string, recordname stri View: dnsview, Name: recordname, Canonical: canonical, - Ea: eas}) + Ea: eas}) ref, err := objMgr.connector.CreateObject(recordCNAME) recordCNAME.Ref = ref @@ -566,10 +564,8 @@ func (objMgr *ObjectManager) DeleteCNAMERecord(ref string) (string, error) { func (objMgr *ObjectManager) CreatePTRRecord(netview string, dnsview string, recordname string, cidr string, ipAddr string, ea EA) (*RecordPTR, error) { - eas := objMgr.extendEA(ea) - recordPTR := NewRecordPTR(RecordPTR{ View: dnsview, PtrdName: recordname, @@ -677,3 +673,59 @@ func (objMgr *ObjectManager) GetGridInfo() ([]Grid, error) { err := objMgr.connector.GetObject(gridObj, "", &res) return res, err } + +// GetZoneAuth returns the authoritatives zones +func (objMgr *ObjectManager) GetZoneAuth() ([]ZoneAuth, error) { + var res []ZoneAuth + + zoneAuth := NewZoneAuth(ZoneAuth{}) + err := objMgr.connector.GetObject(zoneAuth, "", &res) + + return res, err +} + +// GetZoneDelegated returns the delegated zone +func (objMgr *ObjectManager) GetZoneDelegated(fqdn string) (*ZoneDelegated, error) { + if len(fqdn) == 0 { + return nil, nil + } + var res []ZoneDelegated + + zoneDelegated := NewZoneDelegated(ZoneDelegated{Fqdn: fqdn}) + + err := objMgr.connector.GetObject(zoneDelegated, "", &res) + + if err != nil || res == nil || len(res) == 0 { + return nil, err + } + + return &res[0], nil +} + +// CreateZoneDelegated creates delegated zone +func (objMgr *ObjectManager) CreateZoneDelegated(fqdn string, delegate_to []NameServer) (*ZoneDelegated, error) { + zoneDelegated := NewZoneDelegated(ZoneDelegated{ + Fqdn: fqdn, + DelegateTo: delegate_to}) + + ref, err := objMgr.connector.CreateObject(zoneDelegated) + zoneDelegated.Ref = ref + + return zoneDelegated, err +} + +// UpdateZoneDelegated updates delegated zone +func (objMgr *ObjectManager) UpdateZoneDelegated(ref string, delegate_to []NameServer) (*ZoneDelegated, error) { + zoneDelegated := NewZoneDelegated(ZoneDelegated{ + Ref: ref, + DelegateTo: delegate_to}) + + refResp, err := objMgr.connector.UpdateObject(zoneDelegated, ref) + zoneDelegated.Ref = refResp + return zoneDelegated, err +} + +// DeleteZoneDelegated deletes delegated zone +func (objMgr *ObjectManager) DeleteZoneDelegated(ref string) (string, error) { + return objMgr.connector.DeleteObject(ref) +} diff --git a/object_manager_test.go b/object_manager_test.go index b940bd8e..e0b3c3c4 100644 --- a/object_manager_test.go +++ b/object_manager_test.go @@ -59,6 +59,8 @@ func (c *fakeConnector) GetObject(obj IBObject, ref string, res interface{}) (er *res.(*[]License) = c.resultObject.([]License) case *HostRecord: *res.(*[]HostRecord) = c.resultObject.([]HostRecord) + case *ZoneDelegated: + *res.(*[]ZoneDelegated) = c.resultObject.([]ZoneDelegated) } } else { switch obj.(type) { @@ -323,7 +325,7 @@ var _ = Describe("Object Manager", func() { } objMgr := NewObjectManager(aniFakeConnector, cmpType, tenantID) - + ea := objMgr.getBasicEA(true) aniFakeConnector.createObjectObj.(*FixedAddress).Ea = ea aniFakeConnector.createObjectObj.(*FixedAddress).Ea["VM ID"] = vmID @@ -391,7 +393,7 @@ var _ = Describe("Object Manager", func() { } objMgr := NewObjectManager(aniFakeConnector, cmpType, tenantID) - + ea := objMgr.getBasicEA(true) aniFakeConnector.createObjectObj.(*HostRecord).Ea = ea aniFakeConnector.createObjectObj.(*HostRecord).Ea["VM ID"] = vmID @@ -665,7 +667,7 @@ var _ = Describe("Object Manager", func() { } objMgr := NewObjectManager(aniFakeConnector, cmpType, tenantID) - + ea := objMgr.getBasicEA(true) aniFakeConnector.createObjectObj.(*RecordA).Ea = ea aniFakeConnector.createObjectObj.(*RecordA).Ea["VM ID"] = vmID @@ -785,7 +787,7 @@ var _ = Describe("Object Manager", func() { } objMgr := NewObjectManager(aniFakeConnector, cmpType, tenantID) - + ea := objMgr.getBasicEA(true) aniFakeConnector.createObjectObj.(*RecordPTR).Ea = ea aniFakeConnector.createObjectObj.(*RecordPTR).Ea["VM ID"] = vmID @@ -795,7 +797,7 @@ var _ = Describe("Object Manager", func() { aniFakeConnector.resultObject.(*RecordPTR).Ea["VM ID"] = vmID aniFakeConnector.resultObject.(*RecordPTR).Ea["VM Name"] = vmName - aniFakeConnector.getObjectObj.(*RecordPTR).Ea = ea + aniFakeConnector.getObjectObj.(*RecordPTR).Ea = ea aniFakeConnector.getObjectObj.(*RecordPTR).Ea["VM ID"] = vmID aniFakeConnector.getObjectObj.(*RecordPTR).Ea["VM Name"] = vmName @@ -855,7 +857,7 @@ var _ = Describe("Object Manager", func() { aniFakeConnector.resultObject.(*RecordPTR).Ea["VM ID"] = vmID aniFakeConnector.resultObject.(*RecordPTR).Ea["VM Name"] = vmName - aniFakeConnector.getObjectObj.(*RecordPTR).Ea = ea + aniFakeConnector.getObjectObj.(*RecordPTR).Ea = ea aniFakeConnector.getObjectObj.(*RecordPTR).Ea["VM ID"] = vmID aniFakeConnector.getObjectObj.(*RecordPTR).Ea["VM Name"] = vmName @@ -912,13 +914,13 @@ var _ = Describe("Object Manager", func() { aniFakeConnector.resultObject.(*RecordCNAME).Ea["VM ID"] = vmID aniFakeConnector.resultObject.(*RecordCNAME).Ea["VM Name"] = vmName - aniFakeConnector.getObjectObj.(*RecordCNAME).Ea = ea + aniFakeConnector.getObjectObj.(*RecordCNAME).Ea = ea aniFakeConnector.getObjectObj.(*RecordCNAME).Ea["VM ID"] = vmID aniFakeConnector.getObjectObj.(*RecordCNAME).Ea["VM Name"] = vmName var actualRecord *RecordCNAME var err error It("should pass expected CNAME record Object to CreateObject", func() { - actualRecord, err = objMgr.CreateCNAMERecord(canonical, recordName, dnsView,ea) + actualRecord, err = objMgr.CreateCNAMERecord(canonical, recordName, dnsView, ea) }) It("should return expected CNAME record Object", func() { Expect(actualRecord).To(Equal(aniFakeConnector.resultObject)) @@ -1532,4 +1534,115 @@ var _ = Describe("Object Manager", func() { Expect(err).To(BeNil()) }) }) + + Describe("Get Zone Delegated", func() { + cmpType := "Docker" + tenantID := "01234567890abcdef01234567890abcdef" + fqdn := "dzone.example.com" + fakeRefReturn := "zone_delegated/ZG5zLnpvbmUkLl9kZWZhdWx0LnphLmNvLmFic2EuY2Fhcy5vaG15Z2xiLmdzbGJpYmNsaWVudA:dzone.example.com/default" + zdFakeConnector := &fakeConnector{ + getObjectObj: NewZoneDelegated(ZoneDelegated{Fqdn: fqdn}), + getObjectRef: "", + resultObject: []ZoneDelegated{*NewZoneDelegated(ZoneDelegated{Fqdn: fqdn, Ref: fakeRefReturn})}, + } + + objMgr := NewObjectManager(zdFakeConnector, cmpType, tenantID) + + var actualZoneDelegated *ZoneDelegated + var err error + It("should pass expected ZoneDelegated Object to GetObject", func() { + actualZoneDelegated, err = objMgr.GetZoneDelegated(fqdn) + }) + It("should return expected ZoneDelegated Object", func() { + Expect(*actualZoneDelegated).To(Equal(zdFakeConnector.resultObject.([]ZoneDelegated)[0])) + Expect(err).To(BeNil()) + }) + It("should return nil if fqdn is empty", func() { + zdFakeConnector.getObjectObj.(*ZoneDelegated).Fqdn = "" + actualZoneDelegated, err = objMgr.GetZoneDelegated("") + Expect(actualZoneDelegated).To(BeNil()) + Expect(err).To(BeNil()) + }) + }) + + Describe("Create Zone Delegated", func() { + cmpType := "Docker" + tenantID := "01234567890abcdef01234567890abcdef" + fqdn := "dzone.example.com" + delegateTo := []NameServer{ + {Address: "10.0.0.1", Name: "test1.dzone.example.com"}, + {Address: "10.0.0.2", Name: "test2.dzone.example.com"}} + fakeRefReturn := "zone_delegated/ZG5zLnpvbmUkLl9kZWZhdWx0LnphLmNvLmFic2EuY2Fhcy5vaG15Z2xiLmdzbGJpYmNsaWVudA:dzone.example.com/default" + zdFakeConnector := &fakeConnector{ + createObjectObj: NewZoneDelegated(ZoneDelegated{Fqdn: fqdn, DelegateTo: delegateTo}), + resultObject: NewZoneDelegated(ZoneDelegated{Fqdn: fqdn, DelegateTo: delegateTo, Ref: fakeRefReturn}), + fakeRefReturn: fakeRefReturn, + } + + objMgr := NewObjectManager(zdFakeConnector, cmpType, tenantID) + + var actualZoneDelegated *ZoneDelegated + var err error + It("should pass expected ZoneDelegated Object to CreateObject", func() { + actualZoneDelegated, err = objMgr.CreateZoneDelegated(fqdn, delegateTo) + }) + It("should return expected ZoneDelegated Object", func() { + Expect(actualZoneDelegated).To(Equal(zdFakeConnector.resultObject)) + Expect(err).To(BeNil()) + }) + }) + + Describe("Update Zone Delegated", func() { + cmpType := "Docker" + tenantID := "01234567890abcdef01234567890abcdef" + fakeRefReturn := "zone_delegated/ZG5zLnpvbmUkLl9kZWZhdWx0LnphLmNvLmFic2EuY2Fhcy5vaG15Z2xiLmdzbGJpYmNsaWVudA:dzone.example.com/default" + delegateTo := []NameServer{ + {Address: "10.0.0.1", Name: "test1.dzone.example.com"}, + {Address: "10.0.0.2", Name: "test2.dzone.example.com"}} + + receiveUpdateObject := NewZoneDelegated(ZoneDelegated{Ref: fakeRefReturn, DelegateTo: delegateTo}) + returnUpdateObject := NewZoneDelegated(ZoneDelegated{DelegateTo: delegateTo, Ref: fakeRefReturn}) + zdFakeConnector := &fakeConnector{ + fakeRefReturn: fakeRefReturn, + resultObject: returnUpdateObject, + updateObjectObj: receiveUpdateObject, + updateObjectRef: fakeRefReturn, + } + + objMgr := NewObjectManager(zdFakeConnector, cmpType, tenantID) + + var updatedObject *ZoneDelegated + var err error + It("should pass expected updated object to UpdateObject", func() { + updatedObject, err = objMgr.UpdateZoneDelegated(fakeRefReturn, delegateTo) + }) + It("should update zone with new delegation server list with no error", func() { + Expect(updatedObject).To(Equal(returnUpdateObject)) + Expect(err).To(BeNil()) + }) + }) + + Describe("Delete ZoneDelegated", func() { + cmpType := "Docker" + tenantID := "01234567890abcdef01234567890abcdef" + deleteRef := "zone_delegated/ZG5zLnpvbmUkLl9kZWZhdWx0LnphLmNvLmFic2EuY2Fhcy5vaG15Z2xiLmdzbGJpYmNsaWVudA:dzone.example.com/default" + fakeRefReturn := deleteRef + zdFakeConnector := &fakeConnector{ + deleteObjectRef: deleteRef, + fakeRefReturn: fakeRefReturn, + } + + objMgr := NewObjectManager(zdFakeConnector, cmpType, tenantID) + + var actualRef string + var err error + It("should pass expected ZoneDelegated Ref to DeleteObject", func() { + actualRef, err = objMgr.DeleteZoneDelegated(deleteRef) + }) + It("should return expected ZoneDelegated Ref", func() { + Expect(actualRef).To(Equal(fakeRefReturn)) + Expect(err).To(BeNil()) + }) + }) + }) diff --git a/objects.go b/objects.go index 297ad1bb..847028eb 100644 --- a/objects.go +++ b/objects.go @@ -475,6 +475,28 @@ func NewZoneAuth(za ZoneAuth) *ZoneAuth { return &res } +type NameServer struct { + Address string `json:"address,omitempty"` + Name string `json:"name,omitempty"` +} + +type ZoneDelegated struct { + IBBase `json:"-"` + Ref string `json:"_ref,omitempty"` + Fqdn string `json:"fqdn,omitempty"` + DelegateTo []NameServer `json:"delegate_to,omitempty"` + View string `json:"view,omitempty"` + Ea EA `json:"extattrs,omitempty"` +} + +func NewZoneDelegated(za ZoneDelegated) *ZoneDelegated { + res := za + res.objectType = "zone_delegated" + res.returnFields = []string{"extattrs", "fqdn", "view"} + + return &res +} + func (ea EA) MarshalJSON() ([]byte, error) { m := make(map[string]interface{}) for k, v := range ea { diff --git a/objects_test.go b/objects_test.go index 32179beb..d6d96518 100644 --- a/objects_test.go +++ b/objects_test.go @@ -477,6 +477,25 @@ var _ = Describe("Objects", func() { }) }) + Context("ZoneDelegated object", func() { + fqdn := "delegated_zone.domain.com" + view := "default" + + za := NewZoneDelegated(ZoneDelegated{ + Fqdn: fqdn, + View: view}) + + It("should set fields correctly", func() { + Expect(za.Fqdn).To(Equal(fqdn)) + Expect(za.View).To(Equal(view)) + }) + + It("should set base fields correctly", func() { + Expect(za.ObjectType()).To(Equal("zone_delegated")) + Expect(za.ReturnFields()).To(ConsistOf("extattrs", "fqdn", "view")) + }) + }) + }) Context("Unmarshalling malformed JSON", func() {