From 2d4e733226f96fa17394c56dcd4bcc82a494e8cf Mon Sep 17 00:00:00 2001 From: lily Date: Tue, 5 Sep 2017 10:08:02 -0700 Subject: [PATCH 01/10] added netconf service (incomplete) to go - missing CopyConfig() and Validate() --- sdk/go/core/ydk/services/netconf_service.go | 308 ++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 sdk/go/core/ydk/services/netconf_service.go diff --git a/sdk/go/core/ydk/services/netconf_service.go b/sdk/go/core/ydk/services/netconf_service.go new file mode 100644 index 000000000..66f9b6391 --- /dev/null +++ b/sdk/go/core/ydk/services/netconf_service.go @@ -0,0 +1,308 @@ +/* + * ------------------------------------------------------------------ + * YANG Development Kit + * Copyright 2017 Cisco Systems. All rights reserved + * + *---------------------------------------------- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http:www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *---------------------------------------------- + */ +package services + +// #cgo CXXFLAGS: -g -std=c++11 +// #cgo darwin LDFLAGS: -fprofile-arcs -ftest-coverage -lydk -lxml2 -lxslt -lpcre -lssh -lssh_threads -lcurl -lpython -lc++ +// #cgo linux LDFLAGS: -fprofile-arcs -ftest-coverage --coverage -lydk -lxml2 -lxslt -lpcre -lssh -lssh_threads -lcurl -lstdc++ -lpython2.7 -ldl +// #include +// #include +import "C" + +import ( + "encoding/json" + "encoding/xml" + "strconv" + "fmt" + "errors" + "log" + "github.com/CiscoDevNet/ydk-go/ydk" + "github.com/CiscoDevNet/ydk-go/ydk/path" + "github.com/CiscoDevNet/ydk-go/ydk/types" +) + +const ( + Candidate int = iota + Running + StartUp + Url +) + +type NetconfService struct { +} + +func (ns *NetconfService) CancelCommit(provider NetconfServiceProvider, persistId int) bool { + var cstate C.YDKStatePtr = C.YDKStateCreate() + defer C.YDKStateFree(cstate) + + cancelCommitRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:cancel-commit") + if (persistId > 1) { + input := C.RpcInput(cstate, cancelCommitRpc) + persistIdStr := strconv.Itoa(persistId) + C.DataNodeCreate(cstate, input, "persist-id", C.CString(persistIdStr)) + } + + readData := C.RpcExecute(cstate, cancelCommitRpc, provider) + return readData == nil +} + +func (ns *NetconfService) CloseSession(provider NetconfServiceProvider) bool { + var cstate C.YDKStatePtr = C.YDKStateCreate() + defer C.YDKStateFree(cstate) + + closeSessionRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:close-session") + + readData := C.RpcExecute(cstate, closeSessionRpc, provider) + return readData == nil +} + +func (ns *NetconfService) Commit(provider NetconfServiceProvider, confirmed bool, confirmTimeOut, persist, persistId int) bool { + var cstate C.YDKStatePtr = C.YDKStateCreate() + defer C.YDKStateFree(cstate) + + commitRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:commit") + + if (confirmed) { + input := C.RpcInput(cstate, commitRpc) + C.DataNodeCreate(cstate, input, "confirmed", "") + } + + if (confirmTimeOut > -1) { + input := C.RpcInput(cstate, commitRpc) + confirmTimeOutStr := strconv.Itoa(confirmTimeOut) + C.DataNodeCreate(cstate, input, "confirm-timeout", confirmTimeOutStr) + } + + if (persist > -1) { + input := C.RpcInput(cstate, commitRpc) + persistStr := strconv.Itoa(persist) + C.DataNodeCreate(cstate, input, "persist", persistStr) + } + + if (persistId > -1) { + input := C.RpcInput(cstate, commitRpc) + persistIdStr := strconv.Itoa(persistId) + C.DataNodeCreate(cstate, input, "persist-id", persistIdStr) + } + + readData := C.RpcExecute(cstate, commitRpc, provider) + return readData == nil +} + +// TODO: figure out optional arguments +// func (ns *NetconfService) CopyConfig(provider NetconfServiceProvider, target, source int, url string) bool { +// } + +// func (ns *NetconfService) CopyConfig(provider NetconfServiceProvider, target int, source types.Entity) bool { +// } + +func (ns *NetconfService) DeleteConfig(provider NetconfServiceProvider, target int, url string) bool { + var cstate C.YDKStatePtr = C.YDKStateCreate() + defer C.YDKStateFree(cstate) + + deleteConfigRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:delete-config") + input := C.RpcInput(cstate, deleteConfigRpc) + + // target options: startup | url + createInputLeaf(cstate, input, target, "target", "") + + readData := C.RpcExecute(cstate, deleteConfigRpc, provider) + return readData == nil +} + +func (ns *NetconfService) DiscardChanges(provider NetconfServiceProvider) bool { + var cstate C.YDKStatePtr = C.YDKStateCreate() + defer C.YDKStateFree(cstate) + + discardChangesRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:discard-changes") + readData := C.RpcExecute(cstate, discardChangesRpc, provider) + return readData == nil +} + +// TODO +func (ns *NetconfService) EditConfig( + provider NetconfServiceProvider, target int, config types.Entity, defaultOper, testOp, errorOp string) bool { + var cstate C.YDKStatePtr = C.YDKStateCreate() + defer C.YDKStateFree(cstate) + + editConfigRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:edit-config") + // TODO +} + +// incomplete +func (ns *NetconfService) GetConfig(provider NetconfServiceProvider, source int, filter types.Entity) types.Entity { + var cstate C.YDKStatePtr = C.YDKStateCreate() + defer C.YDKStateFree(cstate) + + getConfigRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:get-config") + input := C.RpcInput(cstate, getConfigRpc) + + // source options: candidate | running | startup + createInputLeaf(cstate, input, source, "source") + + payload := getXmlSubtreeFilterPayload(cstate, entity, provider) + C.DataNodeCreate(cstate, input, "filter", payload) + + readData := C.RpcExecute(cstate, getConfigRpc, provider) + if (readData == nil) { + return nil + } + + topEntity := getTopEntityFromFilter(filter) + + // TODO: how to handle DataNodeChildren struct go? + node := C.DataNodeGetChildren(readData)[0] + getEntityFromDataNode(node, topEntity) + + return topEntity +} + +// incomplete +func (ns *NetconfService) Get(provider NetconfServiceProvider, filter types.Entity) bool { + var cstate C.YDKStatePtr = C.YDKStateCreate() + defer C.YDKStateFree(cstate) + + getRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:get") + input := C.RpcInput(cstate, getRpc) + + payload := getXmlSubtreeFilterPayload(cstate, entity, provider) + C.DataNodeCreate(cstate, input, "filter", payload) + + readData := C.RpcExecute(cstate, getConfigRpc, provider) + if (readData == nil) { + return nil + } + + topEntity := getTopEntityFromFilter(filter) + + // TODO: how to handle DataNodeChildren struct go? + node := C.DataNodeGetChildren(readData)[0] + getEntityFromDataNode(node, topEntity) + + return topEntity +} + +func (ns *NetconfService) KillSession(provider NetconfServiceProvider, sessionId int) bool { + var cstate C.YDKStatePtr = C.YDKStateCreate() + defer C.YDKStateFree(cstate) + + killSessionRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:kill-session") + input := C.RpcInput(cstate, killSessionRpc) + sessionIdStr := strconv.Itoa(sessionId) + C.DataNodeCreate(cstate, input, "session-id", sessionIdStr) + + readData := C.RpcExecute(cstate, killSessionRpc, provider) + return readData == nil +} + +func (ns *NetconfService) Lock(provider NetconfServiceProvider, target int) bool { + var cstate C.YDKStatePtr = C.YDKStateCreate() + defer C.YDKStateFree(cstate) + + lockRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:lock") + input := C.RpcInput(cstate, lockRpc) + + // target options: candidate | running | startup + createInputLeaf(cstate, input, target, "target", "") + + readData := C.RpcExecute(cstate, lockRpc, provider) + return readData == nil +} + +func (ns *NetconfService) Unlock(provider NetconfServiceProvider, target DataStore) bool { + var cstate C.YDKStatePtr = C.YDKStateCreate() + defer C.YDKStateFree(cstate) + + unlockRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:unlock") + input := C.RpcInput(cstate, unlockRpc) + + // target options: candidate | running | startup + createInputLeaf(cstate, input, target, "target", "") + + readData := C.RpcExecute(cstate, unlockRpc, provider) + return readData == nil +} + +// TODO: figure out optional arguments +// func (ns *NetconfService) Validate(provider NetconfServiceProvider, source DataStore, url string) bool { +// } + +// func (ns *NetconfService) Validate(provider NetconfServiceProvider, source DataStore) bool { +// } + +func getRpcFromProvider(cstate C.YDKStatePtr, provider NetconfServiceProvider, path string) C.Rpc { + rootSchemaNode := C.ServiceProviderGetRootSchema(cstate, provider) + rpc := C.RootSchemaNodeRpc(cstate, rootSchemaNode, C.CString(path)) + return rpc +} + +func createInputLeaf(cstate C.YDKStatePtr, inputDataNode C.DataNode, dataStore int, dataStoreStr string, url string) { + var path bytes.Buffer + path.WriteString(dataStoreStr) + + switch dataStore { + case Candidate: + path.WriteString("/candidate") + case Running: + path.WriteString("/running") + case StartUp: + path.WriteString("/startup") + case Url: + if (url == "") { + err := errors.New("URL needs to be specified") + log.Fatal(err) + } + path.WriteString("/url") + } + + C.DataNodeCreate(cstate, inputDataNode, path.String(), "") +} + +func getXmlSubtreeFilterPayload(cstate C.YDKStatePtr, entity types.Entity, provider NetconfServiceProvider) string { + // XmlSubTreeCodec* not imported or implemented!! + var xmlSubtreeCodec C.XmlSubtreeCodec = C.XmlSubtreeCodecCreate() + defer C.XmlSubtreeCodec(xmlSubtreeCodec) + + payload := xmlSubtreeCodecEncode(cstate, xmlSubtreeCodec, entity, provider) + return payload +} + +func getTopEntityFromFilter(filter types.Entity) types.Entity { + parent := filter.GetParent() + if (parent == nil) { + return filter.GetFilter() + } + return getTopEntityFromFilter(parent) +} + +// TODO +func getEntityFromDataNode(node C.DataNode, entity types.Entity) { + if (node == nil || entity == nil) { + return + } + + // not sure how this is supposed to work... + children := C.DataNodeGetChildren(node) +} From 0b6d038a707fcf151de1ddd8df13cfb59e360115 Mon Sep 17 00:00:00 2001 From: lily Date: Wed, 11 Oct 2017 09:14:26 -0700 Subject: [PATCH 02/10] added netconf service and tests in go --- sdk/go/core/docsgen/api/services/services.rst | 169 ++++++++- sdk/go/core/tests/netconf_service_test.go | 237 +++++++++++++ sdk/go/core/ydk/path/path.go | 24 +- sdk/go/core/ydk/services/netconf_service.go | 308 ---------------- sdk/go/core/ydk/services/services.go | 331 +++++++++++++++++- sdk/go/core/ydk/types/types.go | 11 + 6 files changed, 749 insertions(+), 331 deletions(-) create mode 100644 sdk/go/core/tests/netconf_service_test.go delete mode 100644 sdk/go/core/ydk/services/netconf_service.go diff --git a/sdk/go/core/docsgen/api/services/services.rst b/sdk/go/core/docsgen/api/services/services.rst index c57be46fc..46e04638b 100644 --- a/sdk/go/core/docsgen/api/services/services.rst +++ b/sdk/go/core/docsgen/api/services/services.rst @@ -13,7 +13,7 @@ CRUD Supports CRUD operations on entities. -.. function:: (provider *CrudService) Create(provider ServiceProvider, entity Entity) +.. function:: (c *CrudService) Create(provider ServiceProvider, entity Entity) Create the entity. @@ -22,7 +22,7 @@ CRUD :return: whether the operation was successful or not :rtype: ``bool`` -.. function:: (provider *CrudService) Update(provider ServiceProvider, entity Entity) +.. function:: (c *CrudService) Update(provider ServiceProvider, entity Entity) Update the entity. @@ -31,7 +31,7 @@ CRUD :return: whether the operation was successful or not :rtype: ``bool`` -.. function:: (provider *CrudService) Delete(provider ServiceProvider, entity Entity) +.. function:: (c *CrudService) Delete(provider ServiceProvider, entity Entity) Delete the entity. @@ -40,7 +40,7 @@ CRUD :return: whether the operation was successful or not :rtype: ``bool`` -.. function:: (provider *CrudService) Read(provider ServiceProvider, filter Entity) +.. function:: (c *CrudService) Read(provider ServiceProvider, filter Entity) Read the entity. @@ -49,7 +49,7 @@ CRUD :return: the entity as identified by the given filter :rtype: :go:struct:`Entity` -.. function:: (provider *CrudService) ReadConfig(provider ServiceProvider, filter Entity) +.. function:: (c *CrudService) ReadConfig(provider ServiceProvider, filter Entity) Read only config. @@ -66,7 +66,7 @@ Codec Supports encoding and decoding Go model API objects of type :go:struct:`Entity` -.. function:: (provider *CodecService) Encode(provider CodecServiceProvider, entity Entity) +.. function:: (c *CodecService) Encode(provider CodecServiceProvider, entity Entity) Encode converts entity object to XML/JSON payload @@ -75,7 +75,7 @@ Codec :return: encoded payload :rtype: A Go ``string`` -.. function:: (provider *CodecService) Decode(provider CodecServiceProvider, payload string) +.. function:: (c *CodecService) Decode(provider CodecServiceProvider, payload string) Decode converts XML/JSON object to entity object @@ -83,3 +83,158 @@ Codec :param payload: A Go ``string`` representing an encoded payload to decode :return: the decoded entity object :rtype: :go:struct:`Entity` + + +Netconf +------- + +.. go:struct:: NetconfService + + Implements the NETCONF Protocol Operations: https://tools.ietf.org/html/rfc6241. + +.. function:: (ns *NetconfService) CancelCommit(provider ServiceProvider, persistId int) + + Cancels an ongoing confirmed commit. If the persist_id < 1, the operation **MUST** be issued on the same session that issued the confirmed commit. + + :param provider: An instance of :go:struct:`NetconfServiceProvider` + :param persistId: An ``int`` + :return: whether or not the operation succeeded + :rtype: ``bool`` + :raises: `YGOError` If error has occurred + +.. function:: (ns *NetconfService) CloseSession(provider ServiceProvider) + + Request graceful termination of a NETCONF session + + :param provider: An instance of :go:struct:`NetconfServiceProvider` + :return: whether or not the operation succeeded + :rtype: ``bool`` + :raises: `YGOError` If error has occurred + +.. function:: (ns *NetconfService) Commit( + provider ServiceProvider, confirmed bool, confirmTimeOut, persist, persistId int) + + Instructs the device to implement the configuration data contained in the candidate configuration. + + :param provider: An instance of :go:struct:`NetconfServiceProvider` + :param confirmed: A ``bool`` that signals a confirmed commit operation + :param comfirmTimeOut: An ``int`` representing the timeout interval for a confirmed commit + :param persist: An ``int`` that makes the confirmed commit persistent + :param persistId: An ``int`` that is given in order to commit a persistent confirmed commit + :return: whether or not the operation succeeded + :rtype: ``bool`` + :raises: `YGOError` If error has occurred + +.. function:: (ns *NetconfService) CopyConfig( + provider ServiceProvider, target, sourceDS DataStore, sourceEntity Entity, url string) + + Create or replace an entire configuration DataStore with the contents of another complete configuration DataStore. If the target DataStore exists, it is overwritten. Otherwise, a new one is created, if allowed. + sourceEntity should be nil OR sourceDS should be nil, but not neither or both. url is ignored unless target/sourceDS is set to Url. + + :param provider: An instance of :go:struct:`NetconfServiceProvider` + :param target: An instance of :go:struct:`DataStore` representing the configuration being used as the destination + :param sourceDS: An instance of :go:struct:`DataStore` representing the configuration being used as the source + :param sourceEntity: An instance of :go:struct:`Entity` representing the configuration being used as the source + :param url: A ``string`` representing the configuration url + :return: whether or not the operation succeeded + :rtype: ``bool`` + :raises: `YGOError` If error has occurred + +.. function:: (ns *NetconfService) DeleteConfig(provider ServiceProvider, target DataStore, url string) + + Delete a configuration DataStore. The RUNNING configuration DataStore cannot be deleted. + + :param provider: An instance of :go:struct:`NetconfServiceProvider` + :param target: An instance of :go:struct:`DataStore` representing the configuration being used as the destination + :param url: A ``string`` representing the configuration url + :return: whether or not the operation succeeded + :rtype: ``bool`` + :raises: `YGOError` If error has occurred + +.. function:: (ns *NetconfService) DiscardChanges(provider ServiceProvider) + + Used to revert the candidate configuration to the current running configuration. + + :param provider: An instance of :go:struct:`NetconfServiceProvider` + :return: whether or not the operation succeeded + :rtype: ``bool`` + :raises: `YGOError` If error has occurred + +.. function:: (ns *NetconfService) EditConfig( + provider ServiceProvider, target DataStore, config Entity, defaultOper, testOp, errorOp string) + + Loads all or part of a specified configuration to the specified target configuration datastore. Allows the new configuration to be expressed using a local file, a remote file, or inline. If the target configuration datastore does not exist, it will be created. + + :param provider: An instance of :go:struct:`NetconfServiceProvider` + :param target: An instance of :go:struct:`DataStore` representing the configuration being used as the destination + :param config: An instance of :go:struct:`Entity` that is a hierarchy configuration of data as defined by one of the device’s data models + :param defaultOper: A ``string`` that changes the default from ``merge`` to either ``merge``, ``replace``, or ``none`` + :param testOp: A ``string`` that can be set to ``test-then-set``, ``set``, or ``test-only`` if the device advertises the :validate:1.1 capability + :param errOp: A ``string`` that can be set to ``stop-on-error``, ``continue-on-error``, or ``rollback-on-error`` + :return: whether or not the operation succeeded + :rtype: ``bool`` + :raises: `YGOError` If error has occurred + +.. function:: (ns *NetconfService) GetConfig(provider ServiceProvider, source DataStore, filter Entity) + + Retrieve all or part of a specified configuration datastore + + :param provider: An instance of :go:struct:`NetconfServiceProvider` + :param source: An instance of :go:struct:`DataStore` representing the configuration being used as the source + :param filter: An instance of :go:struct:`Entity` which specifies the portion of the system configuration and state data to retrieve + :return: The requested data + :rtype: :go:struct:`Entity` + :raises: `YGOError` If error has occurred + +.. function:: (ns *NetconfService) Get(provider ServiceProvider, filter Entity) + + Retrieve running configuration and device state information. + + :param provider: An instance of :go:struct:`NetconfServiceProvider` + :param filter: An instance of :go:struct:`Entity` which specifies the portion of the system configuration and state data to retrieve + :return: The requested data + :rtype: :go:struct:`Entity` + :raises: `YGOError` If error has occurred + +.. function:: (ns *NetconfService) KillSession(provider ServiceProvider, sessionId int) + + Force the termination of a NETCONF session. + + :param provider: An instance of :go:struct:`NetconfServiceProvider` + :param sessionId: An ``int`` that is the session identifier of the NETCONF session to be terminated + :return: whether or not the operation succeeded + :rtype: ``bool`` + :raises: `YGOError` If error has occurred + +.. function:: (ns *NetconfService) Lock(provider ServiceProvider, target DataStore) + + Allows the client to lock the entire configuration datastore system of a device. + + :param provider: An instance of :go:struct:`NetconfServiceProvider` + :param target: An instance of :go:struct:`DataStore` representing the configuration to lock + :return: whether or not the operation succeeded + :rtype: ``bool`` + :raises: `YGOError` If error has occurred + +.. function:: (ns *NetconfService) Unlock(provider ServiceProvider, target DataStore) + + Used to release a configuration lock, previously obtained with the LOCK operation. + + :param provider: An instance of :go:struct:`NetconfServiceProvider` + :param target: An instance of :go:struct:`DataStore` representing the configuration to unlock + :return: whether or not the operation succeeded + :rtype: ``bool`` + :raises: `YGOError` If error has occurred + +.. function:: (ns *NetconfService) Validate( + provider ServiceProvider, sourceDS DataStore, sourceEntity Entity, url string) + + Validates the contents of the specified configuration. sourceEntity should be nil OR sourceDS should be nil, but not neither or both. url is ignored unless target/sourceDS is set to Url. + + :param provider: An instance of :go:struct:`NetconfServiceProvider` + :param sourceEntity: An instance of :go:struct:`Entity` representing the configuration being used as the source + :param sourceDS: An instance of :go:struct:`DataStore` representing the configuration being used as the source + :param url: A ``string`` representing the configuration url + :return: whether or not the operation succeeded + :rtype: ``bool`` + :raises: `YGOError` If error has occurred diff --git a/sdk/go/core/tests/netconf_service_test.go b/sdk/go/core/tests/netconf_service_test.go new file mode 100644 index 000000000..bd98caccb --- /dev/null +++ b/sdk/go/core/tests/netconf_service_test.go @@ -0,0 +1,237 @@ +package test + +import ( + "fmt" + ysanity "github.com/CiscoDevNet/ydk-go/ydk/models/ydktest/sanity" + "github.com/CiscoDevNet/ydk-go/ydk" + "github.com/CiscoDevNet/ydk-go/ydk/providers" + "github.com/CiscoDevNet/ydk-go/ydk/services" + "github.com/CiscoDevNet/ydk-go/ydk/types" + "github.com/stretchr/testify/suite" + "testing" +) + +type NetconfServiceTestSuite struct { + suite.Suite + Provider providers.NetconfServiceProvider + Crud services.CrudService + NS services.NetconfService +} + +func (suite *NetconfServiceTestSuite) SetupSuite() { + suite.Crud = services.CrudService{} + suite.NS = services.NetconfService{} + suite.Provider = providers.NetconfServiceProvider{ + Address: "127.0.0.1", + Username: "admin", + Password: "admin", + Port: 12022} + suite.Provider.Connect() +} + +func (suite *NetconfServiceTestSuite) TearDownSuite() { + suite.Provider.Disconnect() +} + +func (suite *NetconfServiceTestSuite) BeforeTest(suiteName, testName string) { + suite.Crud.Delete(&suite.Provider, &ysanity.Runner{}) + fmt.Printf("%v: %v ...\n", suiteName, testName) +} + +func (suite *NetconfServiceTestSuite) TestEditCommitGet() { + runner := ysanity.Runner{} + runner.One.Number = 1 + runner.One.Name = "runner:one:name" + + // Edit Config + op := suite.NS.EditConfig(&suite.Provider, types.Candidate, &runner, "", "", "") + suite.Equal(op, true) + + // Get Config + readEntity := suite.NS.GetConfig(&suite.Provider, types.Candidate, &ysanity.Runner{}) + suite.Equal(types.EntityEqual(readEntity, &runner), true) + + // // Commit + op = suite.NS.Commit(&suite.Provider, false, -1, -1, -1) + suite.Equal(op, true) + + // Get + readEntity = suite.NS.Get(&suite.Provider, &ysanity.Runner{}) + suite.Equal(types.EntityEqual(readEntity, &runner), true) +} + +func (suite *NetconfServiceTestSuite) TestLockUnlock() { + op := suite.NS.Lock(&suite.Provider, types.Running) + suite.Equal(op, true) + + op = suite.NS.Unlock(&suite.Provider, types.Running) + suite.Equal(op, true) +} + +func (suite *NetconfServiceTestSuite) TestLockUnlockFail() { + op := suite.NS.Lock(&suite.Provider, types.Candidate) + suite.Equal(op, true) + + funcDidPanic, panicValue := didPanic(func() { suite.NS.Unlock(&suite.Provider, types.Running) }) + suite.Equal(funcDidPanic, true) + suite.Regexp("YGOServiceProviderError:", panicValue) + errMsg := ` + application + operation-failed + error + ` + suite.Regexp(errMsg, panicValue) +} + +func (suite *NetconfServiceTestSuite) TestValidate() { + op := suite.NS.Validate(&suite.Provider, nil, types.Candidate, "") + suite.Equal(op, true) + + runner := ysanity.Runner{} + runner.One.Number = 1 + runner.One.Name = "runner:one:name" + op = suite.NS.Validate(&suite.Provider, &runner, -1, "") + suite.Equal(op, true) +} + +func (suite *NetconfServiceTestSuite) TestCommitDiscard(){ + runner := ysanity.Runner{} + runner.Two.Number = 2 + runner.Two.Name = "runner:two:name" + + op := suite.NS.EditConfig(&suite.Provider, types.Candidate, &runner, "", "", "") + suite.Equal(op, true) + + op = suite.NS.DiscardChanges(&suite.Provider) + suite.Equal(op, true) + + op = suite.NS.EditConfig(&suite.Provider, types.Candidate, &runner, "", "", "") + suite.Equal(op, true) + + op = suite.NS.Commit(&suite.Provider, false, -1, -1, -1) + suite.Equal(op, true) + + readEntity := suite.NS.Get(&suite.Provider, &ysanity.Runner{}) + suite.Equal(types.EntityEqual(readEntity, &runner), true) +} + +// skipped in python/cpp +func (suite *NetconfServiceTestSuite) TestConfirmedCommit() { + runner := ysanity.Runner{} + runner.Two.Number = 2 + runner.Two.Name = "runner:two:name" + + op := suite.NS.EditConfig(&suite.Provider, types.Candidate, &runner, "", "", "") + suite.Equal(op, true) + + op = suite.NS.Commit(&suite.Provider, true, 120, -1, -1) + suite.Equal(op, true) + + // op = suite.NS.CancelCommit(&suite.Provider, -1) + // suite.Equal(op, true) + + readEntity := suite.NS.Get(&suite.Provider, &ysanity.Runner{}) + suite.Equal(types.EntityEqual(readEntity, &runner), true) +} + +// TODO: Problems found with path functions: +// readEntity changes with getFilter +// EntityEqual(readEntity, &runner) returns true, even after the above +func (suite *NetconfServiceTestSuite) TestCopyConfig() { + runner := ysanity.Runner{} + runner.Two.Number = 2 + runner.Two.Name = "runner:two:name" + getFilter := ysanity.Runner{} + + var op bool + var readEntity types.Entity + + // Modify Candidate via CopyConfig from runner + op = suite.NS.CopyConfig(&suite.Provider, types.Candidate, -1, &runner, "") + suite.Equal(op, true) + + readEntity = suite.NS.GetConfig(&suite.Provider, types.Candidate, &getFilter) + suite.Equal(types.EntityEqual(readEntity, &runner), true) + getFilter = ysanity.Runner{} + + // Modify Candidate via CopyConfig from runner + runner.Two.Name = fmt.Sprintf("%s_modified", runner.Two.Name) + + op = suite.NS.CopyConfig(&suite.Provider, types.Candidate, -1, &runner, "") + suite.Equal(op, true) + + readEntity = suite.NS.GetConfig(&suite.Provider, types.Candidate, &getFilter) + suite.Equal(types.EntityEqual(readEntity, &runner), true) + getFilter = ysanity.Runner{} + + // Modify Running via CopyConfig from Candidate + op = suite.NS.CopyConfig(&suite.Provider, types.Running, types.Candidate, nil, "") + suite.Equal(op, true) + + readEntity = suite.NS.GetConfig(&suite.Provider, types.Running, &getFilter) + suite.Equal(types.EntityEqual(readEntity, &runner), true) +} + +func (suite *NetconfServiceTestSuite) TestDeleteConfig() { + suite.T().Skip("startup not enabled in ConfD") + + runner := ysanity.Runner{} + runner.Two.Number = 2 + runner.Two.Name = "runner:two:name" + + op := suite.NS.CopyConfig(&suite.Provider, types.Startup, -1, &runner, "") + suite.Equal(op, true) + + op = suite.NS.DeleteConfig(&suite.Provider, types.Startup, "") + suite.Equal(op, true) +} + +func (suite *NetconfServiceTestSuite) TestCloseSession() { + op := suite.NS.CloseSession(&suite.Provider) + suite.Equal(op, true) + + funcDidPanic, panicValue := didPanic(func() { suite.NS.Lock(&suite.Provider, types.Running) }) + suite.Equal(funcDidPanic, true) + suite.Equal(panicValue, "YGOClientError: RPC error occured") + + suite.Provider.Connect() + + op = suite.NS.Lock(&suite.Provider, types.Running) + op = suite.NS.Unlock(&suite.Provider, types.Running) + suite.Equal(op, true) +} + + +func (suite *NetconfServiceTestSuite) TestKillSession() { + funcDidPanic, panicValue := didPanic(func() { suite.NS.KillSession(&suite.Provider, 1) }) + suite.Equal(funcDidPanic, true) + suite.Regexp("YGOServiceProviderError:", panicValue) +} + +func TestNetconfServiceTestSuite(t *testing.T) { + if testing.Verbose() { + ydk.EnableLogging(ydk.Debug) + } + suite.Run(t, new(NetconfServiceTestSuite)) +} + + +// didPanic returns true if the function passed to it panics. Otherwise, it returns false. +func didPanic(panicTestFunc func()) (bool, string) { + + didPanic := false + var message interface{} + func() { + + defer func() { + if message = recover(); message != nil { + didPanic = true + } + }() + + // call the target function + panicTestFunc() + + }() + return didPanic, message.(string) +} \ No newline at end of file diff --git a/sdk/go/core/ydk/path/path.go b/sdk/go/core/ydk/path/path.go index 349abcc08..19ca5ca90 100644 --- a/sdk/go/core/ydk/path/path.go +++ b/sdk/go/core/ydk/path/path.go @@ -38,9 +38,10 @@ import ( "unsafe" ) + // ExecuteRPC executes payload converted from entity. // Returns a data node (types.DataNode) representing the result of the executed rpc. -func ExecuteRPC(provider types.ServiceProvider, entity types.Entity, Filter string, dataTag string, setConfigFlag bool) types.DataNode { +func ExecuteRPC(provider types.ServiceProvider, Filter string, data map[string]interface{}, setConfigFlag bool) types.DataNode { state := provider.GetState() cstate := getCState(state) wrappedProvider := provider.GetPrivate().(types.CServiceProvider) @@ -55,9 +56,6 @@ func ExecuteRPC(provider types.ServiceProvider, entity types.Entity, Filter stri panic(1) } - data := getDataPayload(state, entity, rootSchema, provider) - defer C.free(unsafe.Pointer(data)) - input := C.RpcInput(*cstate, ydkRPC) panicOnCStateError(cstate) @@ -66,8 +64,20 @@ func ExecuteRPC(provider types.ServiceProvider, entity types.Entity, Filter stri panicOnCStateError(cstate) } - C.DataNodeCreate(*cstate, input, C.CString(dataTag), data) - panicOnCStateError(cstate) + var dataTag string = "" + var value interface{} = nil + for dataTag, value = range data { + dataValue := C.CString("") + switch v := value.(type){ + case string: + dataValue = C.CString(value.(string)) + default: + _ = v + dataValue = getDataPayload(state, value.(types.Entity), rootSchema, provider) + defer C.free(unsafe.Pointer(dataValue)) + } + C.DataNodeCreate(*cstate, input, C.CString(dataTag), dataValue) + } dataNode := types.DataNode{C.RpcExecute(*cstate, ydkRPC, realProvider)} panicOnCStateError(cstate) @@ -472,7 +482,7 @@ func getEntityFromDataNode(node C.DataNode, entity types.Entity) { for _, childDataNode := range children { childName := C.GoString(C.DataNodeGetArgument(childDataNode)) - fmt.Printf("Lookin at child datanode: '%s'\n", childName) + fmt.Printf("Looking at child datanode: '%s'\n", childName) if dataNodeIsLeaf(childDataNode) { diff --git a/sdk/go/core/ydk/services/netconf_service.go b/sdk/go/core/ydk/services/netconf_service.go deleted file mode 100644 index 66f9b6391..000000000 --- a/sdk/go/core/ydk/services/netconf_service.go +++ /dev/null @@ -1,308 +0,0 @@ -/* - * ------------------------------------------------------------------ - * YANG Development Kit - * Copyright 2017 Cisco Systems. All rights reserved - * - *---------------------------------------------- - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http:www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - *---------------------------------------------- - */ -package services - -// #cgo CXXFLAGS: -g -std=c++11 -// #cgo darwin LDFLAGS: -fprofile-arcs -ftest-coverage -lydk -lxml2 -lxslt -lpcre -lssh -lssh_threads -lcurl -lpython -lc++ -// #cgo linux LDFLAGS: -fprofile-arcs -ftest-coverage --coverage -lydk -lxml2 -lxslt -lpcre -lssh -lssh_threads -lcurl -lstdc++ -lpython2.7 -ldl -// #include -// #include -import "C" - -import ( - "encoding/json" - "encoding/xml" - "strconv" - "fmt" - "errors" - "log" - "github.com/CiscoDevNet/ydk-go/ydk" - "github.com/CiscoDevNet/ydk-go/ydk/path" - "github.com/CiscoDevNet/ydk-go/ydk/types" -) - -const ( - Candidate int = iota - Running - StartUp - Url -) - -type NetconfService struct { -} - -func (ns *NetconfService) CancelCommit(provider NetconfServiceProvider, persistId int) bool { - var cstate C.YDKStatePtr = C.YDKStateCreate() - defer C.YDKStateFree(cstate) - - cancelCommitRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:cancel-commit") - if (persistId > 1) { - input := C.RpcInput(cstate, cancelCommitRpc) - persistIdStr := strconv.Itoa(persistId) - C.DataNodeCreate(cstate, input, "persist-id", C.CString(persistIdStr)) - } - - readData := C.RpcExecute(cstate, cancelCommitRpc, provider) - return readData == nil -} - -func (ns *NetconfService) CloseSession(provider NetconfServiceProvider) bool { - var cstate C.YDKStatePtr = C.YDKStateCreate() - defer C.YDKStateFree(cstate) - - closeSessionRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:close-session") - - readData := C.RpcExecute(cstate, closeSessionRpc, provider) - return readData == nil -} - -func (ns *NetconfService) Commit(provider NetconfServiceProvider, confirmed bool, confirmTimeOut, persist, persistId int) bool { - var cstate C.YDKStatePtr = C.YDKStateCreate() - defer C.YDKStateFree(cstate) - - commitRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:commit") - - if (confirmed) { - input := C.RpcInput(cstate, commitRpc) - C.DataNodeCreate(cstate, input, "confirmed", "") - } - - if (confirmTimeOut > -1) { - input := C.RpcInput(cstate, commitRpc) - confirmTimeOutStr := strconv.Itoa(confirmTimeOut) - C.DataNodeCreate(cstate, input, "confirm-timeout", confirmTimeOutStr) - } - - if (persist > -1) { - input := C.RpcInput(cstate, commitRpc) - persistStr := strconv.Itoa(persist) - C.DataNodeCreate(cstate, input, "persist", persistStr) - } - - if (persistId > -1) { - input := C.RpcInput(cstate, commitRpc) - persistIdStr := strconv.Itoa(persistId) - C.DataNodeCreate(cstate, input, "persist-id", persistIdStr) - } - - readData := C.RpcExecute(cstate, commitRpc, provider) - return readData == nil -} - -// TODO: figure out optional arguments -// func (ns *NetconfService) CopyConfig(provider NetconfServiceProvider, target, source int, url string) bool { -// } - -// func (ns *NetconfService) CopyConfig(provider NetconfServiceProvider, target int, source types.Entity) bool { -// } - -func (ns *NetconfService) DeleteConfig(provider NetconfServiceProvider, target int, url string) bool { - var cstate C.YDKStatePtr = C.YDKStateCreate() - defer C.YDKStateFree(cstate) - - deleteConfigRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:delete-config") - input := C.RpcInput(cstate, deleteConfigRpc) - - // target options: startup | url - createInputLeaf(cstate, input, target, "target", "") - - readData := C.RpcExecute(cstate, deleteConfigRpc, provider) - return readData == nil -} - -func (ns *NetconfService) DiscardChanges(provider NetconfServiceProvider) bool { - var cstate C.YDKStatePtr = C.YDKStateCreate() - defer C.YDKStateFree(cstate) - - discardChangesRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:discard-changes") - readData := C.RpcExecute(cstate, discardChangesRpc, provider) - return readData == nil -} - -// TODO -func (ns *NetconfService) EditConfig( - provider NetconfServiceProvider, target int, config types.Entity, defaultOper, testOp, errorOp string) bool { - var cstate C.YDKStatePtr = C.YDKStateCreate() - defer C.YDKStateFree(cstate) - - editConfigRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:edit-config") - // TODO -} - -// incomplete -func (ns *NetconfService) GetConfig(provider NetconfServiceProvider, source int, filter types.Entity) types.Entity { - var cstate C.YDKStatePtr = C.YDKStateCreate() - defer C.YDKStateFree(cstate) - - getConfigRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:get-config") - input := C.RpcInput(cstate, getConfigRpc) - - // source options: candidate | running | startup - createInputLeaf(cstate, input, source, "source") - - payload := getXmlSubtreeFilterPayload(cstate, entity, provider) - C.DataNodeCreate(cstate, input, "filter", payload) - - readData := C.RpcExecute(cstate, getConfigRpc, provider) - if (readData == nil) { - return nil - } - - topEntity := getTopEntityFromFilter(filter) - - // TODO: how to handle DataNodeChildren struct go? - node := C.DataNodeGetChildren(readData)[0] - getEntityFromDataNode(node, topEntity) - - return topEntity -} - -// incomplete -func (ns *NetconfService) Get(provider NetconfServiceProvider, filter types.Entity) bool { - var cstate C.YDKStatePtr = C.YDKStateCreate() - defer C.YDKStateFree(cstate) - - getRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:get") - input := C.RpcInput(cstate, getRpc) - - payload := getXmlSubtreeFilterPayload(cstate, entity, provider) - C.DataNodeCreate(cstate, input, "filter", payload) - - readData := C.RpcExecute(cstate, getConfigRpc, provider) - if (readData == nil) { - return nil - } - - topEntity := getTopEntityFromFilter(filter) - - // TODO: how to handle DataNodeChildren struct go? - node := C.DataNodeGetChildren(readData)[0] - getEntityFromDataNode(node, topEntity) - - return topEntity -} - -func (ns *NetconfService) KillSession(provider NetconfServiceProvider, sessionId int) bool { - var cstate C.YDKStatePtr = C.YDKStateCreate() - defer C.YDKStateFree(cstate) - - killSessionRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:kill-session") - input := C.RpcInput(cstate, killSessionRpc) - sessionIdStr := strconv.Itoa(sessionId) - C.DataNodeCreate(cstate, input, "session-id", sessionIdStr) - - readData := C.RpcExecute(cstate, killSessionRpc, provider) - return readData == nil -} - -func (ns *NetconfService) Lock(provider NetconfServiceProvider, target int) bool { - var cstate C.YDKStatePtr = C.YDKStateCreate() - defer C.YDKStateFree(cstate) - - lockRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:lock") - input := C.RpcInput(cstate, lockRpc) - - // target options: candidate | running | startup - createInputLeaf(cstate, input, target, "target", "") - - readData := C.RpcExecute(cstate, lockRpc, provider) - return readData == nil -} - -func (ns *NetconfService) Unlock(provider NetconfServiceProvider, target DataStore) bool { - var cstate C.YDKStatePtr = C.YDKStateCreate() - defer C.YDKStateFree(cstate) - - unlockRpc := getRpcFromProvider(cstate, provider, "ietf-netconf:unlock") - input := C.RpcInput(cstate, unlockRpc) - - // target options: candidate | running | startup - createInputLeaf(cstate, input, target, "target", "") - - readData := C.RpcExecute(cstate, unlockRpc, provider) - return readData == nil -} - -// TODO: figure out optional arguments -// func (ns *NetconfService) Validate(provider NetconfServiceProvider, source DataStore, url string) bool { -// } - -// func (ns *NetconfService) Validate(provider NetconfServiceProvider, source DataStore) bool { -// } - -func getRpcFromProvider(cstate C.YDKStatePtr, provider NetconfServiceProvider, path string) C.Rpc { - rootSchemaNode := C.ServiceProviderGetRootSchema(cstate, provider) - rpc := C.RootSchemaNodeRpc(cstate, rootSchemaNode, C.CString(path)) - return rpc -} - -func createInputLeaf(cstate C.YDKStatePtr, inputDataNode C.DataNode, dataStore int, dataStoreStr string, url string) { - var path bytes.Buffer - path.WriteString(dataStoreStr) - - switch dataStore { - case Candidate: - path.WriteString("/candidate") - case Running: - path.WriteString("/running") - case StartUp: - path.WriteString("/startup") - case Url: - if (url == "") { - err := errors.New("URL needs to be specified") - log.Fatal(err) - } - path.WriteString("/url") - } - - C.DataNodeCreate(cstate, inputDataNode, path.String(), "") -} - -func getXmlSubtreeFilterPayload(cstate C.YDKStatePtr, entity types.Entity, provider NetconfServiceProvider) string { - // XmlSubTreeCodec* not imported or implemented!! - var xmlSubtreeCodec C.XmlSubtreeCodec = C.XmlSubtreeCodecCreate() - defer C.XmlSubtreeCodec(xmlSubtreeCodec) - - payload := xmlSubtreeCodecEncode(cstate, xmlSubtreeCodec, entity, provider) - return payload -} - -func getTopEntityFromFilter(filter types.Entity) types.Entity { - parent := filter.GetParent() - if (parent == nil) { - return filter.GetFilter() - } - return getTopEntityFromFilter(parent) -} - -// TODO -func getEntityFromDataNode(node C.DataNode, entity types.Entity) { - if (node == nil || entity == nil) { - return - } - - // not sure how this is supposed to work... - children := C.DataNodeGetChildren(node) -} diff --git a/sdk/go/core/ydk/services/services.go b/sdk/go/core/ydk/services/services.go index 5dd2f741f..939d4ff58 100644 --- a/sdk/go/core/ydk/services/services.go +++ b/sdk/go/core/ydk/services/services.go @@ -35,6 +35,8 @@ import ( "encoding/json" "encoding/xml" "fmt" + "strconv" + "errors" "github.com/CiscoDevNet/ydk-go/ydk" "github.com/CiscoDevNet/ydk-go/ydk/path" "github.com/CiscoDevNet/ydk-go/ydk/types" @@ -47,35 +49,36 @@ type CrudService struct { // Create the entity. // Returns whether the operation was successful or not (bool) func (c *CrudService) Create(provider types.ServiceProvider, entity types.Entity) bool { - return operationSucceeded(path.ExecuteRPC(provider, entity, "ydk:create", "entity", false)) + data := map[string]interface{} { "entity": entity } + return operationSucceeded(path.ExecuteRPC(provider, "ydk:create", data, false)) } // Update the entity. // Returns whether the operation was successful or not (bool) func (c *CrudService) Update(provider types.ServiceProvider, entity types.Entity) bool { - return operationSucceeded(path.ExecuteRPC(provider, entity, "ydk:update", "entity", false)) + data := map[string]interface{} { "entity": entity } + return operationSucceeded(path.ExecuteRPC(provider, "ydk:update", data, false)) } // Delete the entity. // Returns whether the operation was successful or not (bool) func (c *CrudService) Delete(provider types.ServiceProvider, entity types.Entity) bool { - return operationSucceeded(path.ExecuteRPC(provider, entity, "ydk:delete", "entity", false)) + data := map[string]interface{} { "entity": entity } + return operationSucceeded(path.ExecuteRPC(provider, "ydk:delete", data, false)) } // Read the entity. // Returns the entity as identified by the given filter (types.Entity) func (c *CrudService) Read(provider types.ServiceProvider, filter types.Entity) types.Entity { - return path.ReadDatanode(filter, path.ExecuteRPC(provider, filter, "ydk:read", "filter", true)) + data := map[string]interface{} { "filter": filter } + return path.ReadDatanode(filter, path.ExecuteRPC(provider, "ydk:read", data, true)) } // ReadConfig only reads config. // Returns the entity as identified by the given filter (types.Entity) func (c *CrudService) ReadConfig(provider types.ServiceProvider, filter types.Entity) types.Entity { - return path.ReadDatanode(filter, path.ExecuteRPC(provider, filter, "ydk:read", "filter", false)) -} - -func operationSucceeded(node types.DataNode) bool { - return node.Private != nil + data := map[string]interface{} { "filter": filter } + return path.ReadDatanode(filter, path.ExecuteRPC(provider, "ydk:read", data, false)) } // CodecService supports encoding and decoding Go model API objects of type @@ -104,6 +107,316 @@ func (c *CodecService) Decode(provider types.CodecServiceProvider, payload strin return path.CodecServiceDecode(provider.GetState(), rootSchema, payload, provider.GetEncoding(), topEntity) } +// NetconfService implements the NETCONF Protocol Operations: https://tools.ietf.org/html/rfc6241 +type NetconfService struct { +} + +// CancelCommit cancels an ongoing confirmed commit. +// If persist_id < 1, the operation MUST be issued on the same session that issued the confirmed commit. +// Returns whether the operation is successful or not +func (ns *NetconfService) CancelCommit(provider types.ServiceProvider, persistId int) bool { + data := map[string]interface{} {} + if (persistId > 1) { + data["persist-id"] = strconv.Itoa(persistId) + } + readDataNode := path.ExecuteRPC(provider, "ietf-netconf:cancel-commit", data, false) + return operationSucceeded(readDataNode) +} + +// CloseSession requests graceful termination of a NETCONF session +// Returns whether the operation is successful or not +func (ns *NetconfService) CloseSession(provider types.ServiceProvider) bool { + data := map[string]interface{} {} + readDataNode := path.ExecuteRPC(provider, "ietf-netconf:close-session", data, false) + return operationSucceeded(readDataNode) +} + +// Commit instructs the device to implement the configuration data contained in the candidate configuration. +// Returns whether the operation is successful or not +func (ns *NetconfService) Commit( + provider types.ServiceProvider, confirmed bool, confirmTimeOut, persist, persistId int) bool { + + data := map[string]interface{} {} + if (confirmed) { + data["confirmed"] = "" + } + if (confirmTimeOut > -1) { + data["confirm-timeout"] = strconv.Itoa(confirmTimeOut) + } + if (persist > -1) { + data["persist"] = strconv.Itoa(persist) + } + if (persistId > -1) { + data["persist-id"] = strconv.Itoa(persistId) + } + + readDataNode := path.ExecuteRPC(provider, "ietf-netconf:commit", data, false) + return operationSucceeded(readDataNode) +} + +// CopyConfig creates or replaces an entire configuration DataStore with the contents of another complete configuration DataStore. +// If the target DataStore exists, it is overwritten. Otherwise, a new one is created, if allowed. +// Parameters: +// sourceEntity should be nil OR sourceDS should be nil, but not neither or both. +// url is ignored unless target/sourceDS is set to Url. +// Returns whether the operation is successful or not +func (ns *NetconfService) CopyConfig( + provider types.ServiceProvider, target, sourceDS types.DataStore, sourceEntity types.Entity, url string) bool { + + // target/source options: candidate | running | startup | url + if ((target == types.Url || sourceDS == types.Url) && len(url) == 0){ + err := types.YGOError{Msg: "url must be specified"} + panic(err.Error()) + } + if ((sourceDS != -1 && sourceEntity != nil) || sourceDS == -1 && sourceEntity == nil) { + err := types.YGOError{Msg: "sourceDS OR sourceEntity must be valid, not neither nor both"} + panic(err.Error()) + } + + data := map[string]interface{} {} + dsStr, dataValue, err := getDataStoreString(target, url) + if err != nil { + errMsg := fmt.Sprintf("target: %v is not a valid DataStore value", target) + err := types.YGOError{Msg: errMsg} + panic(err.Error()) + } + + data["target/" + dsStr] = dataValue + + if (sourceDS != -1){ + dsStr, dataValue, err := getDataStoreString(sourceDS, url) + if err != nil { + errMsg := fmt.Sprintf("sourceDS: %v is not a valid DataStore value", sourceDS) + err := types.YGOError{Msg: errMsg} + panic(err.Error()) + } + data["source/" + dsStr] = dataValue + } else { + data["source/config"] = sourceEntity + } + + readDataNode := path.ExecuteRPC(provider, "ietf-netconf:copy-config", data, false) + return operationSucceeded(readDataNode) +} + +// DeleteConfig deletes a configuration DataStore. The CANDIDATE and RUNNING DataStores cannot be deleted +// Returns whether the operation is successful or not +func (ns *NetconfService) DeleteConfig(provider types.ServiceProvider, target types.DataStore, url string) bool { + // target options: startup | url + dsStr, dataValue, err := getDataStoreString(target, url) + if err != nil { + errMsg := fmt.Sprintf("target: %v is not a valid DataStore value", target) + err := types.YGOError{Msg: errMsg} + panic(err.Error()) + } + if (target == types.Candidate || target == types.Running || target == types.Url && len(url) == 0){ + errMsg := fmt.Sprintf("target: %v can only be Startup (url is ignored) or Url (url must be specified)", dsStr) + err := types.YGOError{Msg: errMsg} + panic(err.Error()) + } + + data := map[string]interface{} {} + data["target/" + dsStr] = dataValue + + readDataNode := path.ExecuteRPC(provider, "ietf-netconf:delete-config", data, false) + return operationSucceeded(readDataNode) +} + +// DiscardChanges reverts the candidate configuration to the current running configuration. +// Returns whether the operation is successful or not +func (ns *NetconfService) DiscardChanges(provider types.ServiceProvider) bool { + data := map[string]interface{} {} + readDataNode := path.ExecuteRPC(provider, "ietf-netconf:discard-changes", data, false) + return operationSucceeded(readDataNode) +} + +// EditConfig loads all or part of a specified configuration to the specified target configuration datastore. +// Allows the new configuration to be expressed using a local file, a remote file, or inline. +// If the target configuration datastore does not exist, it will be created. +// Returns whether the operation is successful or not +func (ns *NetconfService) EditConfig( + provider types.ServiceProvider, target types.DataStore, config types.Entity, defaultOper, testOp, errorOp string) bool { + + // target options: candidate | running + dsStr, dataValue, err := getDataStoreString(target, "") + if err != nil { + errMsg := fmt.Sprintf("target: %v is not a valid DataStore value", target) + err := types.YGOError{Msg: errMsg} + panic(err.Error()) + } + if (target == types.Url || target == types.Startup){ + errMsg := fmt.Sprintf("target: %v can only be Candidate or Running", dsStr) + err := types.YGOError{Msg: errMsg} + panic(err.Error()) + } + + data := map[string]interface{} {} + data["target/" + dsStr] = dataValue + + // config + data["config"] = config + + // default operation, test option, error option + if (len(defaultOper) > 0) { + data["default-operation"] = defaultOper + } + if (len(testOp) > 0) { + data["test-option"] = testOp + } + if (len(errorOp) > 0) { + data["error-option"] = errorOp + } + + readDataNode := path.ExecuteRPC(provider, "ietf-netconf:edit-config", data, false) + return operationSucceeded(readDataNode) +} + +// GetConfig retrieves all or part of a specified configuration datastore +// Returns the requested data in Entity instance +func (ns *NetconfService) GetConfig( + provider types.ServiceProvider, source types.DataStore, filter types.Entity) types.Entity { + + // source options: candidate | running | startup + dsStr, dataValue, err := getDataStoreString(source, "") + if err != nil { + errMsg := fmt.Sprintf("source: %v is not a valid DataStore value", source) + err := types.YGOError{Msg: errMsg} + panic(err.Error()) + } + if (source == types.Url){ + errMsg := fmt.Sprintf("source: %v can only be Candidate, Running, or Startup", dsStr) + err := types.YGOError{Msg: errMsg} + panic(err.Error()) + } + + data := map[string]interface{} {} + data["source/" + dsStr] = dataValue + + // filter + data["filter"] = filter + + readDataNode := path.ExecuteRPC(provider, "ietf-netconf:get-config", data, false) + return path.ReadDatanode(filter, readDataNode) +} + +// Get the running configuration and device state information. +// Returns the requested data in Entity instance +func (ns *NetconfService) Get(provider types.ServiceProvider, filter types.Entity) types.Entity { + data := map[string]interface{} {} + data["filter"] = filter + + readDataNode := path.ExecuteRPC(provider, "ietf-netconf:get", data, false) + return path.ReadDatanode(filter, readDataNode) +} + +// KillSession forces the termination of a NETCONF session. +// Returns whether the operation is successful or not +func (ns *NetconfService) KillSession(provider types.ServiceProvider, sessionId int) bool { + data := map[string]interface{} {} + data["session-id"] = strconv.Itoa(sessionId) + + readDataNode := path.ExecuteRPC(provider, "ietf-netconf:kill-session", data, false) + return operationSucceeded(readDataNode) +} + +// Lock allows the client to lock the entire configuration datastore system of a device. +// Returns whether the operation is successful or not +func (ns *NetconfService) Lock(provider types.ServiceProvider, target types.DataStore) bool { + // target options: candidate | running | startup + dsStr, dataValue, err := getDataStoreString(target, "") + if err != nil { + errMsg := fmt.Sprintf("target: %v is not a valid DataStore value", target) + err := types.YGOError{Msg: errMsg} + panic(err.Error()) + } + if (target == types.Url){ + err := types.YGOError{Msg: "url must be specified"} + panic(err.Error()) + } + + data := map[string]interface{} {} + data["target/" + dsStr] = dataValue + + readDataNode := path.ExecuteRPC(provider, "ietf-netconf:lock", data, false) + return operationSucceeded(readDataNode) +} + +// Unlock a configuration lock, previously obtained with the LOCK operation. +// Returns whether the operation is successful or not +func (ns *NetconfService) Unlock(provider types.ServiceProvider, target types.DataStore) bool { + // target options: candidate | running | startup + dsStr, dataValue, err := getDataStoreString(target, "") + if err != nil { + errMsg := fmt.Sprintf("target: %v is not a valid DataStore value", target) + err := types.YGOError{Msg: errMsg} + panic(err.Error()) + } + if (target == types.Url){ + err := types.YGOError{Msg: "url must be specified"} + panic(err.Error()) + } + + data := map[string]interface{} {} + data["target/" + dsStr] = dataValue + + readDataNode := path.ExecuteRPC(provider, "ietf-netconf:unlock", data, false) + return operationSucceeded(readDataNode) +} + +// Validate the contents of the specified configuration +// Parameters: +// sourceEntity should be nil OR sourceDS should be nil, but not neither or both. +// url is ignored unless target/sourceDS is set to Url. +// Returns whether the operation is successful or not +func (ns *NetconfService) Validate( + provider types.ServiceProvider, sourceDS types.DataStore, sourceEntity types.Entity, url string) bool { + + if ((sourceDS != -1 && sourceEntity != nil) || sourceDS == -1 && sourceEntity == nil) { + err := types.YGOError{Msg: "sourceDS OR sourceEntity must be valid, not neither nor both"} + panic(err.Error()) + } + // sourceDS options: candidate | running | startup | url + if (sourceDS == types.Url && len(url) == 0){ + err := types.YGOError{Msg: "url must be specified"} + panic(err.Error()) + } + data := map[string]interface{} {} + if (sourceDS != -1){ + dsStr, dataValue, err := getDataStoreString(sourceDS, url) + if err != nil { + errMsg := fmt.Sprintf("sourceDS: %v is not a valid DataStore value", sourceDS) + err := types.YGOError{Msg: errMsg} + panic(err.Error()) + } + + data["source/" + dsStr] = dataValue + } else { + data["source/config"] = sourceEntity + } + + readDataNode := path.ExecuteRPC(provider, "ietf-netconf:validate", data, false) + return operationSucceeded(readDataNode) +} + +func getDataStoreString(ds types.DataStore, url string) (string, string, error) { + switch ds { + case types.Candidate: + return "candidate", "", nil + case types.Running: + return "running", "", nil + case types.Startup: + return "startup", "", nil + case types.Url: + return "url", url, nil + } + + return "", "", errors.New("ds is not a valid DataStore value") +} + +func operationSucceeded(node types.DataNode) bool { + return node.Private != nil +} + func getEntityLookupKey(provider types.CodecServiceProvider, payload string) string { var nmsp string encoding := provider.GetEncoding() diff --git a/sdk/go/core/ydk/types/types.go b/sdk/go/core/ydk/types/types.go index 6cc23b27f..8ad7e1d8b 100644 --- a/sdk/go/core/ydk/types/types.go +++ b/sdk/go/core/ydk/types/types.go @@ -199,6 +199,17 @@ func (y *YLeafList) GetNameLeafdata() [](NameLeafData) { return result } +// DataStore is a complete set of configuration data that is required to get a +// device from its initial default state into a desired operational state +type DataStore int + +const ( + Candidate DataStore = iota + Running + Startup + Url +) + // EncodingFormat represents the encoding format type EncodingFormat int From 3865e3d6f02dc81ebbe7024b4595c1c5b375bafe Mon Sep 17 00:00:00 2001 From: lily Date: Wed, 11 Oct 2017 10:36:07 -0700 Subject: [PATCH 03/10] fix typo --- sdk/go/core/tests/netconf_service_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/go/core/tests/netconf_service_test.go b/sdk/go/core/tests/netconf_service_test.go index bd98caccb..de57f3770 100644 --- a/sdk/go/core/tests/netconf_service_test.go +++ b/sdk/go/core/tests/netconf_service_test.go @@ -84,13 +84,13 @@ func (suite *NetconfServiceTestSuite) TestLockUnlockFail() { } func (suite *NetconfServiceTestSuite) TestValidate() { - op := suite.NS.Validate(&suite.Provider, nil, types.Candidate, "") + op := suite.NS.Validate(&suite.Provider, types.Candidate, nil, "") suite.Equal(op, true) runner := ysanity.Runner{} runner.One.Number = 1 runner.One.Name = "runner:one:name" - op = suite.NS.Validate(&suite.Provider, &runner, -1, "") + op = suite.NS.Validate(&suite.Provider, -1, &runner, "") suite.Equal(op, true) } From 25c4203554b4f15479b7521696f2b337b5955ddb Mon Sep 17 00:00:00 2001 From: lily Date: Thu, 12 Oct 2017 16:53:13 -0700 Subject: [PATCH 04/10] added executor service and tests in go, update netconf tests --- sdk/go/core/docsgen/api/services/services.rst | 21 + sdk/go/core/tests/did_panic.go | 21 + sdk/go/core/tests/executor_service_test.go | 378 ++++++++++++++++++ sdk/go/core/tests/netconf_service_test.go | 73 ++-- sdk/go/core/ydk/path/path.go | 91 ++++- sdk/go/core/ydk/services/services.go | 12 + 6 files changed, 563 insertions(+), 33 deletions(-) create mode 100644 sdk/go/core/tests/did_panic.go create mode 100644 sdk/go/core/tests/executor_service_test.go diff --git a/sdk/go/core/docsgen/api/services/services.rst b/sdk/go/core/docsgen/api/services/services.rst index 46e04638b..3b51e28f1 100644 --- a/sdk/go/core/docsgen/api/services/services.rst +++ b/sdk/go/core/docsgen/api/services/services.rst @@ -84,6 +84,27 @@ Codec :return: the decoded entity object :rtype: :go:struct:`Entity` +Executor +-------- + +.. go:struct:: ExecutorService + + Provides the functionality to execute RPCs + +.. function:: (es *ExecutorService) ExecuteRpc (provider types.ServiceProvider, rpcEntity, topEntity types.Entity) + + Create the entity + + :param provider: An instance of :go:struct:`ServiceProvider` + :param rpcEntity: An instance of :go:struct:`Entity` representing an RPC entity + :param topEntity: Provide an instance of :go:struct:`Entity` only when expecting data to be returned + :return: Any data the resulting from the operation when provided topEntity parameter + :rtype: :go:struct:`Entity` or ``nil`` + :raises: `YGOError` If error has occurred + + Possible Errors: + * a server side error + * there isn't enough information in the entity to prepare the message (eg. missing keys) Netconf ------- diff --git a/sdk/go/core/tests/did_panic.go b/sdk/go/core/tests/did_panic.go new file mode 100644 index 000000000..1615a777c --- /dev/null +++ b/sdk/go/core/tests/did_panic.go @@ -0,0 +1,21 @@ +package test + +// didPanic returns true if the function passed to it panics. Otherwise, it returns false. +func didPanic(panicTestFunc func()) (bool, string) { + + didPanic := false + var message interface{} + func() { + + defer func() { + if message = recover(); message != nil { + didPanic = true + } + }() + + // call the target function + panicTestFunc() + + }() + return didPanic, message.(string) +} \ No newline at end of file diff --git a/sdk/go/core/tests/executor_service_test.go b/sdk/go/core/tests/executor_service_test.go new file mode 100644 index 000000000..80e3129f4 --- /dev/null +++ b/sdk/go/core/tests/executor_service_test.go @@ -0,0 +1,378 @@ +package test + +import ( + "fmt" + "strings" + "strconv" + ysanity "github.com/CiscoDevNet/ydk-go/ydk/models/ydktest/sanity" + ietfNetconf "github.com/CiscoDevNet/ydk-go/ydk/models/ydktest/ietf_netconf" + "github.com/CiscoDevNet/ydk-go/ydk" + "github.com/CiscoDevNet/ydk-go/ydk/providers" + "github.com/CiscoDevNet/ydk-go/ydk/services" + "github.com/CiscoDevNet/ydk-go/ydk/types" + "github.com/stretchr/testify/suite" + "testing" +) + +type ExecutorServiceTestSuite struct { + suite.Suite + CodecProvider providers.CodecServiceProvider + NetconfProvider providers.NetconfServiceProvider + CrudService services.CrudService + CodecService services.CodecService + ExecutorService services.ExecutorService +} + +func (suite *ExecutorServiceTestSuite) SetupSuite() { + suite.CodecProvider = providers.CodecServiceProvider{} + suite.NetconfProvider = providers.NetconfServiceProvider{ + Address: "127.0.0.1", + Username: "admin", + Password: "admin", + Port: 12022} + suite.NetconfProvider.Connect() + suite.CrudService = services.CrudService{} + suite.CodecService = services.CodecService{} + suite.ExecutorService = services.ExecutorService{} +} + +func (suite *ExecutorServiceTestSuite) TearDownSuite() { + suite.NetconfProvider.Disconnect() +} + +func (suite *ExecutorServiceTestSuite) BeforeTest(suiteName, testName string) { + suite.CrudService.Delete(&suite.NetconfProvider, &ysanity.Runner{}) + fmt.Printf("%v: %v ...\n", suiteName, testName) +} + +func (suite *ExecutorServiceTestSuite) TestEditCommitGet() { + suite.CodecProvider.Encoding = types.XML + + runner := ysanity.Runner{} + runner.One.Number = 1 + runner.One.Name = "runner:one:name" + runnerXML := suite.CodecService.Encode(&suite.CodecProvider, &runner) + + // Edit Config + editConfigRpc := ietfNetconf.EditConfig{} + editConfigRpc.Input.Target.Candidate = types.Empty{} + editConfigRpc.Input.Config = runnerXML + + readEntity := suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &editConfigRpc, nil) + suite.Equal(readEntity, nil) + + // Get Config + filterXML := suite.CodecService.Encode(&suite.CodecProvider, &ysanity.Runner{}) + getConfigRpc := ietfNetconf.GetConfig{} + getConfigRpc.Input.Source.Candidate = types.Empty{} + getConfigRpc.Input.Filter = filterXML + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &getConfigRpc, &ysanity.Runner{}) + suite.Equal(types.EntityEqual(readEntity, &runner), true) + + // Commit + commitRpc := ietfNetconf.Commit{} + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &commitRpc, nil) + suite.Equal(readEntity, nil) + + // Get + filterXML = suite.CodecService.Encode(&suite.CodecProvider, &ysanity.Runner{}) + getRpc := ietfNetconf.Get{} + getRpc.Input.Filter = filterXML + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &getRpc, &ysanity.Runner{}) + suite.Equal(types.EntityEqual(readEntity, &runner), true) +} + +func (suite *ExecutorServiceTestSuite) TestLockUnlock() { + lockRpc := ietfNetconf.Lock{} + lockRpc.Input.Target.Candidate = types.Empty{} + + readEntity := suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &lockRpc, nil) + suite.Equal(readEntity, nil) + + unlockRpc := ietfNetconf.Unlock{} + unlockRpc.Input.Target.Candidate = types.Empty{} + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &unlockRpc, nil) + suite.Equal(readEntity, nil) +} + +func (suite *ExecutorServiceTestSuite) TestLockUnlockFail() { + lockRpc := ietfNetconf.Lock{} + lockRpc.Input.Target.Candidate = types.Empty{} + + readEntity := suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &lockRpc, nil) + suite.Equal(readEntity, nil) + + funcDidPanic, panicValue := didPanic(func() { + suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &lockRpc, nil) }) + suite.Equal(funcDidPanic, true) + suite.Regexp("YGOServiceProviderError:", panicValue) + suite.Regexp("lock-denied", panicValue) +} + +func (suite *ExecutorServiceTestSuite) TestValidate() { + rpc := ietfNetconf.Validate{} + rpc.Input.Source.Candidate = types.Empty{} + + readEntity := suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &rpc, nil) + suite.Equal(readEntity, nil) + + suite.CodecProvider.Encoding = types.XML + runner := ysanity.Runner{} + runner.One.Number = 1 + runner.One.Name = "runner:one:name" + runnerXML := suite.CodecService.Encode(&suite.CodecProvider, &runner) + + rpc = ietfNetconf.Validate{} + rpc.Input.Source.Config = runnerXML + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &rpc, nil) + suite.Equal(readEntity, nil) +} + +func (suite *ExecutorServiceTestSuite) TestDiscardChanges(){ + suite.CodecProvider.Encoding = types.XML + runner := ysanity.Runner{} + runner.Two.Number = 2 + runner.Two.Name = "runner:two:name" + runnerXML := suite.CodecService.Encode(&suite.CodecProvider, &runner) + + // EditConfig + editConfigRpc := ietfNetconf.EditConfig{} + editConfigRpc.Input.Target.Candidate = types.Empty{} + editConfigRpc.Input.Config = runnerXML + + readEntity := suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &editConfigRpc, nil) + suite.Equal(readEntity, nil) + + // DiscardChanges + readEntity = suite.ExecutorService.ExecuteRpc( + &suite.NetconfProvider, &ietfNetconf.DiscardChanges{}, nil) + suite.Equal(readEntity, nil) + + // GetConfig + filterXML := suite.CodecService.Encode(&suite.CodecProvider, &ysanity.Runner{}) + getConfigRpc := ietfNetconf.GetConfig{} + getConfigRpc.Input.Source.Candidate = types.Empty{} + getConfigRpc.Input.Filter = filterXML + + readEntity = suite.ExecutorService.ExecuteRpc( + &suite.NetconfProvider, &getConfigRpc, &ysanity.Runner{}) + suite.Equal(types.EntityEqual(readEntity, &ysanity.Runner{}), true) +} + +func (suite *ExecutorServiceTestSuite) TestConfirmedCommit() { + suite.CodecProvider.Encoding = types.XML + runner := ysanity.Runner{} + runner.Two.Number = 2 + runner.Two.Name = "runner:two:name" + runnerXML := suite.CodecService.Encode(&suite.CodecProvider, &runner) + + // EditConfig + editConfigRpc := ietfNetconf.EditConfig{} + editConfigRpc.Input.Target.Candidate = types.Empty{} + editConfigRpc.Input.Config = runnerXML + + readEntity := suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &editConfigRpc, nil) + suite.Equal(readEntity, nil) + + // Commit + commitRpc := ietfNetconf.Commit{} + commitRpc.Input.Confirmed = types.Empty{} + commitRpc.Input.ConfirmTimeout = 5 + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &commitRpc, nil) + suite.Equal(readEntity, nil) + + // Get + filterXML := suite.CodecService.Encode(&suite.CodecProvider, &ysanity.Runner{}) + getRpc := ietfNetconf.Get{} + getRpc.Input.Filter = filterXML + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &getRpc, &ysanity.Runner{}) + suite.Equal(types.EntityEqual(readEntity, &runner), true) +} + +// skip +func (suite *ExecutorServiceTestSuite) TestCancelCommit() { + suite.T().Skip("No message id in cancel commit payload") + + suite.CodecProvider.Encoding = types.XML + runner := ysanity.Runner{} + runner.Two.Number = 2 + runner.Two.Name = "runner:two:name" + runnerXML := suite.CodecService.Encode(&suite.CodecProvider, &runner) + + // EditConfig + editConfigRpc := ietfNetconf.EditConfig{} + editConfigRpc.Input.Target.Candidate = types.Empty{} + editConfigRpc.Input.Config = runnerXML + + readEntity := suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &editConfigRpc, nil) + suite.Equal(readEntity, nil) + + // Commit + commitRpc := ietfNetconf.Commit{} + commitRpc.Input.Confirmed = types.Empty{} + // commitRpc.Input.ConfirmTimeout = 5 + // commitRpc.Input.Persist = 2 + // commitRpc.Input.PersistId = 2 + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &commitRpc, nil) + suite.Equal(readEntity, nil) + + // CancelCommit + cancelRpc := ietfNetconf.CancelCommit{} + // cancelRpc.Input.PersistId = 2 + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &cancelRpc, nil) + suite.Equal(readEntity, nil) +} + +func (suite *ExecutorServiceTestSuite) TestCopyConfig() { + suite.CodecProvider.Encoding = types.XML + runner := ysanity.Runner{} + runner.Two.Number = 2 + runner.Two.Name = "runner:two:name" + runnerXML := suite.CodecService.Encode(&suite.CodecProvider, &runner) + + var readEntity types.Entity + + // Modify Candidate via CopyConfig from runner + copyRpc := ietfNetconf.CopyConfig{} + copyRpc.Input.Target.Candidate = types.Empty{} + copyRpc.Input.Source.Config = runnerXML + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, ©Rpc, nil) + suite.Equal(readEntity, nil) + + filterXML := suite.CodecService.Encode(&suite.CodecProvider, &ysanity.Runner{}) + getConfigRpc := ietfNetconf.GetConfig{} + getConfigRpc.Input.Source.Candidate = types.Empty{} + getConfigRpc.Input.Filter = filterXML + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &getConfigRpc, &ysanity.Runner{}) + suite.Equal(types.EntityEqual(readEntity, &runner), true) + + // Modify Candidate via CopyConfig from runner + runner.Two.Name = fmt.Sprintf("%s_modified", runner.Two.Name) + runnerXML = suite.CodecService.Encode(&suite.CodecProvider, &runner) + + copyRpc.Input.Source.Config = runnerXML + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, ©Rpc, nil) + suite.Equal(readEntity, nil) + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &getConfigRpc, &ysanity.Runner{}) + suite.Equal(types.EntityEqual(readEntity, &runner), true) + + // Modify Running via CopyConfig from Candidate + copyRpc = ietfNetconf.CopyConfig{} + copyRpc.Input.Target.Running = types.Empty{} + copyRpc.Input.Source.Candidate = types.Empty{} + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, ©Rpc, nil) + suite.Equal(readEntity, nil) + + getConfigRpc = ietfNetconf.GetConfig{} + getConfigRpc.Input.Source.Running = types.Empty{} + getConfigRpc.Input.Filter = filterXML + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &getConfigRpc, &ysanity.Runner{}) + suite.Equal(types.EntityEqual(readEntity, &runner), true) +} + +// skip +func (suite *ExecutorServiceTestSuite) TestDeleteConfig() { + suite.T().Skip("startup/url not enabled in ConfD") + + suite.CodecProvider.Encoding = types.XML + runner := ysanity.Runner{} + runner.Two.Number = 2 + runner.Two.Name = "runner:two:name" + runnerXML := suite.CodecService.Encode(&suite.CodecProvider, &runner) + + // CopyConfig + copyRpc := ietfNetconf.CopyConfig{} + copyRpc.Input.Target.Startup = types.Empty{} + copyRpc.Input.Source.Config = runnerXML + + readEntity := suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, ©Rpc, nil) + suite.Equal(readEntity, nil) + + // DeleteConfig + deleteRpc := ietfNetconf.DeleteConfig{} + deleteRpc.Input.Target.Startup = types.Empty{} + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &deleteRpc, nil) + suite.Equal(readEntity, nil) + + // CopyConfig + copyRpc = ietfNetconf.CopyConfig{} + copyRpc.Input.Target.Url = "http://test" + copyRpc.Input.Source.Config = runnerXML + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, ©Rpc, nil) + suite.Equal(readEntity, nil) + + // DeleteConfig + deleteRpc = ietfNetconf.DeleteConfig{} + deleteRpc.Input.Target.Url = "http://test" + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &deleteRpc, nil) + suite.Equal(readEntity, nil) +} + +func (suite *ExecutorServiceTestSuite) TestCloseSession() { + closeRpc := ietfNetconf.CloseSession{} + readEntity := suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &closeRpc, nil) + suite.Equal(readEntity, nil) + + suite.NetconfProvider.Connect() + + validateRpc := ietfNetconf.Validate{} + validateRpc.Input.Source.Candidate = types.Empty{} + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &validateRpc, nil) + suite.Equal(readEntity, nil) +} + +// skip +func (suite *ExecutorServiceTestSuite) TestKillSession() { + suite.T().Skip("session-id not recognized") + + lockRpc := ietfNetconf.Lock{} + lockRpc.Input.Target.Candidate = types.Empty{} + + readEntity := suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &lockRpc, nil) + suite.Equal(readEntity, nil) + + funcDidPanic, panicValue := didPanic(func() { + suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &lockRpc, nil) }) + + suite.Equal(funcDidPanic, true) + suite.Regexp("", panicValue) + + sessionIdStr := strings.Split(panicValue, "")[1] + sessionIdStr = strings.Split(sessionIdStr, "")[0] + sessionId, err := strconv.Atoi(sessionIdStr) + suite.Equal(err, nil) + + fmt.Println(sessionId) + + killRpc := ietfNetconf.KillSession{} + killRpc.Input.SessionId = sessionId + + readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &killRpc, nil) + suite.Equal(readEntity, nil) +} + +func TestExecutorServiceTestSuite(t *testing.T) { + if testing.Verbose() { + ydk.EnableLogging(ydk.Debug) + } + suite.Run(t, new(ExecutorServiceTestSuite)) +} diff --git a/sdk/go/core/tests/netconf_service_test.go b/sdk/go/core/tests/netconf_service_test.go index de57f3770..dc55a9fa5 100644 --- a/sdk/go/core/tests/netconf_service_test.go +++ b/sdk/go/core/tests/netconf_service_test.go @@ -2,6 +2,8 @@ package test import ( "fmt" + "strconv" + "strings" ysanity "github.com/CiscoDevNet/ydk-go/ydk/models/ydktest/sanity" "github.com/CiscoDevNet/ydk-go/ydk" "github.com/CiscoDevNet/ydk-go/ydk/providers" @@ -51,7 +53,7 @@ func (suite *NetconfServiceTestSuite) TestEditCommitGet() { readEntity := suite.NS.GetConfig(&suite.Provider, types.Candidate, &ysanity.Runner{}) suite.Equal(types.EntityEqual(readEntity, &runner), true) - // // Commit + // Commit op = suite.NS.Commit(&suite.Provider, false, -1, -1, -1) suite.Equal(op, true) @@ -94,29 +96,43 @@ func (suite *NetconfServiceTestSuite) TestValidate() { suite.Equal(op, true) } -func (suite *NetconfServiceTestSuite) TestCommitDiscard(){ +func (suite *NetconfServiceTestSuite) TestDiscardChanges(){ runner := ysanity.Runner{} runner.Two.Number = 2 runner.Two.Name = "runner:two:name" + // EditConfig op := suite.NS.EditConfig(&suite.Provider, types.Candidate, &runner, "", "", "") suite.Equal(op, true) + // DiscardChanges op = suite.NS.DiscardChanges(&suite.Provider) suite.Equal(op, true) - op = suite.NS.EditConfig(&suite.Provider, types.Candidate, &runner, "", "", "") + // GetConfig + readEntity := suite.NS.GetConfig(&suite.Provider, types.Candidate, &ysanity.Runner{}) + suite.Equal(types.EntityEqual(readEntity, &ysanity.Runner{}), true) +} + +func (suite *NetconfServiceTestSuite) TestConfirmedCommit() { + runner := ysanity.Runner{} + runner.Two.Number = 2 + runner.Two.Name = "runner:two:name" + + op := suite.NS.EditConfig(&suite.Provider, types.Candidate, &runner, "", "", "") suite.Equal(op, true) - op = suite.NS.Commit(&suite.Provider, false, -1, -1, -1) + op = suite.NS.Commit(&suite.Provider, true, 120, -1, -1) suite.Equal(op, true) readEntity := suite.NS.Get(&suite.Provider, &ysanity.Runner{}) suite.Equal(types.EntityEqual(readEntity, &runner), true) } -// skipped in python/cpp -func (suite *NetconfServiceTestSuite) TestConfirmedCommit() { +// skip +func (suite *NetconfServiceTestSuite) TestCancelCommit() { + suite.T().Skip("No message id in cancel commit payload") + runner := ysanity.Runner{} runner.Two.Number = 2 runner.Two.Name = "runner:two:name" @@ -127,8 +143,8 @@ func (suite *NetconfServiceTestSuite) TestConfirmedCommit() { op = suite.NS.Commit(&suite.Provider, true, 120, -1, -1) suite.Equal(op, true) - // op = suite.NS.CancelCommit(&suite.Provider, -1) - // suite.Equal(op, true) + op = suite.NS.CancelCommit(&suite.Provider, -1) + suite.Equal(op, true) readEntity := suite.NS.Get(&suite.Provider, &ysanity.Runner{}) suite.Equal(types.EntityEqual(readEntity, &runner), true) @@ -172,6 +188,7 @@ func (suite *NetconfServiceTestSuite) TestCopyConfig() { suite.Equal(types.EntityEqual(readEntity, &runner), true) } +// skip func (suite *NetconfServiceTestSuite) TestDeleteConfig() { suite.T().Skip("startup not enabled in ConfD") @@ -201,11 +218,24 @@ func (suite *NetconfServiceTestSuite) TestCloseSession() { suite.Equal(op, true) } - +// skip func (suite *NetconfServiceTestSuite) TestKillSession() { - funcDidPanic, panicValue := didPanic(func() { suite.NS.KillSession(&suite.Provider, 1) }) + suite.T().Skip("session-id not recognized") + + op := suite.NS.Lock(&suite.Provider, types.Candidate) + suite.Equal(op, true) + + funcDidPanic, panicValue := didPanic(func() { suite.NS.Lock(&suite.Provider, types.Candidate) }) suite.Equal(funcDidPanic, true) - suite.Regexp("YGOServiceProviderError:", panicValue) + suite.Regexp("", panicValue) + + sessionIdStr := strings.Split(panicValue, "")[1] + sessionIdStr = strings.Split(sessionIdStr, "")[0] + sessionId, err := strconv.Atoi(sessionIdStr) + suite.Equal(err, nil) + + op = suite.NS.KillSession(&suite.Provider, sessionId) + suite.Equal(op, true) } func TestNetconfServiceTestSuite(t *testing.T) { @@ -214,24 +244,3 @@ func TestNetconfServiceTestSuite(t *testing.T) { } suite.Run(t, new(NetconfServiceTestSuite)) } - - -// didPanic returns true if the function passed to it panics. Otherwise, it returns false. -func didPanic(panicTestFunc func()) (bool, string) { - - didPanic := false - var message interface{} - func() { - - defer func() { - if message = recover(); message != nil { - didPanic = true - } - }() - - // call the target function - panicTestFunc() - - }() - return didPanic, message.(string) -} \ No newline at end of file diff --git a/sdk/go/core/ydk/path/path.go b/sdk/go/core/ydk/path/path.go index 19ca5ca90..904e1554f 100644 --- a/sdk/go/core/ydk/path/path.go +++ b/sdk/go/core/ydk/path/path.go @@ -106,6 +106,95 @@ func getDataPayload(state *types.State, entity types.Entity, rootSchema C.RootSc return (data) } +func ExecuteRpcEntity(provider types.ServiceProvider, rpcEntity, topEntity types.Entity) types.Entity { + state := provider.GetState() + cstate := getCState(state) + wrappedProvider := provider.GetPrivate().(types.CServiceProvider) + realProvider := wrappedProvider.Private.(C.ServiceProvider) + rootSchema := C.ServiceProviderGetRootSchema(*cstate, realProvider) + panicOnCStateError(cstate) + + ydkRPC := C.RootSchemaNodeRpc(*cstate, rootSchema, C.CString(rpcEntity.GetSegmentPath())) + panicOnCStateError(cstate) + + if rootSchema == nil { + panic(1) + } + + rpcInput := C.RpcInput(*cstate, ydkRPC) + panicOnCStateError(cstate) + + child := rpcEntity.GetChildByName("input", "") + walkRpcChildren(state, child, rpcInput, "") + + readDataNode := types.DataNode{C.RpcExecute(*cstate, ydkRPC, realProvider)} + panicOnCStateError(cstate) + + output := rpcEntity.GetChildByName("output", "") + + if (output == nil || readDataNode.Private == nil) { + return nil + } + return ReadDatanode(topEntity, readDataNode) +} + +func walkRpcChildren(state *types.State, rpcEntity types.Entity, rpcInput C.DataNode, path string) { + fmt.Printf("Walking Rpc Children...\n") + if(rpcEntity != nil) { + children := rpcEntity.GetChildren() + entityPath := rpcEntity.GetEntityPath(rpcEntity.GetParent()) + fmt.Printf("Got %d entity children in '%s'\n", len(children), entityPath.Path) + fmt.Printf("Got %d leafs in '%s'\n", len(entityPath.ValuePaths), entityPath.Path) + + if (path != "") { + path = fmt.Sprintf("%s/", path) + } + + if (entityPath.Path != "input") { + path = fmt.Sprintf("%s%s", path, entityPath.Path) + } + + if (path != "") { + fmt.Printf("Path: %s\n", path) + } + + for childName, _ := range children { + fmt.Printf("Looking at entity child '%s'\n", children[childName].GetSegmentPath()) + walkRpcChildren(state, children[childName], rpcInput, path) + } + + // if there are leafs, create from entity path + if (len(entityPath.ValuePaths) != 0) { + createFromEntityPath(state, rpcEntity, rpcInput, path) + } + + createFromChildren(state, children, rpcInput) + } +} + +func createFromEntityPath(state *types.State, rpcEntity types.Entity, rpcInput C.DataNode, path string) { + entityPath := rpcEntity.GetEntityPath(rpcEntity.GetParent()) + for _, nameValue := range entityPath.ValuePaths { + fmt.Printf("Creating leaf '%s' with value '%s' in '%s'\n", nameValue.Name, nameValue.Data.Value, entityPath.Path) + + tempPath := "" + if (path != "") { + tempPath = fmt.Sprintf("%s/", path) + } + tempPath = fmt.Sprintf("%s%s", tempPath, nameValue.Name) + C.DataNodeCreate(*getCState(state), rpcInput, C.CString(tempPath), C.CString(nameValue.Data.Value)) + } +} + +func createFromChildren(state *types.State, children map[string]types.Entity, rpcInput C.DataNode) { + for childName, child := range children { + if (len(child.GetChildren()) == 0) { + fmt.Printf("Creating child '%s' : %s\n", childName, child.GetEntityPath(child.GetParent()).Path) + C.DataNodeCreate(*getCState(state), rpcInput, C.CString(childName), C.CString("")) + } + } +} + func getTopEntityFromFilter(filter types.Entity) types.Entity { if filter.GetParent() == nil { return filter @@ -420,7 +509,7 @@ func walkChildren(state *types.State, entity types.Entity, dataNode C.DataNode) for childName := range children { - fmt.Printf("Lookin at entity child '%s'\n", children[childName].GetSegmentPath()) + fmt.Printf("Looking at entity child '%s'\n", children[childName].GetSegmentPath()) if children[childName].HasDataOrFilter() { populateDataNode(state, children[childName], dataNode) diff --git a/sdk/go/core/ydk/services/services.go b/sdk/go/core/ydk/services/services.go index 939d4ff58..dda4e4c9b 100644 --- a/sdk/go/core/ydk/services/services.go +++ b/sdk/go/core/ydk/services/services.go @@ -107,6 +107,18 @@ func (c *CodecService) Decode(provider types.CodecServiceProvider, payload strin return path.CodecServiceDecode(provider.GetState(), rootSchema, payload, provider.GetEncoding(), topEntity) } +// ExecutorService provides the functionality to execute RPCs +type ExecutorService struct { +} + +// ExecuteRpc creates the entity represented by rpcEntity +// Any expected return data uses topEntity as a filter +func (es *ExecutorService) ExecuteRpc ( + provider types.ServiceProvider, rpcEntity, topEntity types.Entity) types.Entity { + + return path.ExecuteRpcEntity(provider, rpcEntity, topEntity) +} + // NetconfService implements the NETCONF Protocol Operations: https://tools.ietf.org/html/rfc6241 type NetconfService struct { } From d76945dbb2d8e2b68649581d1388f3476d3c1ab5 Mon Sep 17 00:00:00 2001 From: lily Date: Mon, 16 Oct 2017 10:34:51 -0700 Subject: [PATCH 05/10] fixed issue #599 --- ydkgen/printer/go/class_constructor_printer.py | 2 +- ydkgen/printer/go/class_has_data_printer.py | 2 +- ydkgen/printer/go/class_printer.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ydkgen/printer/go/class_constructor_printer.py b/ydkgen/printer/go/class_constructor_printer.py index baabf00b5..4bc843608 100644 --- a/ydkgen/printer/go/class_constructor_printer.py +++ b/ydkgen/printer/go/class_constructor_printer.py @@ -39,7 +39,7 @@ def print_function_header(self): def print_function_body(self): self.ctx.writeln('parent types.Entity') - self.ctx.writeln('Filter types.YFilter') + self.ctx.writeln('YFilter types.YFilter') self._print_inits() def _print_docstring(self): diff --git a/ydkgen/printer/go/class_has_data_printer.py b/ydkgen/printer/go/class_has_data_printer.py index 0d9997a4a..dc7716a85 100644 --- a/ydkgen/printer/go/class_has_data_printer.py +++ b/ydkgen/printer/go/class_has_data_printer.py @@ -52,7 +52,7 @@ def print_function_body(self): def _get_conditions(self): conditions = [] - conditions.append('{}.Filter != types.NotSet'.format(self.class_alias)) + conditions.append('{}.YFilter != types.NotSet'.format(self.class_alias)) line = '{0}.%s != nil'.format(self.class_alias) conditions.extend([line % l.go_name() for l in self.leafs if not l.is_many]) diff --git a/ydkgen/printer/go/class_printer.py b/ydkgen/printer/go/class_printer.py index a948fb13e..f0bd89503 100644 --- a/ydkgen/printer/go/class_printer.py +++ b/ydkgen/printer/go/class_printer.py @@ -87,14 +87,14 @@ def _print_class_has_data(self, clazz, leafs, children): def _print_class_get_filter(self, clazz): fp = FunctionPrinter(self.ctx, clazz) fp.print_function_header_helper('GetFilter', return_type='types.YFilter') - fp.ctx.writeln('return %s.Filter' % fp.class_alias) + fp.ctx.writeln('return %s.YFilter' % fp.class_alias) fp.print_function_trailer() # SetFilter def _print_class_set_filter(self, clazz): fp = FunctionPrinter(self.ctx, clazz) fp.print_function_header_helper('SetFilter', args='yfilter types.YFilter') - fp.ctx.writeln('%s.Filter = yfilter' % fp.class_alias) + fp.ctx.writeln('%s.YFilter = yfilter' % fp.class_alias) fp.print_function_trailer() # GetSegmentPath From d3bb38e3f93f8ff35ad5b8d7ae93dd4284435872 Mon Sep 17 00:00:00 2001 From: lily Date: Mon, 16 Oct 2017 16:42:05 -0700 Subject: [PATCH 06/10] added Go logging wrapper, replace Printf() with logging in path.go --- sdk/cpp/core/src/ydk.cpp | 21 ++++++++++++++++ sdk/cpp/core/src/ydk.h | 5 ++++ sdk/go/core/tests/logging_test.go | 30 ++++++++++++++++++++++ sdk/go/core/ydk/logging.go | 21 ++++++++++++++++ sdk/go/core/ydk/path/path.go | 41 +++++++++++++++++-------------- 5 files changed, 99 insertions(+), 19 deletions(-) create mode 100644 sdk/go/core/tests/logging_test.go diff --git a/sdk/cpp/core/src/ydk.cpp b/sdk/cpp/core/src/ydk.cpp index 080605e5e..66bbc54e0 100644 --- a/sdk/cpp/core/src/ydk.cpp +++ b/sdk/cpp/core/src/ydk.cpp @@ -26,6 +26,7 @@ #include "crud_service.hpp" #include "errors.hpp" +#include "logger.hpp" #include "netconf_provider.hpp" #include "opendaylight_provider.hpp" #include "restconf_provider.hpp" @@ -763,3 +764,23 @@ LogLevel GetLoggingLevel(void) } } +void YLogInfo(const char* msg) +{ + ydk::YLOG_INFO(msg); +} + +void YLogDebug(const char* msg) +{ + ydk::YLOG_DEBUG(msg); +} + +void YLogWarn(const char* msg) +{ + ydk::YLOG_WARN(msg); +} + +void YLogError(const char* msg) +{ + ydk::YLOG_ERROR(msg); +} + diff --git a/sdk/cpp/core/src/ydk.h b/sdk/cpp/core/src/ydk.h index 4b6b58032..ccda5e33f 100644 --- a/sdk/cpp/core/src/ydk.h +++ b/sdk/cpp/core/src/ydk.h @@ -149,6 +149,11 @@ void EnableLogging(LogLevel); LogLevel GetLoggingLevel(void); // LogLevel GetLoggingLevel(YDKState*, void); +void YLogInfo(const char*); +void YLogDebug(const char*); +void YLogWarn(const char*); +void YLogError(const char*); + #ifdef __cplusplus } #endif diff --git a/sdk/go/core/tests/logging_test.go b/sdk/go/core/tests/logging_test.go new file mode 100644 index 000000000..9ad0a2d24 --- /dev/null +++ b/sdk/go/core/tests/logging_test.go @@ -0,0 +1,30 @@ +package test + +import ( + "fmt" + "github.com/CiscoDevNet/ydk-go/ydk" + "github.com/stretchr/testify/suite" + "testing" +) + +type LoggingTestSuite struct { + suite.Suite +} + +func (suite *LoggingTestSuite) BeforeTest(suiteName, testName string) { + fmt.Printf("%v: %v ...\n", suiteName, testName) +} + +func (suite *LoggingTestSuite) TestLogging() { + ydk.YLogInfo("Testing YLogInfo") + ydk.YLogDebug("Testing YLogDebug") + ydk.YLogWarn("Testing YLogDebug") + ydk.YLogError("Testing YLogDebug") +} + +func TestLoggingTestSuite(t *testing.T) { + if testing.Verbose() { + ydk.EnableLogging(ydk.Debug) + } + suite.Run(t, new(LoggingTestSuite)) +} diff --git a/sdk/go/core/ydk/logging.go b/sdk/go/core/ydk/logging.go index 997a43dd5..f7fc94164 100644 --- a/sdk/go/core/ydk/logging.go +++ b/sdk/go/core/ydk/logging.go @@ -29,6 +29,7 @@ package ydk // #cgo linux LDFLAGS: -fprofile-arcs -ftest-coverage --coverage -lydk -lxml2 -lxslt -lpcre -lssh -lssh_threads -lcurl -lstdc++ -lpython2.7 -ldl //#include import "C" +import "fmt" // LogLevel indicates what level of logging to output type LogLevel int @@ -56,3 +57,23 @@ func EnableLogging(level LogLevel) { C.EnableLogging(C.ERROR) } } + +func YLogInfo(msg string){ + msg = fmt.Sprintf("[Go] %s", msg) + C.YLogInfo(C.CString(msg)); +} + +func YLogDebug(msg string){ + msg = fmt.Sprintf("[Go] %s", msg) + C.YLogDebug(C.CString(msg)); +} + +func YLogWarn(msg string){ + msg = fmt.Sprintf("[Go] %s", msg) + C.YLogWarn(C.CString(msg)); +} + +func YLogError(msg string){ + msg = fmt.Sprintf("[Go] %s", msg) + C.YLogError(C.CString(msg)); +} diff --git a/sdk/go/core/ydk/path/path.go b/sdk/go/core/ydk/path/path.go index 904e1554f..452b410f1 100644 --- a/sdk/go/core/ydk/path/path.go +++ b/sdk/go/core/ydk/path/path.go @@ -33,6 +33,7 @@ import "C" import ( "fmt" + "github.com/CiscoDevNet/ydk-go/ydk" "github.com/CiscoDevNet/ydk-go/ydk/types" "strings" "unsafe" @@ -139,12 +140,12 @@ func ExecuteRpcEntity(provider types.ServiceProvider, rpcEntity, topEntity types } func walkRpcChildren(state *types.State, rpcEntity types.Entity, rpcInput C.DataNode, path string) { - fmt.Printf("Walking Rpc Children...\n") + ydk.YLogInfo("Walking Rpc Children...") if(rpcEntity != nil) { children := rpcEntity.GetChildren() entityPath := rpcEntity.GetEntityPath(rpcEntity.GetParent()) - fmt.Printf("Got %d entity children in '%s'\n", len(children), entityPath.Path) - fmt.Printf("Got %d leafs in '%s'\n", len(entityPath.ValuePaths), entityPath.Path) + ydk.YLogInfo(fmt.Sprintf("Got %d entity children in '%s'", len(children), entityPath.Path)) + ydk.YLogInfo(fmt.Sprintf("Got %d leafs in '%s'", len(entityPath.ValuePaths), entityPath.Path)) if (path != "") { path = fmt.Sprintf("%s/", path) @@ -155,11 +156,11 @@ func walkRpcChildren(state *types.State, rpcEntity types.Entity, rpcInput C.Data } if (path != "") { - fmt.Printf("Path: %s\n", path) + ydk.YLogInfo(fmt.Sprintf("Path: %s", path)) } for childName, _ := range children { - fmt.Printf("Looking at entity child '%s'\n", children[childName].GetSegmentPath()) + ydk.YLogInfo(fmt.Sprintf("Looking at entity child '%s'", children[childName].GetSegmentPath())) walkRpcChildren(state, children[childName], rpcInput, path) } @@ -175,7 +176,8 @@ func walkRpcChildren(state *types.State, rpcEntity types.Entity, rpcInput C.Data func createFromEntityPath(state *types.State, rpcEntity types.Entity, rpcInput C.DataNode, path string) { entityPath := rpcEntity.GetEntityPath(rpcEntity.GetParent()) for _, nameValue := range entityPath.ValuePaths { - fmt.Printf("Creating leaf '%s' with value '%s' in '%s'\n", nameValue.Name, nameValue.Data.Value, entityPath.Path) + ydk.YLogInfo(fmt.Sprintf("Creating leaf '%s' with value '%s' in '%s'", + nameValue.Name, nameValue.Data.Value, entityPath.Path)) tempPath := "" if (path != "") { @@ -189,7 +191,8 @@ func createFromEntityPath(state *types.State, rpcEntity types.Entity, rpcInput C func createFromChildren(state *types.State, children map[string]types.Entity, rpcInput C.DataNode) { for childName, child := range children { if (len(child.GetChildren()) == 0) { - fmt.Printf("Creating child '%s' : %s\n", childName, child.GetEntityPath(child.GetParent()).Path) + ydk.YLogInfo(fmt.Sprintf("Creating child '%s' : %s", + childName, child.GetEntityPath(child.GetParent()).Path)) C.DataNodeCreate(*getCState(state), rpcInput, C.CString(childName), C.CString("")) } } @@ -211,7 +214,7 @@ func ReadDatanode(filter types.Entity, readDataNode types.DataNode) types.Entity } topEntity := getTopEntityFromFilter(filter) - fmt.Printf("Reading top entity: '%s'\n", topEntity.GetSegmentPath()) + ydk.YLogInfo(fmt.Sprintf("Reading top entity: '%s'", topEntity.GetSegmentPath())) cchildren := C.DataNodeGetChildren(readDataNode.Private.(C.DataNode)) @@ -320,11 +323,11 @@ func InitCodecServiceProvider(state *types.State, entity types.Entity, repo type defer C.free(unsafe.Pointer(repoPath)) if len(repo.Path) > 0 { - fmt.Printf("CodecServiceProvider using YANG models in %v\n", repo.Path) + ydk.YLogInfo(fmt.Sprintf("CodecServiceProvider using YANG models in %v", repo.Path)) repoPath = C.CString(repo.Path) } else { yangPath := entity.GetBundleYangModelsLocation() - fmt.Printf("CodecServiceProvider using YANG models in %v\n", yangPath) + ydk.YLogInfo(fmt.Sprintf("CodecServiceProvider using YANG models in %v", yangPath)) repoPath = C.CString(yangPath) } @@ -505,17 +508,17 @@ func getDataNodeFromEntity(state *types.State, entity types.Entity, rootSchema C func walkChildren(state *types.State, entity types.Entity, dataNode C.DataNode) { children := entity.GetChildren() - fmt.Printf("Got %d entity children\n", len(children)) + ydk.YLogInfo(fmt.Sprintf("Got %d entity children", len(children))) for childName := range children { - fmt.Printf("Looking at entity child '%s'\n", children[childName].GetSegmentPath()) + ydk.YLogInfo(fmt.Sprintf("Looking at entity child '%s'", children[childName].GetSegmentPath())) if children[childName].HasDataOrFilter() { populateDataNode(state, children[childName], dataNode) } } - fmt.Println() + ydk.YLogInfo("") } func populateDataNode(state *types.State, entity types.Entity, parentDataNode C.DataNode) { @@ -543,7 +546,7 @@ func populateNameValues(state *types.State, dataNode C.DataNode, path types.Enti var result C.DataNode leafData := nameValue.Data p := C.CString(nameValue.Name) - fmt.Printf("got leaf {%s: %s}\n", nameValue.Name, nameValue.Data.Value) + ydk.YLogInfo(fmt.Sprintf("got leaf {%s: %s}", nameValue.Name, nameValue.Data.Value)) if leafData.IsSet { p1 := C.CString(leafData.Value) @@ -567,26 +570,26 @@ func getEntityFromDataNode(node C.DataNode, entity types.Entity) { cchildren := C.DataNodeGetChildren(node) children := (*[1 << 30]C.DataNode)(unsafe.Pointer(cchildren.datanodes))[:cchildren.count:cchildren.count] - fmt.Printf("Got %d datanode children\n", cchildren.count) + ydk.YLogInfo(fmt.Sprintf("Got %d datanode children", cchildren.count)) for _, childDataNode := range children { childName := C.GoString(C.DataNodeGetArgument(childDataNode)) - fmt.Printf("Looking at child datanode: '%s'\n", childName) + ydk.YLogInfo(fmt.Sprintf("Looking at child datanode: '%s'", childName)) if dataNodeIsLeaf(childDataNode) { value := C.GoString(C.DataNodeGetValue(childDataNode)) - fmt.Printf("Creating leaf '%s' with value '%s'\n", childName, value) + ydk.YLogInfo(fmt.Sprintf("Creating leaf '%s' with value '%s'", childName, value)) entity.SetValue(childName, value) } else { var childEntity types.Entity if dataNodeIsList(childDataNode) { segmentPath := C.GoString(C.DataNodeGetSegmentPath(childDataNode)) - fmt.Printf("Creating child list instance '%s'\n", segmentPath) + ydk.YLogInfo(fmt.Sprintf("Creating child list instance '%s'", segmentPath)) childEntity = entity.GetChildByName(childName, segmentPath) } else { - fmt.Printf("Creating child node '%s'\n", childName) + ydk.YLogInfo(fmt.Sprintf("Creating child node '%s'", childName)) childEntity = entity.GetChildByName(childName, "") } if childEntity == nil { From 4f91040e80d7a32d5613a50f1bcda5e0642ac3b1 Mon Sep 17 00:00:00 2001 From: lily Date: Tue, 17 Oct 2017 10:44:40 -0700 Subject: [PATCH 07/10] fix typos in go tests --- sdk/go/core/tests/executor_service_test.go | 2 ++ sdk/go/core/tests/netconf_operations_test.go | 23 ++++++++++---------- sdk/go/core/tests/netconf_service_test.go | 3 +++ sdk/go/core/tests/sanity_types_test.go | 10 ++++----- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/sdk/go/core/tests/executor_service_test.go b/sdk/go/core/tests/executor_service_test.go index 80e3129f4..3c6698f62 100644 --- a/sdk/go/core/tests/executor_service_test.go +++ b/sdk/go/core/tests/executor_service_test.go @@ -232,7 +232,9 @@ func (suite *ExecutorServiceTestSuite) TestCancelCommit() { suite.Equal(readEntity, nil) } +// skip func (suite *ExecutorServiceTestSuite) TestCopyConfig() { + suite.T().Skip("Crashes ConfD connection") suite.CodecProvider.Encoding = types.XML runner := ysanity.Runner{} runner.Two.Number = 2 diff --git a/sdk/go/core/tests/netconf_operations_test.go b/sdk/go/core/tests/netconf_operations_test.go index 8baf4bd26..d0cea9c71 100644 --- a/sdk/go/core/tests/netconf_operations_test.go +++ b/sdk/go/core/tests/netconf_operations_test.go @@ -6,7 +6,6 @@ import ( "github.com/CiscoDevNet/ydk-go/ydk/providers" "github.com/CiscoDevNet/ydk-go/ydk/services" "github.com/CiscoDevNet/ydk-go/ydk/types" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" "testing" ) @@ -72,14 +71,12 @@ func (suite *NETCONFOperationsTestSuite) TestCreate() { // create duplicate value raises error // The payload errMsg is hardcoded with message-id of certain value. // Please change corresponding message-id if new tests are added/enabled. - errMsg := `YGOServiceProviderError: - - + errMsg := ` application data-exists error - /nc:rpc/nc:edit-config/nc:config/ydkut:runner/ydkut:one-list/ydkut:ldata[ydkut:number='1'] + /nc:rpc/nc:edit-config/nc:config/ydkut:runner/ydkut:one-list/ydkut:ldata\[ydkut:number='[1-2]'] ldata @@ -87,7 +84,10 @@ func (suite *NETCONFOperationsTestSuite) TestCreate() { ` - assert.PanicsWithValue(suite.T(), errMsg, func() { suite.CRUD.Update(&suite.Provider, &runnerCreate) }) + funcDidPanic, panicValue := didPanic(func() { suite.CRUD.Update(&suite.Provider, &runnerCreate) }) + suite.Equal(funcDidPanic, true) + suite.Regexp("YGOServiceProviderError:", panicValue) + suite.Regexp(errMsg, panicValue) } func (suite *NETCONFOperationsTestSuite) TestDelete() { @@ -116,14 +116,12 @@ func (suite *NETCONFOperationsTestSuite) TestDelete() { // delete again raises error // The payload errMsg is hardcoded with message-id of certain value. // Please change corresponding message-id if new tests are added/enabled. - errMsg := `YGOServiceProviderError: - - + errMsg := ` application data-missing error - /nc:rpc/nc:edit-config/nc:config/ydkut:runner/ydkut:one-list/ydkut:ldata[ydkut:number='1'] + /nc:rpc/nc:edit-config/nc:config/ydkut:runner/ydkut:one-list/ydkut:ldata\[ydkut:number='[1-2]'] ldata @@ -131,7 +129,10 @@ func (suite *NETCONFOperationsTestSuite) TestDelete() { ` - assert.PanicsWithValue(suite.T(), errMsg, func() { suite.CRUD.Update(&suite.Provider, &runnerUpdate) }) + funcDidPanic, panicValue := didPanic(func() { suite.CRUD.Update(&suite.Provider, &runnerUpdate) }) + suite.Equal(funcDidPanic, true) + suite.Regexp("YGOServiceProviderError:", panicValue) + suite.Regexp(errMsg, panicValue) } func (suite *NETCONFOperationsTestSuite) TestRemove() { diff --git a/sdk/go/core/tests/netconf_service_test.go b/sdk/go/core/tests/netconf_service_test.go index dc55a9fa5..c0a8520c5 100644 --- a/sdk/go/core/tests/netconf_service_test.go +++ b/sdk/go/core/tests/netconf_service_test.go @@ -150,10 +150,13 @@ func (suite *NetconfServiceTestSuite) TestCancelCommit() { suite.Equal(types.EntityEqual(readEntity, &runner), true) } +// skip // TODO: Problems found with path functions: // readEntity changes with getFilter // EntityEqual(readEntity, &runner) returns true, even after the above func (suite *NetconfServiceTestSuite) TestCopyConfig() { + suite.T().Skip("Crashes ConfD connection") + runner := ysanity.Runner{} runner.Two.Number = 2 runner.Two.Name = "runner:two:name" diff --git a/sdk/go/core/tests/sanity_types_test.go b/sdk/go/core/tests/sanity_types_test.go index 773260084..9008684b6 100644 --- a/sdk/go/core/tests/sanity_types_test.go +++ b/sdk/go/core/tests/sanity_types_test.go @@ -7,7 +7,6 @@ import ( "github.com/CiscoDevNet/ydk-go/ydk/providers" "github.com/CiscoDevNet/ydk-go/ydk/services" "github.com/CiscoDevNet/ydk-go/ydk/types" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" "strconv" "testing" @@ -282,9 +281,7 @@ func (suite *SanityTypesTestSuite) TestListMaxElements() { runner.OneList.Ldata = elems // The payload errMsg is hardcoded with message-id of certain value. // Please change corresponding message-id if new tests are added/enabled. - errMsg := `YGOServiceProviderError: - - + errMsg := ` application operation-failed error @@ -303,7 +300,10 @@ func (suite *SanityTypesTestSuite) TestListMaxElements() { ` - assert.PanicsWithValue(suite.T(), errMsg, func() { suite.CRUD.Create(&suite.Provider, &runner) }) + funcDidPanic, panicValue := didPanic(func() { suite.CRUD.Create(&suite.Provider, &runner) }) + suite.Equal(funcDidPanic, true) + suite.Regexp("YGOServiceProviderError:", panicValue) + suite.Regexp(errMsg, panicValue) } func (suite *SanityTypesTestSuite) TestSubmodule() { From 9e137b9eed3d1b5028eacc002b90b7a925f0b0b6 Mon Sep 17 00:00:00 2001 From: lily Date: Wed, 18 Oct 2017 12:02:25 -0700 Subject: [PATCH 08/10] update copyconfig test to not break confd --- sdk/go/core/tests/executor_service_test.go | 24 ++++++++++++++-------- sdk/go/core/tests/netconf_service_test.go | 15 +++++++------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/sdk/go/core/tests/executor_service_test.go b/sdk/go/core/tests/executor_service_test.go index 3c6698f62..8d2a5f3f6 100644 --- a/sdk/go/core/tests/executor_service_test.go +++ b/sdk/go/core/tests/executor_service_test.go @@ -232,9 +232,7 @@ func (suite *ExecutorServiceTestSuite) TestCancelCommit() { suite.Equal(readEntity, nil) } -// skip func (suite *ExecutorServiceTestSuite) TestCopyConfig() { - suite.T().Skip("Crashes ConfD connection") suite.CodecProvider.Encoding = types.XML runner := ysanity.Runner{} runner.Two.Number = 2 @@ -256,7 +254,8 @@ func (suite *ExecutorServiceTestSuite) TestCopyConfig() { getConfigRpc.Input.Source.Candidate = types.Empty{} getConfigRpc.Input.Filter = filterXML - readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &getConfigRpc, &ysanity.Runner{}) + readEntity = suite.ExecutorService.ExecuteRpc( + &suite.NetconfProvider, &getConfigRpc, &ysanity.Runner{}) suite.Equal(types.EntityEqual(readEntity, &runner), true) // Modify Candidate via CopyConfig from runner @@ -268,23 +267,30 @@ func (suite *ExecutorServiceTestSuite) TestCopyConfig() { readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, ©Rpc, nil) suite.Equal(readEntity, nil) - readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &getConfigRpc, &ysanity.Runner{}) + readEntity = suite.ExecutorService.ExecuteRpc( + &suite.NetconfProvider, &getConfigRpc, &ysanity.Runner{}) suite.Equal(types.EntityEqual(readEntity, &runner), true) - // Modify Running via CopyConfig from Candidate + // Modify Candidate via CopyConfig from Running copyRpc = ietfNetconf.CopyConfig{} - copyRpc.Input.Target.Running = types.Empty{} - copyRpc.Input.Source.Candidate = types.Empty{} + copyRpc.Input.Target.Candidate = types.Empty{} + copyRpc.Input.Source.Running = types.Empty{} readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, ©Rpc, nil) suite.Equal(readEntity, nil) getConfigRpc = ietfNetconf.GetConfig{} - getConfigRpc.Input.Source.Running = types.Empty{} + getConfigRpc.Input.Source.Candidate = types.Empty{} getConfigRpc.Input.Filter = filterXML - readEntity = suite.ExecutorService.ExecuteRpc(&suite.NetconfProvider, &getConfigRpc, &ysanity.Runner{}) + readEntity = suite.ExecutorService.ExecuteRpc( + &suite.NetconfProvider, &getConfigRpc, &ysanity.Runner{}) suite.Equal(types.EntityEqual(readEntity, &runner), true) + + // DiscardChanges + readEntity = suite.ExecutorService.ExecuteRpc( + &suite.NetconfProvider, &ietfNetconf.DiscardChanges{}, nil) + suite.Equal(readEntity, nil) } // skip diff --git a/sdk/go/core/tests/netconf_service_test.go b/sdk/go/core/tests/netconf_service_test.go index c0a8520c5..962281c71 100644 --- a/sdk/go/core/tests/netconf_service_test.go +++ b/sdk/go/core/tests/netconf_service_test.go @@ -150,13 +150,10 @@ func (suite *NetconfServiceTestSuite) TestCancelCommit() { suite.Equal(types.EntityEqual(readEntity, &runner), true) } -// skip // TODO: Problems found with path functions: // readEntity changes with getFilter // EntityEqual(readEntity, &runner) returns true, even after the above func (suite *NetconfServiceTestSuite) TestCopyConfig() { - suite.T().Skip("Crashes ConfD connection") - runner := ysanity.Runner{} runner.Two.Number = 2 runner.Two.Name = "runner:two:name" @@ -183,12 +180,16 @@ func (suite *NetconfServiceTestSuite) TestCopyConfig() { suite.Equal(types.EntityEqual(readEntity, &runner), true) getFilter = ysanity.Runner{} - // Modify Running via CopyConfig from Candidate - op = suite.NS.CopyConfig(&suite.Provider, types.Running, types.Candidate, nil, "") + // Modify Candidate via CopyConfig from Running + op = suite.NS.CopyConfig(&suite.Provider, types.Candidate, types.Running, nil, "") suite.Equal(op, true) - readEntity = suite.NS.GetConfig(&suite.Provider, types.Running, &getFilter) - suite.Equal(types.EntityEqual(readEntity, &runner), true) + readEntity = suite.NS.GetConfig(&suite.Provider, types.Candidate, &getFilter) + suite.Equal(types.EntityEqual(readEntity, &ysanity.Runner{}), true) + + // DiscardChanges + op = suite.NS.DiscardChanges(&suite.Provider) + suite.Equal(op, true) } // skip From 3a19fb9b07da04ecb9ff2c3d3efd3306274b28b1 Mon Sep 17 00:00:00 2001 From: lily Date: Wed, 18 Oct 2017 12:03:30 -0700 Subject: [PATCH 09/10] update tests to use YFilter instead of Filter --- sdk/go/core/tests/delete_test.go | 10 +++++----- sdk/go/core/tests/filters_test.go | 2 +- sdk/go/core/tests/netconf_operations_test.go | 20 ++++++++++---------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sdk/go/core/tests/delete_test.go b/sdk/go/core/tests/delete_test.go index 863fb6f9c..47cc4834f 100644 --- a/sdk/go/core/tests/delete_test.go +++ b/sdk/go/core/tests/delete_test.go @@ -165,7 +165,7 @@ func (suite *DeleteTestSuite) TestDeleteOnListWithIdentitykey() { k := ysanity.Runner_OneList_IdentityList{} k.Config.Id = ysanity.Child_Identity{} k.IdRef = ysanity.Child_Identity{} - k.Filter = types.Delete + k.YFilter = types.Delete runnerUpdate.OneList.IdentityList = append(runnerUpdate.OneList.IdentityList, k) suite.CRUD.Update(&suite.Provider, &runnerUpdate) @@ -181,7 +181,7 @@ func (suite *DeleteTestSuite) TestDeleteOnContainer() { suite.CRUD.Create(&suite.Provider, &runnerCreate) runnerUpdate := ysanity.Runner{} - runnerUpdate.Two.Filter = types.Delete + runnerUpdate.Two.YFilter = types.Delete suite.CRUD.Update(&suite.Provider, &runnerUpdate) runnerCmp := ysanity.Runner{} @@ -217,7 +217,7 @@ func (suite *DeleteTestSuite) TestDeleteOnListElement() { suite.CRUD.Create(&suite.Provider, &runnerCreate) runnerUpdate := runnerCreate - runnerUpdate.InbtwList.Ldata[1].Filter = types.Delete + runnerUpdate.InbtwList.Ldata[1].YFilter = types.Delete suite.CRUD.Update(&suite.Provider, &runnerUpdate) entity := suite.CRUD.Read(&suite.Provider, &ysanity.Runner{}) @@ -249,8 +249,8 @@ func (suite *DeleteTestSuite) TestDeleteOnListElements() { entity := suite.CRUD.Read(&suite.Provider, &ysanity.Runner{}) runnerUpdate := entity.(*ysanity.Runner) - runnerUpdate.OneList.Ldata[1].Filter = types.Delete - runnerUpdate.OneList.Ldata[2].Filter = types.Delete + runnerUpdate.OneList.Ldata[1].YFilter = types.Delete + runnerUpdate.OneList.Ldata[2].YFilter = types.Delete suite.CRUD.Update(&suite.Provider, runnerUpdate) diff --git a/sdk/go/core/tests/filters_test.go b/sdk/go/core/tests/filters_test.go index d27ecd5bd..8fa4750ee 100644 --- a/sdk/go/core/tests/filters_test.go +++ b/sdk/go/core/tests/filters_test.go @@ -42,7 +42,7 @@ func (suite *FiltersTestSuite) TestReadOnRefClass() { suite.CRUD.Create(&suite.Provider, &r1) r2 := ysanity.Runner{} - r2.One.Filter = types.Read + r2.One.YFilter = types.Read entity := suite.CRUD.Read(&suite.Provider, &r2) suite.Equal(types.EntityEqual(entity, &r1), true) diff --git a/sdk/go/core/tests/netconf_operations_test.go b/sdk/go/core/tests/netconf_operations_test.go index d0cea9c71..999e57bd6 100644 --- a/sdk/go/core/tests/netconf_operations_test.go +++ b/sdk/go/core/tests/netconf_operations_test.go @@ -37,7 +37,7 @@ func (suite *NETCONFOperationsTestSuite) BeforeTest(suiteName, testName string) func (suite *NETCONFOperationsTestSuite) TestReplace() { runner := ysanity.Runner{} - runner.Filter = types.Delete + runner.YFilter = types.Delete suite.CRUD.Update(&suite.Provider, &runner) runnerCreate := ysanity.Runner{} @@ -46,7 +46,7 @@ func (suite *NETCONFOperationsTestSuite) TestReplace() { runnerUpdate := ysanity.Runner{} runnerUpdate.Ytypes.BuiltInT.Number8 = 25 - runnerUpdate.Filter = types.Replace + runnerUpdate.YFilter = types.Replace suite.CRUD.Update(&suite.Provider, &runnerUpdate) entity := suite.CRUD.Read(&suite.Provider, &ysanity.Runner{}) @@ -59,10 +59,10 @@ func (suite *NETCONFOperationsTestSuite) TestCreate() { e2 := ysanity.Runner_OneList_Ldata{} e1.Number = 1 e1.Name = "foo" - e1.Filter = types.Create + e1.YFilter = types.Create e2.Number = 2 e2.Name = "bar" - e2.Filter = types.Create + e2.YFilter = types.Create runnerCreate.OneList.Ldata = append(runnerCreate.OneList.Ldata, e1) runnerCreate.OneList.Ldata = append(runnerCreate.OneList.Ldata, e2) @@ -96,10 +96,10 @@ func (suite *NETCONFOperationsTestSuite) TestDelete() { e2 := ysanity.Runner_OneList_Ldata{} e1.Number = 1 e1.Name = "foo" - e1.Filter = types.Create + e1.YFilter = types.Create e2.Number = 2 e2.Name = "bar" - e2.Filter = types.Create + e2.YFilter = types.Create runnerCreate.OneList.Ldata = append(runnerCreate.OneList.Ldata, e1) runnerCreate.OneList.Ldata = append(runnerCreate.OneList.Ldata, e2) suite.CRUD.Update(&suite.Provider, &runnerCreate) @@ -108,7 +108,7 @@ func (suite *NETCONFOperationsTestSuite) TestDelete() { runnerUpdate := ysanity.Runner{} eU1 := ysanity.Runner_OneList_Ldata{} eU1.Number = 1 - eU1.Filter = types.Delete + eU1.YFilter = types.Delete runnerUpdate.OneList.Ldata = append(runnerUpdate.OneList.Ldata, eU1) suite.CRUD.Update(&suite.Provider, &runnerUpdate) fmt.Println("TestDelete finished Update") @@ -138,11 +138,11 @@ func (suite *NETCONFOperationsTestSuite) TestDelete() { func (suite *NETCONFOperationsTestSuite) TestRemove() { runnerCreate := ysanity.Runner{} runnerCreate.Ytypes.BuiltInT.Number8 = 25 - runnerCreate.Filter = types.Merge + runnerCreate.YFilter = types.Merge suite.CRUD.Update(&suite.Provider, &runnerCreate) runnerUpdate := ysanity.Runner{} - runnerUpdate.Filter = types.Remove + runnerUpdate.YFilter = types.Remove suite.CRUD.Update(&suite.Provider, &runnerUpdate) // remove again without any error @@ -156,7 +156,7 @@ func (suite *NETCONFOperationsTestSuite) TestMerge() { runnerUpdate := ysanity.Runner{} runnerUpdate.Ytypes.BuiltInT.Number8 = 32 - runnerUpdate.Filter = types.Merge + runnerUpdate.YFilter = types.Merge suite.CRUD.Update(&suite.Provider, &runnerUpdate) entity := suite.CRUD.Read(&suite.Provider, &ysanity.Runner{}) From bd8994b48f99bacc51df81ef648c8043b63fad8f Mon Sep 17 00:00:00 2001 From: lily Date: Wed, 18 Oct 2017 14:06:28 -0700 Subject: [PATCH 10/10] change YLogInfo to YLogDebug --- sdk/go/core/ydk/path/path.go | 38 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/sdk/go/core/ydk/path/path.go b/sdk/go/core/ydk/path/path.go index 452b410f1..85ca07719 100644 --- a/sdk/go/core/ydk/path/path.go +++ b/sdk/go/core/ydk/path/path.go @@ -140,12 +140,12 @@ func ExecuteRpcEntity(provider types.ServiceProvider, rpcEntity, topEntity types } func walkRpcChildren(state *types.State, rpcEntity types.Entity, rpcInput C.DataNode, path string) { - ydk.YLogInfo("Walking Rpc Children...") + ydk.YLogDebug("Walking Rpc Children...") if(rpcEntity != nil) { children := rpcEntity.GetChildren() entityPath := rpcEntity.GetEntityPath(rpcEntity.GetParent()) - ydk.YLogInfo(fmt.Sprintf("Got %d entity children in '%s'", len(children), entityPath.Path)) - ydk.YLogInfo(fmt.Sprintf("Got %d leafs in '%s'", len(entityPath.ValuePaths), entityPath.Path)) + ydk.YLogDebug(fmt.Sprintf("Got %d entity children in '%s'", len(children), entityPath.Path)) + ydk.YLogDebug(fmt.Sprintf("Got %d leafs in '%s'", len(entityPath.ValuePaths), entityPath.Path)) if (path != "") { path = fmt.Sprintf("%s/", path) @@ -156,11 +156,11 @@ func walkRpcChildren(state *types.State, rpcEntity types.Entity, rpcInput C.Data } if (path != "") { - ydk.YLogInfo(fmt.Sprintf("Path: %s", path)) + ydk.YLogDebug(fmt.Sprintf("Path: %s", path)) } for childName, _ := range children { - ydk.YLogInfo(fmt.Sprintf("Looking at entity child '%s'", children[childName].GetSegmentPath())) + ydk.YLogDebug(fmt.Sprintf("Looking at entity child '%s'", children[childName].GetSegmentPath())) walkRpcChildren(state, children[childName], rpcInput, path) } @@ -176,7 +176,7 @@ func walkRpcChildren(state *types.State, rpcEntity types.Entity, rpcInput C.Data func createFromEntityPath(state *types.State, rpcEntity types.Entity, rpcInput C.DataNode, path string) { entityPath := rpcEntity.GetEntityPath(rpcEntity.GetParent()) for _, nameValue := range entityPath.ValuePaths { - ydk.YLogInfo(fmt.Sprintf("Creating leaf '%s' with value '%s' in '%s'", + ydk.YLogDebug(fmt.Sprintf("Creating leaf '%s' with value '%s' in '%s'", nameValue.Name, nameValue.Data.Value, entityPath.Path)) tempPath := "" @@ -191,7 +191,7 @@ func createFromEntityPath(state *types.State, rpcEntity types.Entity, rpcInput C func createFromChildren(state *types.State, children map[string]types.Entity, rpcInput C.DataNode) { for childName, child := range children { if (len(child.GetChildren()) == 0) { - ydk.YLogInfo(fmt.Sprintf("Creating child '%s' : %s", + ydk.YLogDebug(fmt.Sprintf("Creating child '%s' : %s", childName, child.GetEntityPath(child.GetParent()).Path)) C.DataNodeCreate(*getCState(state), rpcInput, C.CString(childName), C.CString("")) } @@ -214,7 +214,7 @@ func ReadDatanode(filter types.Entity, readDataNode types.DataNode) types.Entity } topEntity := getTopEntityFromFilter(filter) - ydk.YLogInfo(fmt.Sprintf("Reading top entity: '%s'", topEntity.GetSegmentPath())) + ydk.YLogDebug(fmt.Sprintf("Reading top entity: '%s'", topEntity.GetSegmentPath())) cchildren := C.DataNodeGetChildren(readDataNode.Private.(C.DataNode)) @@ -323,11 +323,11 @@ func InitCodecServiceProvider(state *types.State, entity types.Entity, repo type defer C.free(unsafe.Pointer(repoPath)) if len(repo.Path) > 0 { - ydk.YLogInfo(fmt.Sprintf("CodecServiceProvider using YANG models in %v", repo.Path)) + ydk.YLogDebug(fmt.Sprintf("CodecServiceProvider using YANG models in %v", repo.Path)) repoPath = C.CString(repo.Path) } else { yangPath := entity.GetBundleYangModelsLocation() - ydk.YLogInfo(fmt.Sprintf("CodecServiceProvider using YANG models in %v", yangPath)) + ydk.YLogDebug(fmt.Sprintf("CodecServiceProvider using YANG models in %v", yangPath)) repoPath = C.CString(yangPath) } @@ -508,17 +508,17 @@ func getDataNodeFromEntity(state *types.State, entity types.Entity, rootSchema C func walkChildren(state *types.State, entity types.Entity, dataNode C.DataNode) { children := entity.GetChildren() - ydk.YLogInfo(fmt.Sprintf("Got %d entity children", len(children))) + ydk.YLogDebug(fmt.Sprintf("Got %d entity children", len(children))) for childName := range children { - ydk.YLogInfo(fmt.Sprintf("Looking at entity child '%s'", children[childName].GetSegmentPath())) + ydk.YLogDebug(fmt.Sprintf("Looking at entity child '%s'", children[childName].GetSegmentPath())) if children[childName].HasDataOrFilter() { populateDataNode(state, children[childName], dataNode) } } - ydk.YLogInfo("") + ydk.YLogDebug("") } func populateDataNode(state *types.State, entity types.Entity, parentDataNode C.DataNode) { @@ -546,7 +546,7 @@ func populateNameValues(state *types.State, dataNode C.DataNode, path types.Enti var result C.DataNode leafData := nameValue.Data p := C.CString(nameValue.Name) - ydk.YLogInfo(fmt.Sprintf("got leaf {%s: %s}", nameValue.Name, nameValue.Data.Value)) + ydk.YLogDebug(fmt.Sprintf("got leaf {%s: %s}", nameValue.Name, nameValue.Data.Value)) if leafData.IsSet { p1 := C.CString(leafData.Value) @@ -570,26 +570,26 @@ func getEntityFromDataNode(node C.DataNode, entity types.Entity) { cchildren := C.DataNodeGetChildren(node) children := (*[1 << 30]C.DataNode)(unsafe.Pointer(cchildren.datanodes))[:cchildren.count:cchildren.count] - ydk.YLogInfo(fmt.Sprintf("Got %d datanode children", cchildren.count)) + ydk.YLogDebug(fmt.Sprintf("Got %d datanode children", cchildren.count)) for _, childDataNode := range children { childName := C.GoString(C.DataNodeGetArgument(childDataNode)) - ydk.YLogInfo(fmt.Sprintf("Looking at child datanode: '%s'", childName)) + ydk.YLogDebug(fmt.Sprintf("Looking at child datanode: '%s'", childName)) if dataNodeIsLeaf(childDataNode) { value := C.GoString(C.DataNodeGetValue(childDataNode)) - ydk.YLogInfo(fmt.Sprintf("Creating leaf '%s' with value '%s'", childName, value)) + ydk.YLogDebug(fmt.Sprintf("Creating leaf '%s' with value '%s'", childName, value)) entity.SetValue(childName, value) } else { var childEntity types.Entity if dataNodeIsList(childDataNode) { segmentPath := C.GoString(C.DataNodeGetSegmentPath(childDataNode)) - ydk.YLogInfo(fmt.Sprintf("Creating child list instance '%s'", segmentPath)) + ydk.YLogDebug(fmt.Sprintf("Creating child list instance '%s'", segmentPath)) childEntity = entity.GetChildByName(childName, segmentPath) } else { - ydk.YLogInfo(fmt.Sprintf("Creating child node '%s'", childName)) + ydk.YLogDebug(fmt.Sprintf("Creating child node '%s'", childName)) childEntity = entity.GetChildByName(childName, "") } if childEntity == nil {