diff --git a/build/ci/.test.yml b/build/ci/.test.yml
index 225356ea6656130a0737e4b8b4a7b3ee39bcd5b2..dd4f07a0a70490c2ce539a91081ad3c196d73f3e 100644
--- a/build/ci/.test.yml
+++ b/build/ci/.test.yml
@@ -27,22 +27,23 @@ integration-test:
   allow_failure: true
   variables:
     GOSDN_LOG: "nolog"
+    GOSDN_CHANGE_TIMEOUT: "100ms"
   rules:
     - if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
     - if: $CI_NIGHTLY
     - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
     - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
       allow_failure: true
-  after_script:
-    - go tool cover -func=coverage.out
 
 unit-test:
   script:
     - go test -short -race $(go list ./... | grep -v /forks/ | grep -v /api/ | grep -v /mocks ) -v -coverprofile=coverage.out
+  after_script:
+    - go tool cover -func=coverage.out
   <<: *test
 
-http-api-test:
+controller-test:
   script:
     - cd ./nucleus
-    - go test -race -v -run Test_httpApi -coverprofile=coverage.out
+    - go test -race -v -run TestRun
   <<: *test
\ No newline at end of file
diff --git a/cli/http.go b/cli/http.go
index 746c4a45146a882d827ef4b58526a5e06e4ef9a3..a90be457ba4e72d9c1a9005fb81c6b9860410039 100644
--- a/cli/http.go
+++ b/cli/http.go
@@ -58,6 +58,8 @@ func HTTPGet(apiEndpoint, f string, args ...string) error {
 		uuid := string(bytes[19:55])
 		viper.Set("LAST_DEVICE_UUID", uuid)
 		fmt.Println(string(bytes))
+	case http.StatusAccepted:
+
 	default:
 		log.WithFields(log.Fields{
 			"status code": resp.StatusCode,
diff --git a/cli/set.go b/cli/set.go
index 4d01d1477fd281446c3666faaf69e9a9899f7347..c5499d6f3a085db76d03fcef3227645662e829fc 100644
--- a/cli/set.go
+++ b/cli/set.go
@@ -3,10 +3,7 @@ package cli
 import (
 	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
 	"code.fbi.h-da.de/cocsn/gosdn/nucleus"
-	"code.fbi.h-da.de/cocsn/gosdn/nucleus/util/proto"
 	"context"
-	pb "google.golang.org/protobuf/proto"
-	"os"
 )
 
 // Set sends a gNMI Set request to the specified target. Only one
@@ -23,28 +20,5 @@ func Set(a, u, p, typ string, args ...string) error {
 	if err != nil {
 		return err
 	}
-
-	path := gnmi.SplitPath(args[0])
-	req := []interface{}{
-		&gnmi.Operation{
-			Type:   typ,
-			Origin: "",
-			Target: "",
-			Path:   path,
-			Val:    args[1],
-		},
-	}
-
-	resp, err := t.Set(context.Background(), req...)
-	if err != nil {
-		return err
-	}
-
-	_, tap := os.LookupEnv("GOSDN_TAP")
-	if tap {
-		if err := proto.Write(resp.(pb.Message), "resp-set-system-config-hostname"); err != nil {
-			return err
-		}
-	}
-	return nil
+	return t.Set(context.Background(), args)
 }
diff --git a/cmd/change.go b/cmd/change.go
new file mode 100644
index 0000000000000000000000000000000000000000..fc10bdb4fb746317c2450b4548cfae680115769f
--- /dev/null
+++ b/cmd/change.go
@@ -0,0 +1,49 @@
+/*
+Copyright © 2021 da/net research group <danet.fbi.h-da.de>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package cmd
+
+import (
+	"github.com/spf13/cobra"
+)
+
+// changeCmd represents the change command
+var changeCmd = &cobra.Command{
+	Use:   "change",
+	Short: "manage changes of the specified pnd",
+	Long: `use "change list" or "change list-pending" to list changes
+
+use "change commit" or "change confirm" respectively`,
+}
+
+func init() {
+	cliCmd.AddCommand(changeCmd)
+}
diff --git a/cmd/cliSet.go b/cmd/cliSet.go
index 9a79c630bed30d80c0d8438224edc42f084ff14d..e3f3a0743fdea2fa9c5c2ebd5686ef2e6675dc6b 100644
--- a/cmd/cliSet.go
+++ b/cmd/cliSet.go
@@ -41,12 +41,14 @@ var cliSetCmd = &cobra.Command{
 	Use:   "set",
 	Args:  cobra.ExactArgs(2),
 	Short: "set a value on a device",
-	Long: `Set a path value for a given device. Only one path and
-only one value supported for now`,
+	Long: `Update a path value for a given device. Only one path and
+only one value supported for now.
+
+Use "set replace" or "set delete" respectively`,
 	RunE: func(cmd *cobra.Command, args []string) error {
 		return cli.HTTPGet(
 			apiEndpoint,
-			"set",
+			"update",
 			"uuid="+uuid,
 			"cliSbi="+cliSbi,
 			"cliPnd="+cliPnd,
@@ -60,5 +62,5 @@ only one value supported for now`,
 func init() {
 	cliCmd.AddCommand(cliSetCmd)
 
-	cliSetCmd.Flags().StringVar(&uuid, "uuid", "", "uuid of the requested device")
+	cliSetCmd.PersistentFlags().StringVar(&uuid, "uuid", "", "uuid of the target device")
 }
diff --git a/cmd/commit.go b/cmd/commit.go
new file mode 100644
index 0000000000000000000000000000000000000000..a6ccb3b109b3c7f6afc4d7303c7c8ca88b196989
--- /dev/null
+++ b/cmd/commit.go
@@ -0,0 +1,57 @@
+/*
+Copyright © 2021 da/net research group <danet.fbi.h-da.de>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package cmd
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cli"
+	"github.com/spf13/cobra"
+)
+
+// commitCmd represents the commit command
+var commitCmd = &cobra.Command{
+	Use:   "commit",
+	Args:  cobra.ExactArgs(1),
+	Short: "Commit the given change for the active PND",
+	Long:  ``,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.HTTPGet(
+			apiEndpoint,
+			"change-commit",
+			"pnd="+cliPnd,
+			"cuid="+args[0],
+		)
+	},
+}
+
+func init() {
+	changeCmd.AddCommand(commitCmd)
+}
diff --git a/cmd/confirm.go b/cmd/confirm.go
new file mode 100644
index 0000000000000000000000000000000000000000..59cda76985aac03a9149da41a4e08f9545d0ac77
--- /dev/null
+++ b/cmd/confirm.go
@@ -0,0 +1,57 @@
+/*
+Copyright © 2021 da/net research group <danet.fbi.h-da.de>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package cmd
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cli"
+	"github.com/spf13/cobra"
+)
+
+// confirmCmd represents the confirm command
+var confirmCmd = &cobra.Command{
+	Use:   "confirm",
+	Args:  cobra.ExactArgs(1),
+	Short: "Confirms the given change for the active PND",
+	Long:  ``,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.HTTPGet(
+			apiEndpoint,
+			"change-confirm",
+			"pnd="+cliPnd,
+			"cuid="+args[0],
+		)
+	},
+}
+
+func init() {
+	changeCmd.AddCommand(confirmCmd)
+}
diff --git a/cmd/delete.go b/cmd/delete.go
new file mode 100644
index 0000000000000000000000000000000000000000..3c4e4e7603c32be00c4bba428bd22b09cd735eea
--- /dev/null
+++ b/cmd/delete.go
@@ -0,0 +1,71 @@
+/*
+Copyright © 2021 da/net research group <danet.fbi.h-da.de>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package cmd
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cli"
+	"github.com/spf13/cobra"
+)
+
+// deleteCmd represents the delete command
+var deleteCmd = &cobra.Command{
+	Use:   "delete",
+	Args:  cobra.ExactArgs(1),
+	Short: "set a value on a device",
+	Long: `Set a path value for a given device. Only one path and
+only one value supported for now`,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.HTTPGet(
+			apiEndpoint,
+			"delete",
+			"uuid="+uuid,
+			"cliSbi="+cliSbi,
+			"cliPnd="+cliPnd,
+			"path="+args[0],
+			"address="+address,
+		)
+	},
+}
+
+func init() {
+	cliSetCmd.AddCommand(deleteCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// deleteCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	// deleteCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/list.go b/cmd/list.go
new file mode 100644
index 0000000000000000000000000000000000000000..198662268afafa640e5c73749c0f64899874188b
--- /dev/null
+++ b/cmd/list.go
@@ -0,0 +1,55 @@
+/*
+Copyright © 2021 da/net research group <danet.fbi.h-da.de>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package cmd
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cli"
+	"github.com/spf13/cobra"
+)
+
+// listCmd represents the list command
+var listCmd = &cobra.Command{
+	Use:   "list",
+	Short: "Lists all committed changes",
+	Long:  ``,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.HTTPGet(
+			apiEndpoint,
+			"change-list",
+			"pnd="+cliPnd,
+		)
+	},
+}
+
+func init() {
+	changeCmd.AddCommand(listCmd)
+}
diff --git a/cmd/listPending.go b/cmd/listPending.go
new file mode 100644
index 0000000000000000000000000000000000000000..c7893d97bfe5e891c0ca90c9df4b44856b39f045
--- /dev/null
+++ b/cmd/listPending.go
@@ -0,0 +1,55 @@
+/*
+Copyright © 2021 da/net research group <danet.fbi.h-da.de>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package cmd
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cli"
+	"github.com/spf13/cobra"
+)
+
+// listPendingCmd represents the listPending command
+var listPendingCmd = &cobra.Command{
+	Use:   "listPending",
+	Short: "Lists all committed changes",
+	Long:  ``,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.HTTPGet(
+			apiEndpoint,
+			"change-list-pending",
+			"pnd="+cliPnd,
+		)
+	},
+}
+
+func init() {
+	changeCmd.AddCommand(listPendingCmd)
+}
diff --git a/cmd/replace.go b/cmd/replace.go
new file mode 100644
index 0000000000000000000000000000000000000000..33529c6d0e647aa9494b0dec9eee4ea2b2253818
--- /dev/null
+++ b/cmd/replace.go
@@ -0,0 +1,62 @@
+/*
+Copyright © 2021 da/net research group <danet.fbi.h-da.de>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package cmd
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cli"
+	"github.com/spf13/cobra"
+)
+
+// replaceCmd represents the replace command
+var replaceCmd = &cobra.Command{
+	Use:   "replace",
+	Args:  cobra.ExactArgs(2),
+	Short: "set a value on a device",
+	Long: `Set a path value for a given device. Only one path and
+only one value supported for now`,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.HTTPGet(
+			apiEndpoint,
+			"replace",
+			"uuid="+uuid,
+			"cliSbi="+cliSbi,
+			"cliPnd="+cliPnd,
+			"path="+args[0],
+			"address="+address,
+			"value="+args[1],
+		)
+	},
+}
+
+func init() {
+	cliSetCmd.AddCommand(replaceCmd)
+}
diff --git a/cmd/update.go b/cmd/update.go
new file mode 100644
index 0000000000000000000000000000000000000000..93db8e374adf4553675bd14db98c29b09ee88052
--- /dev/null
+++ b/cmd/update.go
@@ -0,0 +1,62 @@
+/*
+Copyright © 2021 da/net research group <danet.fbi.h-da.de>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package cmd
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cli"
+	"github.com/spf13/cobra"
+)
+
+// updateCmd represents the update command
+var updateCmd = &cobra.Command{
+	Use:   "update",
+	Args:  cobra.ExactArgs(2),
+	Short: "update a value on a device",
+	Long: `Update a path value for a given device. Only one path and
+only one value supported for now`,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.HTTPGet(
+			apiEndpoint,
+			"update",
+			"uuid="+uuid,
+			"cliSbi="+cliSbi,
+			"cliPnd="+cliPnd,
+			"path="+args[0],
+			"address="+address,
+			"value="+args[1],
+		)
+	},
+}
+
+func init() {
+	cliSetCmd.AddCommand(updateCmd)
+}
diff --git a/forks/goarista/gnmi/client.go b/forks/goarista/gnmi/client.go
index fc041336eb078e224f739bbad9f93dd2767c10fb..c4512f2c8f6a3ef34b405ccfe81a33fcfcd57f72 100644
--- a/forks/goarista/gnmi/client.go
+++ b/forks/goarista/gnmi/client.go
@@ -118,7 +118,7 @@ func DialContext(ctx context.Context, cfg *Config) (pb.GNMIClient, error) {
 
 	if cfg.TLS || cfg.CAFile != "" || cfg.CertFile != "" || cfg.Token != "" {
 		tlsConfig := &tls.Config{
-			MinVersion:                  tls.VersionTLS12,
+			MinVersion: tls.VersionTLS12,
 		}
 		if cfg.CAFile != "" {
 			b, err := ioutil.ReadFile(cfg.CAFile)
diff --git a/go.mod b/go.mod
index 9822234c73e01a5119746554b44198af1da233b9..c3595c3e3c9bf7cfe659b8fa65dff53fcf79a714 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module code.fbi.h-da.de/cocsn/gosdn
 go 1.14
 
 require (
-	code.fbi.h-da.de/cocsn/yang-models v0.0.4
+	code.fbi.h-da.de/cocsn/yang-models v0.0.6
 	github.com/aristanetworks/goarista v0.0.0-20201120222254-94a892eb0c6a
 	github.com/golang/protobuf v1.5.0
 	github.com/google/gnxi v0.0.0-20201221102247-c26672548161
@@ -11,8 +11,8 @@ require (
 	github.com/neo4j/neo4j-go-driver v1.8.3
 	github.com/openconfig/gnmi v0.0.0-20200617225440-d2b4e6a45802
 	github.com/openconfig/goyang v0.2.3
-	github.com/openconfig/ygot v0.10.0
-	github.com/sirupsen/logrus v1.7.0
+	github.com/openconfig/ygot v0.10.4
+	github.com/sirupsen/logrus v1.8.0
 	github.com/spf13/cobra v1.1.1
 	github.com/spf13/viper v1.7.1
 	github.com/stretchr/testify v1.6.1
diff --git a/go.sum b/go.sum
index df1bca3a02416ecdb2b8129aa30f24d7ceea3832..dfc84d46a711f66bbcaac6e485f4bdbc96f34d2b 100644
--- a/go.sum
+++ b/go.sum
@@ -21,8 +21,10 @@ cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIA
 cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
 cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
 cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
-code.fbi.h-da.de/cocsn/yang-models v0.0.4 h1:y/Ph5CaD2NJDPjoOuS59iKrMYf9bvpg2/hefC2RG6E4=
-code.fbi.h-da.de/cocsn/yang-models v0.0.4/go.mod h1:7MnNmAQ9o84BpUepcaV6RB1mBGCNyXVJcdbKUl6rK0g=
+code.fbi.h-da.de/cocsn/gosdn v0.0.1/go.mod h1:LK5EZWj/QPi+ueMptEB2MigvnS03Lky7p4UHoA+M7Ao=
+code.fbi.h-da.de/cocsn/swagger/apis v0.0.0-20200924152423-61030cab7b88/go.mod h1:3jDZAOmepPl3kiukNGvPFkJEzgGczgrC3zJ2jcqVFSs=
+code.fbi.h-da.de/cocsn/yang-models v0.0.6 h1:dqpxs/rx5shpQncmC4/Z97fkwRkRgoWBevzAPw2PYfo=
+code.fbi.h-da.de/cocsn/yang-models v0.0.6/go.mod h1:VnKJrYR/CJrLhGfxFcZU2rpMQ6hosFC4q77/CJxpy+M=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
@@ -35,17 +37,21 @@ github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ
 github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
 github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
 github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
 github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/Shopify/sarama v1.26.1/go.mod h1:NbSGBSSndYaIhRcBtY9V0U7AyH+x71bG668AuWys/yU=
 github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
+github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
 github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
 github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
 github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks=
@@ -56,7 +62,10 @@ github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
+github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
+github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
@@ -87,6 +96,7 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8
 github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
 github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
+github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
@@ -112,8 +122,12 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
 github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
+github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
+github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM=
 github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
+github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -124,14 +138,88 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
 github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
 github.com/go-logr/logr v0.2.0 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY=
 github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
+github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
+github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
+github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
+github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
+github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
+github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU=
+github.com/go-openapi/analysis v0.19.10/go.mod h1:qmhS3VNFxBlquFJ0RGoDtylO9y4pgTAUNE9AEEMdlJQ=
+github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
+github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
+github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
+github.com/go-openapi/errors v0.19.3/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
+github.com/go-openapi/errors v0.19.6/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
+github.com/go-openapi/errors v0.19.7/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
+github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
+github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
 github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
 github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
+github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
 github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
 github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
+github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
+github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
+github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
+github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs=
+github.com/go-openapi/loads v0.19.3/go.mod h1:YVfqhUCdahYwR3f3iiwQLhicVRvLlU/WO5WPaZvcvSI=
+github.com/go-openapi/loads v0.19.5/go.mod h1:dswLCAdonkRufe/gSUC3gN8nTSaB9uaS2es0x5/IbjY=
+github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
+github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64=
+github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=
+github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo=
+github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98=
+github.com/go-openapi/runtime v0.19.22/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk=
+github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
+github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
+github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
 github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
+github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
+github.com/go-openapi/spec v0.19.8/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
+github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
+github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
+github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
+github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
+github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
+github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk=
+github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk=
+github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
+github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
 github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
 github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
+github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
+github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
+github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
+github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
+github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo=
+github.com/go-openapi/validate v0.19.10/go.mod h1:RKEZTUWDkxKQxN2jDT7ZnZi2bhZlbNMAuKvKB+IaGx8=
+github.com/go-openapi/validate v0.19.11/go.mod h1:Rzou8hA/CBw8donlS6WNEUQupNvUZ0waH08tGe6kAQ4=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
+github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
+github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
+github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
+github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
+github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
+github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
+github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
+github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
+github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
+github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo=
+github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk=
+github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
+github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
+github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg=
+github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE=
+github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
+github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
+github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
+github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
+github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
+github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
+github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
+github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
 github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
@@ -190,6 +278,7 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
 github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
 github.com/google/protobuf v3.11.4+incompatible/go.mod h1:lUQ9D1ePzbH2PrIS7ob/bjm9HXyH5WHB0Akwh7URreM=
 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -237,6 +326,7 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
 github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
+github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -247,10 +337,13 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
 github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
+github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
 github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
 github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
 github.com/klauspost/compress v1.10.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
 github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
@@ -261,6 +354,7 @@ github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQ
 github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
 github.com/klauspost/reedsolomon v1.9.3/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -272,13 +366,25 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
+github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
+github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
+github.com/magefile/mage v1.10.0 h1:3HiXzCUY12kh9bIuyXShaVe529fJfyqoVM42o/uom2g=
+github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
 github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY=
 github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
+github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
+github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
+github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
 github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
+github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc=
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
@@ -290,6 +396,7 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
 github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
 github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/moby/moby v1.13.1/go.mod h1:fDXVQ6+S340veQPv35CzDahGBmHsiclFwfEygB/TWMc=
@@ -299,6 +406,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
 github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
@@ -333,10 +441,14 @@ github.com/openconfig/ygot v0.6.0/go.mod h1:o30svNf7O0xK+R35tlx95odkDmZWS9JyWWQS
 github.com/openconfig/ygot v0.9.0/go.mod h1:oCQNdXnv7dWc8scTDgoFkauv1wwplJn5HspHcjlxSAQ=
 github.com/openconfig/ygot v0.10.0 h1:EmgwLXbFiCBmEUlSI4/1fPuRzgf4EsD0sThmAmRqbYM=
 github.com/openconfig/ygot v0.10.0/go.mod h1:oCQNdXnv7dWc8scTDgoFkauv1wwplJn5HspHcjlxSAQ=
+github.com/openconfig/ygot v0.10.4 h1:7rfvHEWFBYxFeVVK9UbMq6BJMAD7zeedidEUuxhcfaU=
+github.com/openconfig/ygot v0.10.4/go.mod h1:oCQNdXnv7dWc8scTDgoFkauv1wwplJn5HspHcjlxSAQ=
 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
+github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
 github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
 github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
 github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
@@ -369,18 +481,24 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
 github.com/prometheus/procfs v0.0.10/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
+github.com/rivo/tview v0.0.0-20200915114512-42866ecf6ca6/go.mod h1:xV4Aw4WIX8cmhg71U7MUHBdpIQ7zSEXdRruGHLaEAOc=
+github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
+github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
-github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.8.0 h1:nfhvjKcUMhBMVqbKHJlk5RPrrfYr/NMo3692g0dwfWU=
+github.com/sirupsen/logrus v1.8.0/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
 github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
@@ -395,6 +513,7 @@ github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
 github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
 github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
@@ -421,18 +540,25 @@ github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
 github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
+github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
 github.com/tjfoc/gmsm v1.3.0/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
 github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
 github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
+github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
 github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
+github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
 github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
 github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
 github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
+go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
+go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
+go.mongodb.org/mongo-driver v1.3.4/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@@ -443,9 +569,13 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -487,6 +617,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -494,6 +625,7 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r
 golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -510,6 +642,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
 golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201216054612-986b41b23924 h1:QsnDpLLOKwHBBDa8nDws4DYNc/ryVW2vCpxCs09d4PY=
 golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@@ -523,6 +657,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -534,13 +669,18 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -558,6 +698,7 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -580,16 +721,22 @@ golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGm
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -684,6 +831,7 @@ gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPA
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
 gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
@@ -712,6 +860,7 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/mocks/PrincipalNetworkDomain.go b/mocks/PrincipalNetworkDomain.go
index 38233e76794d9913cf722aa848b2409fe4e1e499..6c795cb7388b80a8446f5c2c8314ed98fa3eba5f 100644
--- a/mocks/PrincipalNetworkDomain.go
+++ b/mocks/PrincipalNetworkDomain.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.6.0. DO NOT EDIT.
+// Code generated by mockery 2.7.4. DO NOT EDIT.
 
 package mocks
 
@@ -6,6 +6,8 @@ import (
 	mock "github.com/stretchr/testify/mock"
 
 	uuid "github.com/google/uuid"
+
+	ygot "github.com/openconfig/ygot/ygot"
 )
 
 // PrincipalNetworkDomain is an autogenerated mock type for the PrincipalNetworkDomain type
@@ -41,6 +43,71 @@ func (_m *PrincipalNetworkDomain) AddSbi(_a0 interface{}) error {
 	return r0
 }
 
+// ChangeOND provides a mock function with given fields: _a0, operation, path, value
+func (_m *PrincipalNetworkDomain) ChangeOND(_a0 uuid.UUID, operation interface{}, path string, value ...string) error {
+	_va := make([]interface{}, len(value))
+	for _i := range value {
+		_va[_i] = value[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, _a0, operation, path)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(uuid.UUID, interface{}, string, ...string) error); ok {
+		r0 = rf(_a0, operation, path, value...)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// Commit provides a mock function with given fields: _a0
+func (_m *PrincipalNetworkDomain) Commit(_a0 uuid.UUID) error {
+	ret := _m.Called(_a0)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(uuid.UUID) error); ok {
+		r0 = rf(_a0)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// Committed provides a mock function with given fields:
+func (_m *PrincipalNetworkDomain) Committed() []uuid.UUID {
+	ret := _m.Called()
+
+	var r0 []uuid.UUID
+	if rf, ok := ret.Get(0).(func() []uuid.UUID); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).([]uuid.UUID)
+		}
+	}
+
+	return r0
+}
+
+// Confirm provides a mock function with given fields: _a0
+func (_m *PrincipalNetworkDomain) Confirm(_a0 uuid.UUID) error {
+	ret := _m.Called(_a0)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(uuid.UUID) error); ok {
+		r0 = rf(_a0)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
 // ContainsDevice provides a mock function with given fields: _a0
 func (_m *PrincipalNetworkDomain) ContainsDevice(_a0 uuid.UUID) bool {
 	ret := _m.Called(_a0)
@@ -69,6 +136,22 @@ func (_m *PrincipalNetworkDomain) Destroy() error {
 	return r0
 }
 
+// Devices provides a mock function with given fields:
+func (_m *PrincipalNetworkDomain) Devices() []uuid.UUID {
+	ret := _m.Called()
+
+	var r0 []uuid.UUID
+	if rf, ok := ret.Get(0).(func() []uuid.UUID); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).([]uuid.UUID)
+		}
+	}
+
+	return r0
+}
+
 // GetDescription provides a mock function with given fields:
 func (_m *PrincipalNetworkDomain) GetDescription() string {
 	ret := _m.Called()
@@ -83,6 +166,29 @@ func (_m *PrincipalNetworkDomain) GetDescription() string {
 	return r0
 }
 
+// GetDevice provides a mock function with given fields: _a0
+func (_m *PrincipalNetworkDomain) GetDevice(_a0 uuid.UUID) (ygot.GoStruct, error) {
+	ret := _m.Called(_a0)
+
+	var r0 ygot.GoStruct
+	if rf, ok := ret.Get(0).(func(uuid.UUID) ygot.GoStruct); ok {
+		r0 = rf(_a0)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(ygot.GoStruct)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(uuid.UUID) error); ok {
+		r1 = rf(_a0)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
 // GetName provides a mock function with given fields:
 func (_m *PrincipalNetworkDomain) GetName() string {
 	ret := _m.Called()
@@ -113,7 +219,7 @@ func (_m *PrincipalNetworkDomain) GetSBIs() interface{} {
 	return r0
 }
 
-// Id provides a mock function with given fields:
+// ID provides a mock function with given fields:
 func (_m *PrincipalNetworkDomain) ID() uuid.UUID {
 	ret := _m.Called()
 
@@ -150,6 +256,22 @@ func (_m *PrincipalNetworkDomain) MarshalDevice(_a0 uuid.UUID) (string, error) {
 	return r0, r1
 }
 
+// Pending provides a mock function with given fields:
+func (_m *PrincipalNetworkDomain) Pending() []uuid.UUID {
+	ret := _m.Called()
+
+	var r0 []uuid.UUID
+	if rf, ok := ret.Get(0).(func() []uuid.UUID); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).([]uuid.UUID)
+		}
+	}
+
+	return r0
+}
+
 // RemoveDevice provides a mock function with given fields: _a0
 func (_m *PrincipalNetworkDomain) RemoveDevice(_a0 uuid.UUID) error {
 	ret := _m.Called(_a0)
diff --git a/mocks/SouthboundInterface.go b/mocks/SouthboundInterface.go
index 6217f5a7674db004f64254bfe5d5c8348ac733a7..38ffb81ff021989bb8153c33169ce40ad8863a33 100644
--- a/mocks/SouthboundInterface.go
+++ b/mocks/SouthboundInterface.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.6.0. DO NOT EDIT.
+// Code generated by mockery 2.7.4. DO NOT EDIT.
 
 package mocks
 
@@ -18,7 +18,7 @@ type SouthboundInterface struct {
 	mock.Mock
 }
 
-// Id provides a mock function with given fields:
+// ID provides a mock function with given fields:
 func (_m *SouthboundInterface) ID() uuid.UUID {
 	ret := _m.Called()
 
diff --git a/mocks/Storable.go b/mocks/Storable.go
index 630f70145d05ec4878461e243d238fe59958a483..e55a23eb41a51d2715f2ee94dfbb9e7a285a0145 100644
--- a/mocks/Storable.go
+++ b/mocks/Storable.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.6.0. DO NOT EDIT.
+// Code generated by mockery 2.7.4. DO NOT EDIT.
 
 package mocks
 
@@ -13,7 +13,7 @@ type Storable struct {
 	mock.Mock
 }
 
-// Id provides a mock function with given fields:
+// ID provides a mock function with given fields:
 func (_m *Storable) ID() uuid.UUID {
 	ret := _m.Called()
 
diff --git a/mocks/Transport.go b/mocks/Transport.go
index 6dc256acae1ee730623be6ab1fd5508f9f4ed9f5..7d8531e57334fd330a698165132428273d618f39 100644
--- a/mocks/Transport.go
+++ b/mocks/Transport.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.6.0. DO NOT EDIT.
+// Code generated by mockery 2.7.4. DO NOT EDIT.
 
 package mocks
 
@@ -76,29 +76,20 @@ func (_m *Transport) ProcessResponse(resp interface{}, root interface{}, models
 }
 
 // Set provides a mock function with given fields: ctx, params
-func (_m *Transport) Set(ctx context.Context, params ...interface{}) (interface{}, error) {
+func (_m *Transport) Set(ctx context.Context, params ...interface{}) error {
 	var _ca []interface{}
 	_ca = append(_ca, ctx)
 	_ca = append(_ca, params...)
 	ret := _m.Called(_ca...)
 
-	var r0 interface{}
-	if rf, ok := ret.Get(0).(func(context.Context, ...interface{}) interface{}); ok {
+	var r0 error
+	if rf, ok := ret.Get(0).(func(context.Context, ...interface{}) error); ok {
 		r0 = rf(ctx, params...)
 	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(interface{})
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, ...interface{}) error); ok {
-		r1 = rf(ctx, params...)
-	} else {
-		r1 = ret.Error(1)
+		r0 = ret.Error(0)
 	}
 
-	return r0, r1
+	return r0
 }
 
 // Subscribe provides a mock function with given fields: ctx, params
diff --git a/mocks/TransportOptions.go b/mocks/TransportOptions.go
index 4893655f8a5bc0fef06e4898e116fc3df7171421..b969fdb60e490658017a191dfb2bae818408b83a 100644
--- a/mocks/TransportOptions.go
+++ b/mocks/TransportOptions.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.6.0. DO NOT EDIT.
+// Code generated by mockery 2.7.4. DO NOT EDIT.
 
 package mocks
 
diff --git a/nucleus/controller_test.go b/nucleus/controller_test.go
index 47fa1026ccc54a35ca3296ce0779fc58af856e9b..1dc5b8bd001270ace098c39a81e027263df7869c 100644
--- a/nucleus/controller_test.go
+++ b/nucleus/controller_test.go
@@ -9,6 +9,9 @@ import (
 )
 
 func TestRun(t *testing.T) {
+	if testing.Short() {
+		t.Skip("this test is executed separately")
+	}
 	type args struct {
 		request string
 	}
diff --git a/nucleus/errors.go b/nucleus/errors.go
index 8bd01fe67150cba93b9c6f2cb5710ae63383b11c..7466b3ec10d37bf51b5f5605643882c359664f74 100644
--- a/nucleus/errors.go
+++ b/nucleus/errors.go
@@ -90,3 +90,13 @@ type ErrInvalidTransportOptions struct {
 func (e ErrInvalidTransportOptions) Error() string {
 	return fmt.Sprintf("invalid transport options: %v", reflect.TypeOf(e.t))
 }
+
+// ErrOperationNotSupported implements the Error interface and is called if the
+// wrong Operation has been provided.
+type ErrOperationNotSupported struct {
+	o interface{}
+}
+
+func (e ErrOperationNotSupported) Error() string {
+	return fmt.Sprintf("transport operation not supported: %v", reflect.TypeOf(e.o))
+}
diff --git a/nucleus/gnmi_transport.go b/nucleus/gnmi_transport.go
index 3bbcc03c6146804d862af1932f5cac2a4a0fca86..870af9eaeb787c8cbf6cb7de90bf2d9ea40e4870 100644
--- a/nucleus/gnmi_transport.go
+++ b/nucleus/gnmi_transport.go
@@ -2,19 +2,21 @@ package nucleus
 
 import (
 	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
+	pathutils "code.fbi.h-da.de/cocsn/gosdn/nucleus/util/path"
 	"context"
 	gpb "github.com/openconfig/gnmi/proto/gnmi"
 	"github.com/openconfig/gnmi/proto/gnmi_ext"
 	"github.com/openconfig/goyang/pkg/yang"
+	"github.com/openconfig/ygot/ygot"
 	"github.com/openconfig/ygot/ytypes"
 	log "github.com/sirupsen/logrus"
 	"reflect"
-	"strings"
 )
 
 // CtxKeyType is a custom type to be used as key in a context.WithValue() or
 // context.Value() call. For more information see:
 // https://www.calhoun.io/pitfalls-of-context-values-and-how-to-avoid-or-mitigate-them/
+// TODO: Unexport to comply with best practice
 type CtxKeyType string
 
 const (
@@ -22,8 +24,16 @@ const (
 	CtxKeyOpts CtxKeyType = "opts"
 	// CtxKeyConfig is a context key for gnmi.Config
 	CtxKeyConfig = "config"
+	// CtxKeyOperation is a context key for a gNMI operation (update, replace, delete)
+	CtxKeyOperation = "op"
 )
 
+var opmap = map[Operation]string{
+	TransportUpdate:  "update",
+	TransportReplace: "replace",
+	TransportDelete:  "delete",
+}
+
 // Gnmi implements the Transport interface and provides an SBI with the
 // possibility to access a gNMI endpoint.
 type Gnmi struct {
@@ -75,22 +85,50 @@ func (g *Gnmi) Get(ctx context.Context, params ...string) (interface{}, error) {
 
 // Set takes a slice of params. This slice must contain at least one operation.
 // It can contain an additional arbitrary amount of operations and extensions.
-func (g *Gnmi) Set(ctx context.Context, args ...interface{}) (interface{}, error) {
+func (g *Gnmi) Set(ctx context.Context, args ...interface{}) error {
 	if g.client == nil {
-		return nil, &ErrNilClient{}
+		return &ErrNilClient{}
 	}
 	if len(args) == 0 {
-		return nil, &ErrInvalidParameters{
+		return &ErrInvalidParameters{
 			f: "gnmi.Set()",
 			r: "no parameters provided",
 		}
 	}
 
+	if len(args) == 2 {
+		switch args[0].(type) {
+		case ygot.GoStruct:
+			return g.applyDiff(ctx, args[0])
+		default:
+
+		}
+	}
+
+	opts := make([]interface{}, 0)
+	for _, o := range args {
+		attrs, ok := o.([]string)
+		if !ok {
+			return &ErrInvalidTypeAssertion{
+				v: o,
+				t: reflect.TypeOf("placeholder"),
+			}
+		}
+		opts = append(opts, &gnmi.Operation{
+			// Hardcoded TransportUpdate until multiple operations are supported
+			Type:   opmap[TransportUpdate],
+			Origin: "",
+			Target: "",
+			Path:   gnmi.SplitPath(attrs[0]),
+			Val:    attrs[1],
+		})
+	}
+
 	// Loop over args and create ops and exts
 	// Invalid args cause unhealable error
 	ops := make([]*gnmi.Operation, 0)
 	exts := make([]*gnmi_ext.Extension, 0)
-	for _, p := range args {
+	for _, p := range opts {
 		switch p.(type) {
 		case *gnmi.Operation:
 			op := p.(*gnmi.Operation)
@@ -101,19 +139,66 @@ func (g *Gnmi) Set(ctx context.Context, args ...interface{}) (interface{}, error
 		case *gnmi_ext.Extension:
 			exts = append(exts, p.(*gnmi_ext.Extension))
 		default:
-			return nil, &ErrInvalidParameters{
+			return &ErrInvalidParameters{
 				f: "gnmi.Set()",
 				r: "args contain invalid type",
 			}
 		}
 	}
 	if len(ops) == 0 {
-		return nil, &ErrInvalidParameters{
+		return &ErrInvalidParameters{
 			f: "gnmi.Set()",
 			r: "no operations provided",
 		}
 	}
-	return g.set(ctx, ops, exts...)
+	resp, err := g.set(ctx, ops, exts...)
+	if err != nil {
+		return err
+	}
+	log.Info(resp)
+	return nil
+}
+
+func (g *Gnmi) applyDiff(ctx context.Context, payload ...interface{}) error {
+	if len(payload) != 2 {
+		return &ErrInvalidParameters{}
+	}
+	op := ctx.Value(CtxKeyOperation)
+	oldstate, ok := payload[0].(ygot.GoStruct)
+	if !ok {
+		return &ErrInvalidTypeAssertion{
+			v: payload[0],
+			t: reflect.TypeOf("ygot.GoStruct"),
+		}
+	}
+	newstate, ok := payload[1].(ygot.GoStruct)
+	if !ok {
+		return &ErrInvalidTypeAssertion{
+			v: payload[1],
+			t: reflect.TypeOf("ygot.GoStruct"),
+		}
+	}
+
+	diff, err := ygot.Diff(oldstate, newstate)
+	if err != nil {
+		return err
+	}
+	req := &gpb.SetRequest{}
+	if diff.Update != nil {
+		switch op {
+		case TransportUpdate:
+			req.Update = diff.Update
+		case TransportReplace:
+			req.Replace = diff.Update
+		default:
+			return &ErrOperationNotSupported{}
+		}
+	} else if diff.Delete != nil {
+		req.Delete = diff.Delete
+	}
+	resp, err := g.client.Set(ctx, req)
+	log.Info(resp)
+	return err
 }
 
 //Subscribe subscribes to a gNMI target
@@ -141,7 +226,7 @@ func (g *Gnmi) ProcessResponse(resp interface{}, root interface{}, s *ytypes.Sch
 			val, ok := update.Val.Value.(*gpb.TypedValue_JsonIetfVal)
 			if ok {
 				opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}}
-				if err := g.Unmarshal(val.JsonIetfVal, extraxtPathElements(fullPath), root, opts...); err != nil {
+				if err := g.Unmarshal(val.JsonIetfVal, pathutils.ToStrings(fullPath), root, opts...); err != nil {
 					return err
 				}
 				return nil
@@ -157,14 +242,6 @@ func (g *Gnmi) ProcessResponse(resp interface{}, root interface{}, s *ytypes.Sch
 	return nil
 }
 
-func extraxtPathElements(path *gpb.Path) []string {
-	elems := make([]string, len(path.Elem))
-	for i, e := range path.Elem {
-		elems[i] = strings.Title(e.Name)
-	}
-	return elems
-}
-
 // Capabilities calls GNMI capabilities
 func (g *Gnmi) Capabilities(ctx context.Context) (interface{}, error) {
 	log.WithFields(log.Fields{
diff --git a/nucleus/gnmi_transport_test.go b/nucleus/gnmi_transport_test.go
index 38270c8da5fe3f31f030c5010de2b980a8d8d127..18627bd9349ab7d740a80bd5472c7eda045632bf 100644
--- a/nucleus/gnmi_transport_test.go
+++ b/nucleus/gnmi_transport_test.go
@@ -276,7 +276,6 @@ func TestGnmi_Set(t *testing.T) {
 		name    string
 		fields  fields
 		args    args
-		want    interface{}
 		wantErr bool
 	}{
 		{
@@ -285,20 +284,15 @@ func TestGnmi_Set(t *testing.T) {
 			args: args{
 				params: nil,
 			},
-			want:    nil,
 			wantErr: true,
 		},
 		// TODO: Positive test cases
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			got, err := tt.fields.transport.Set(context.Background(), tt.args.params...)
+			err := tt.fields.transport.Set(context.Background(), tt.args.params...)
 			if (err != nil) != tt.wantErr {
 				t.Errorf("Set() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("Set() got = %v, want %v", got, tt.want)
 			}
 		})
 	}
diff --git a/nucleus/http.go b/nucleus/http.go
index 56ad4cb0af707662e72656e1a7b6a4fa0a88f046..ee0590e4e5645ff665417c9be7ec3d6b1542d220 100644
--- a/nucleus/http.go
+++ b/nucleus/http.go
@@ -7,11 +7,18 @@ import (
 	"github.com/google/uuid"
 	gpb "github.com/openconfig/gnmi/proto/gnmi"
 	log "github.com/sirupsen/logrus"
+	"io"
 	"net/http"
 	"net/url"
 	"time"
 )
 
+var apiOpmap = map[string]Operation{
+	"update":  TransportUpdate,
+	"replace": TransportReplace,
+	"delete":  TransportDelete,
+}
+
 func stopHttpServer() error {
 	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
 	defer cancel()
@@ -61,7 +68,6 @@ func httpHandler(writer http.ResponseWriter, request *http.Request) {
 		return
 	}
 
-
 	id, err := uuid.Parse(query.Get("uuid"))
 	if err != nil {
 		if err.Error() != "invalid UUID length: 0" {
@@ -88,23 +94,18 @@ func httpHandler(writer http.ResponseWriter, request *http.Request) {
 	if query.Get("q") != "init" && query.Get("q") != "getIDs" {
 		pnd, err = c.pndc.get(pid)
 		if err != nil {
-			log.Error(err)
-			writer.WriteHeader(http.StatusInternalServerError)
+			handleServerError(writer, err)
 			return
 		}
 		sbic := pnd.GetSBIs()
 		sbi, err = sbic.(*sbiStore).get(sid)
 		if err != nil {
-			log.WithFields(log.Fields{
-				"requested uuid":  sid,
-				"available uuids": sbic.(*sbiStore).UUIDs(),
-			}).Error(err)
-			writer.WriteHeader(http.StatusInternalServerError)
+			handleServerError(writer, err)
 			return
 		}
 	}
 
-	switch query.Get("q") {
+	switch q := query.Get("q"); q {
 	case "addDevice":
 		d, err := NewDevice(sbi, &GnmiTransportOptions{
 			Config: gnmi.Config{
@@ -167,42 +168,75 @@ func httpHandler(writer http.ResponseWriter, request *http.Request) {
 		writer.Header().Set("Content-Type", "application/json")
 		fmt.Fprintf(writer, "%v", device)
 	case "getIDs":
-		writeIDs := func(typ string, ids []uuid.UUID) {
-			fmt.Fprintf(writer, "%v:\n", typ)
-			for i, id := range ids {
-				fmt.Fprintf(writer, "%v: %v\n", i+1, id)
-			}
-		}
+
 		pnds := c.pndc.UUIDs()
-		writeIDs("PNDs", pnds)
-		writeIDs("SBIs", c.sbic.UUIDs())
-		for _,id := range pnds{
+		writeIDs(writer, "PNDs", pnds)
+		writeIDs(writer, "SBIs", c.sbic.UUIDs())
+		for _, id := range pnds {
 			p, err := c.pndc.get(id)
 			if err != nil {
-				writer.WriteHeader(http.StatusInternalServerError)
-				log.Error(err)
+				handleServerError(writer, err)
 				return
 			}
-			writeIDs("Devices", p.(*pndImplementation).devices.UUIDs())
+			writeIDs(writer, "Devices", p.Devices())
 		}
 	case "init":
-		writeIDs := func(typ string, ids []uuid.UUID) {
-			for _, id := range ids {
-				fmt.Fprintf(writer, "%v", id)
-			}
+		writeIDs(writer, "PNDs", c.pndc.UUIDs())
+		writeIDs(writer, "SBIs", c.sbic.UUIDs())
+	case "update", "replace":
+		if err := pnd.ChangeOND(id, apiOpmap[q], query.Get("path"), query.Get("value")); err != nil {
+			handleServerError(writer, err)
+			return
 		}
-		writeIDs("PNDs", c.pndc.UUIDs())
-		writeIDs("SBIs", c.sbic.UUIDs())
-	case "set":
-		resp, err := pnd.(*pndImplementation).Set(id, query.Get("path"), query.Get("value"))
-		if err != nil {
-			writer.WriteHeader(http.StatusInternalServerError)
-			log.Error(err)
+		writer.WriteHeader(http.StatusOK)
+	case "delete":
+		if err := pnd.ChangeOND(id, TransportDelete, query.Get("path")); err != nil {
+			handleServerError(writer, err)
 			return
 		}
 		writer.WriteHeader(http.StatusOK)
-		fmt.Fprintln(writer, resp)
+	case "change-list":
+		changes := pnd.Committed()
+		writeIDs(writer, "Tentative changes", changes)
+	case "change-list-pending":
+		changes := pnd.Pending()
+		writeIDs(writer, "Pending changes", changes)
+	case "change-commit":
+		cuid, err := uuid.Parse(query.Get("cuid"))
+		if err != nil {
+			handleServerError(writer, err)
+			return
+		}
+		if err := pnd.Commit(cuid); err != nil {
+			handleServerError(writer, err)
+			return
+		}
+		writer.WriteHeader(http.StatusAccepted)
+	case "change-confirm":
+		cuid, err := uuid.Parse(query.Get("cuid"))
+		if err != nil {
+			handleServerError(writer, err)
+			return
+		}
+		if err := pnd.Confirm(cuid); err != nil {
+			handleServerError(writer, err)
+			return
+		}
+		writer.WriteHeader(http.StatusAccepted)
 	default:
 		writer.WriteHeader(http.StatusBadRequest)
 	}
 }
+
+func writeIDs(w io.Writer, typ string, ids []uuid.UUID) {
+	fmt.Fprintf(w, "%v:\n", typ)
+	for i, id := range ids {
+		fmt.Fprintf(w, "%v: %v\n", i+1, id)
+	}
+}
+
+func handleServerError(w http.ResponseWriter, err error) {
+	w.WriteHeader(http.StatusInternalServerError)
+	fmt.Fprintf(w, "error: %v", err)
+	log.Error(err)
+}
diff --git a/nucleus/http_test.go b/nucleus/http_test.go
index 9efa72110a1fe89cf1507424d147e7faac6fd71b..bd1eeaf40a28bbc4a7edc2b1fea6bfbc4562519f 100644
--- a/nucleus/http_test.go
+++ b/nucleus/http_test.go
@@ -39,9 +39,6 @@ func testSetupHTTP() {
 }
 
 func Test_httpApi(t *testing.T) {
-	if testing.Short() {
-		t.Skip("this test is executed separately")
-	}
 	tests := []struct {
 		name    string
 		request string
@@ -123,10 +120,54 @@ func Test_httpApi(t *testing.T) {
 		},
 		{
 			name:    "set",
-			request: apiEndpoint + "/api?q=set" + args + "&path=/system/config/hostname&value=ceos3000",
+			request: apiEndpoint + "/api?q=update" + args + "&path=/system/config/hostname&value=ceos3000",
+			want:    &http.Response{StatusCode: http.StatusOK},
+			wantErr: false,
+		},
+		{
+			name:    "replace",
+			request: apiEndpoint + "/api?q=replace" + args + "&path=/system/config/hostname&value=ceos3000",
+			want:    &http.Response{StatusCode: http.StatusOK},
+			wantErr: false,
+		},
+		{
+			name:    "delete",
+			request: apiEndpoint + "/api?q=delete" + args + "&path=/system/config/hostname",
+			want:    &http.Response{StatusCode: http.StatusOK},
+			wantErr: false,
+		},
+		{
+			name:    "change list",
+			request: apiEndpoint + "/api?q=change-list" + args + "&path=/system/config/hostname",
+			want:    &http.Response{StatusCode: http.StatusOK},
+			wantErr: false,
+		},
+		{
+			name:    "change list pending",
+			request: apiEndpoint + "/api?q=change-list-pending" + args + "&path=/system/config/hostname",
 			want:    &http.Response{StatusCode: http.StatusOK},
 			wantErr: false,
 		},
+		{
+			name:    "change commit",
+			request: apiEndpoint + "/api?q=change-commit" + args + "&cuid=" + cuid.String(),
+			// TODO: Mock Change for testing
+			want:    &http.Response{StatusCode: http.StatusInternalServerError},
+			wantErr: false,
+		},
+		{
+			name:    "change confirm",
+			request: apiEndpoint + "/api?q=change-confirm" + args + "&cuid=" + cuid.String(),
+			// TODO: Mock Change for testing
+			want:    &http.Response{StatusCode: http.StatusInternalServerError},
+			wantErr: false,
+		},
+		{
+			name:    "bad request",
+			request: apiEndpoint + "/api?q=bad-request" + args,
+			want:    &http.Response{StatusCode: http.StatusBadRequest},
+			wantErr: false,
+		},
 		{
 			name:    "internal server errror: wrong pnd",
 			request: apiEndpoint + "/api?pnd=" + uuid.New().String(),
diff --git a/nucleus/initialise_test.go b/nucleus/initialise_test.go
index 6c90b054e44d009e03542821ced09f46cd65bb49..9bcd8d270f625d05445c9a818e4eedbd086edf6a 100644
--- a/nucleus/initialise_test.go
+++ b/nucleus/initialise_test.go
@@ -25,6 +25,7 @@ var defaultPndID uuid.UUID
 var ocUUID uuid.UUID
 var iid uuid.UUID
 var altIid uuid.UUID
+var cuid uuid.UUID
 
 var sbi SouthboundInterface
 var pnd PrincipalNetworkDomain
@@ -108,51 +109,38 @@ func newGnmiTransportOptions() *GnmiTransportOptions {
 func readTestUUIDs() {
 	var err error
 	did, err = uuid.Parse("4d8246f8-e884-41d6-87f5-c2c784df9e44")
-	if err != nil {
-		log.Fatal(err)
-	}
-
 	mdid, err = uuid.Parse("688a264e-5f85-40f8-bd13-afc42fcd5c7a")
-	if err != nil {
-		log.Fatal(err)
-	}
-
 	defaultSbiID, err = uuid.Parse("b70c8425-68c7-4d4b-bb5e-5586572bd64b")
-	if err != nil {
-		log.Fatal(err)
-	}
-
 	defaultPndID, err = uuid.Parse("b4016412-eec5-45a1-aa29-f59915357bad")
-	if err != nil {
-		log.Fatal(err)
-	}
-
 	ocUUID, err = uuid.Parse("5e252b70-38f2-4c99-a0bf-1b16af4d7e67")
-	if err != nil {
-		log.Fatal(err)
-	}
 	iid, err = uuid.Parse("8495a8ac-a1e8-418e-b787-10f5878b2690")
 	altIid, err = uuid.Parse("edc5de93-2d15-4586-b2a7-fb1bc770986b")
+	cuid, err = uuid.Parse("3e8219b0-e926-400d-8660-217f2a25a7c6")
 	if err != nil {
 		log.Fatal(err)
 	}
 }
 
 func mockDevice() Device {
+	sbi := &OpenConfig{}
 	return Device{
 		UUID:      mdid,
-		GoStruct:  nil,
-		SBI:       &OpenConfig{},
+		GoStruct:  sbi.Schema().Root,
+		SBI:       sbi,
 		Transport: &mocks.Transport{},
 	}
 }
 
 func newPnd() pndImplementation {
 	return pndImplementation{
-		name:        "default",
-		description: "default test pnd",
-		sbic:        sbiStore{store{}},
-		devices:     deviceStore{store{}},
-		id:          defaultPndID,
+		name:             "default",
+		description:      "default test pnd",
+		sbic:             sbiStore{store{}},
+		devices:          deviceStore{store{}},
+		pendingChanges:   changeStore{store{}},
+		committedChanges: changeStore{store{}},
+		confirmedChanges: changeStore{store{}},
+		id:               defaultPndID,
+		errChans:         make(map[uuid.UUID]chan error),
 	}
 }
diff --git a/nucleus/pnd/change.go b/nucleus/pnd/change.go
new file mode 100644
index 0000000000000000000000000000000000000000..55c7fc539f515d4383a6e9b5783986ed6feac270
--- /dev/null
+++ b/nucleus/pnd/change.go
@@ -0,0 +1,133 @@
+package pnd
+
+import (
+	"errors"
+	"github.com/google/uuid"
+	"github.com/openconfig/ygot/ygot"
+	log "github.com/sirupsen/logrus"
+	"golang.org/x/net/context"
+	"os"
+	"sync"
+	"time"
+)
+
+var changeTimeout time.Duration
+
+func init() {
+	var err error
+	e := os.Getenv("GOSDN_CHANGE_TIMEOUT")
+	if e != "" {
+		changeTimeout, err = time.ParseDuration(e)
+		if err != nil {
+			log.Fatal(err)
+		}
+	} else {
+		changeTimeout, err = time.ParseDuration("10m")
+		if err != nil {
+			log.Fatal(err)
+		}
+	}
+	log.Debugf("change timeout set to %v", changeTimeout)
+}
+
+// NewChange takes a Device UUID, a pair GoStructs (current and intended state)
+// a callback function and a channel for errors and returns a *Change
+// The callback function is used by the Commit() and Confirm() functions. It
+// must define how the change is carried out.
+func NewChange(device uuid.UUID, currentState ygot.GoStruct, change ygot.GoStruct, callback func(ygot.GoStruct, ygot.GoStruct) error, errChan chan error) *Change {
+	return &Change{
+		cuid:          uuid.New(),
+		duid:          device,
+		timestamp:     time.Now(),
+		previousState: currentState,
+		intendedState: change,
+		committed:     false,
+		confirmed:     false,
+		callback:      callback,
+		errChan:       errChan,
+		Done:          make(chan int),
+	}
+}
+
+// Change is an intended change to an OND. It is unique and immutable.
+// It has a cuid, a timestamp, and holds both the previous and the new
+// state. It keeps track if the state is committed and confirmed. A callback
+// exists to acess the proper transport for the changed OND
+type Change struct {
+	cuid          uuid.UUID
+	duid          uuid.UUID
+	timestamp     time.Time
+	previousState ygot.GoStruct
+	intendedState ygot.GoStruct
+	committed     bool
+	confirmed     bool
+	inconsistent  bool
+	callback      func(ygot.GoStruct, ygot.GoStruct) error
+	lock          sync.RWMutex
+	cancelFunc    context.CancelFunc
+	errChan       chan error
+	// TODO: Move nucleus.pndImplementation and Change to same package and unexport
+	Done chan int
+}
+
+// ID returns the Change's UUID
+func (c *Change) ID() uuid.UUID {
+	return c.cuid
+}
+
+// Commit pushes the cange to the OND using the callback() function
+// and starts the timeout-timer for the Change. If the timer expires
+// the change is rolled back.
+func (c *Change) Commit() error {
+	if err := c.callback(c.intendedState, c.previousState); err != nil {
+		return err
+	}
+	c.committed = true
+	log.WithFields(log.Fields{
+		"change uuid": c.cuid,
+		"device uuid": c.duid,
+	}).Debug("change commited")
+	ctx, cancel := context.WithCancel(context.Background())
+	c.cancelFunc = cancel
+	go c.rollbackHandler(ctx)
+	return nil
+}
+
+func (c *Change) rollbackHandler(ctx context.Context) {
+	select {
+	case <-ctx.Done():
+		return
+	case <-time.Tick(changeTimeout):
+		c.lock.RLock()
+		defer c.lock.RUnlock()
+		if !c.confirmed {
+			c.errChan <- c.callback(c.previousState, c.intendedState)
+			log.WithFields(log.Fields{
+				"change uuid": c.cuid,
+				"device uuid": c.duid,
+			}).Info("change timed out")
+		}
+	}
+}
+
+// Confirm confirms a committed Change and stops the rollback timer.
+func (c *Change) Confirm() error {
+	c.lock.RLock()
+	if !c.committed {
+		defer c.lock.RUnlock()
+		return errors.New("cannot confirm uncommitted change")
+	}
+	c.lock.RUnlock()
+	c.lock.Lock()
+	defer c.lock.Unlock()
+	c.confirmed = true
+	c.cancelFunc()
+	close(c.errChan)
+	c.Done <- 0
+	close(c.Done)
+	log.WithFields(log.Fields{
+		"change uuid": c.cuid,
+		"device uuid": c.duid,
+	}).Info("change confirmed")
+	return nil
+}
diff --git a/nucleus/pnd/change_test.go b/nucleus/pnd/change_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..7871a0db04a1527246df36a23b0ad83d264d10ef
--- /dev/null
+++ b/nucleus/pnd/change_test.go
@@ -0,0 +1,244 @@
+package pnd
+
+import (
+	"context"
+	"errors"
+	"github.com/google/uuid"
+	"github.com/openconfig/ygot/exampleoc"
+	"github.com/openconfig/ygot/ygot"
+	"reflect"
+	"sync"
+	"testing"
+	"time"
+)
+
+var commit = "commit"
+var rollback = "rollback"
+
+var commitDevice = &exampleoc.Device{
+	System: &exampleoc.System{
+		Hostname: &commit,
+	},
+}
+
+var rollbackDevice = &exampleoc.Device{
+	System: &exampleoc.System{
+		Hostname: &rollback,
+	},
+}
+
+func TestChange_CommitRollback(t *testing.T) {
+	wantErr := false
+	want := rollback
+	callback := make(chan string)
+	c := &Change{
+		cuid:          changeUUID,
+		duid:          did,
+		timestamp:     time.Now(),
+		previousState: rollbackDevice,
+		intendedState: commitDevice,
+		callback: func(first ygot.GoStruct, second ygot.GoStruct) error {
+			hostname := *first.(*exampleoc.Device).System.Hostname
+			t.Logf("hostname: %v", hostname)
+			switch hostname {
+			case rollback:
+				callback <- rollback
+			}
+			return nil
+		},
+		lock: sync.RWMutex{},
+	}
+	go func() {
+		time.Sleep(time.Millisecond * 10)
+		if err := c.Commit(); (err != nil) != wantErr {
+			t.Errorf("Commit() error = %v, wantErr %v", err, wantErr)
+		}
+		time.Sleep(changeTimeout)
+	}()
+	got := <-callback
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("Commit() = %v, want %v", got, want)
+	}
+	close(callback)
+}
+
+func TestChange_CommitRollbackError(t *testing.T) {
+	wantErr := false
+	want := errors.New("this is an expected error")
+	c := &Change{
+		cuid:          changeUUID,
+		duid:          did,
+		timestamp:     time.Now(),
+		previousState: rollbackDevice,
+		intendedState: commitDevice,
+		callback: func(first ygot.GoStruct, second ygot.GoStruct) error {
+			hostname := *first.(*exampleoc.Device).System.Hostname
+			t.Logf("hostname: %v", hostname)
+			switch hostname {
+			case rollback:
+				return errors.New("this is an expected error")
+			}
+			return nil
+		},
+		lock:    sync.RWMutex{},
+		errChan: make(chan error),
+	}
+	go func() {
+		time.Sleep(time.Millisecond * 10)
+		if err := c.Commit(); (err != nil) != wantErr {
+			t.Errorf("Commit() error = %v, wantErr %v", err, wantErr)
+		}
+		time.Sleep(changeTimeout)
+	}()
+	got := <-c.errChan
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("Commit() = %v, want %v", got, want)
+	}
+	close(c.errChan)
+}
+
+func TestChange_CommitError(t *testing.T) {
+	wantErr := true
+	c := &Change{
+		cuid:          changeUUID,
+		duid:          did,
+		timestamp:     time.Now(),
+		previousState: rollbackDevice,
+		intendedState: commitDevice,
+		callback: func(first ygot.GoStruct, second ygot.GoStruct) error {
+			return errors.New("this is an expected error")
+		},
+		lock: sync.RWMutex{},
+	}
+	go func() {
+		time.Sleep(time.Millisecond * 10)
+		if err := c.Commit(); (err != nil) != wantErr {
+			t.Errorf("Commit() error = %v, wantErr %v", err, wantErr)
+		}
+	}()
+	got := c.committed
+	if !reflect.DeepEqual(got, false) {
+		t.Errorf("Commit() = %v, want %v", got, false)
+	}
+}
+
+func TestChange_Commit(t *testing.T) {
+	wantErr := false
+	want := commit
+	callback := make(chan string)
+
+	c := &Change{
+		cuid:          changeUUID,
+		duid:          did,
+		timestamp:     time.Now(),
+		previousState: rollbackDevice,
+		intendedState: commitDevice,
+		callback: func(first ygot.GoStruct, second ygot.GoStruct) error {
+			hostname := *first.(*exampleoc.Device).System.Hostname
+			t.Logf("hostname: %v", hostname)
+			callback <- hostname
+			return nil
+		},
+		lock:    sync.RWMutex{},
+		errChan: make(chan error),
+		Done:    make(chan int),
+	}
+	go func() {
+		time.Sleep(time.Millisecond * 10)
+		if err := c.Commit(); (err != nil) != wantErr {
+			t.Errorf("Commit() error = %v, wantErr %v", err, wantErr)
+		}
+		if err := c.Confirm(); err != nil {
+			t.Errorf("Commit() error = %v", err)
+		}
+	}()
+	got := <-callback
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("Commit() = %v, want %v", got, want)
+	}
+	close(callback)
+}
+
+func TestChange_Confirm(t *testing.T) {
+	_, cancel := context.WithCancel(context.Background())
+	type fields struct {
+		cuid          uuid.UUID
+		duid          uuid.UUID
+		timestamp     time.Time
+		previousState ygot.GoStruct
+		intendedState ygot.GoStruct
+		callback      func(ygot.GoStruct, ygot.GoStruct) error
+		committed     bool
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		wantErr bool
+	}{
+		{
+			name: "committed",
+			fields: fields{
+				committed: true,
+			},
+			wantErr: false,
+		},
+		{
+			name:    "uncommitted",
+			fields:  fields{},
+			wantErr: true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			c := &Change{
+				committed: tt.fields.committed,
+				timestamp: tt.fields.timestamp,
+				previousState: &exampleoc.Device{
+					System: &exampleoc.System{
+						Hostname: &rollback,
+					},
+				},
+				intendedState: &exampleoc.Device{
+					System: &exampleoc.System{
+						Hostname: &commit,
+					},
+				},
+				cancelFunc: cancel,
+				lock:       sync.RWMutex{},
+				errChan:    make(chan error),
+				Done:       make(chan int, 1),
+			}
+			if err := c.Confirm(); (err != nil) != tt.wantErr {
+				t.Errorf("Confirm() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+	cancel()
+}
+
+func TestChange_ID(t *testing.T) {
+	type fields struct {
+		cuid uuid.UUID
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		want   uuid.UUID
+	}{
+		{
+			name:   "default",
+			fields: fields{cuid: changeUUID},
+			want:   changeUUID,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			c := &Change{
+				cuid: tt.fields.cuid,
+			}
+			if got := c.ID(); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("ID() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/nucleus/pnd/initialise_test.go b/nucleus/pnd/initialise_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..674656c8825327bac8c34ef84a8db6548ea2baaf
--- /dev/null
+++ b/nucleus/pnd/initialise_test.go
@@ -0,0 +1,22 @@
+package pnd
+
+import (
+	"github.com/google/uuid"
+	log "github.com/sirupsen/logrus"
+	"os"
+	"testing"
+)
+
+// UUIDs for test cases
+var changeUUID uuid.UUID
+var did uuid.UUID
+
+func TestMain(m *testing.M) {
+	var err error
+	changeUUID, err = uuid.Parse("cfbb96cd-ecad-45d1-bebf-1851760f5087")
+	did, err = uuid.Parse("4d8246f8-e884-41d6-87f5-c2c784df9e44")
+	if err != nil {
+		log.Fatal(err)
+	}
+	os.Exit(m.Run())
+}
diff --git a/nucleus/principalNetworkDomain.go b/nucleus/principalNetworkDomain.go
index 88c08172e2f4c859d1a8212328a20680953e3054..6a2da78f52ea9322b8290d5aa6d4d6261fe59def 100644
--- a/nucleus/principalNetworkDomain.go
+++ b/nucleus/principalNetworkDomain.go
@@ -2,7 +2,10 @@ package nucleus
 
 import (
 	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
+	. "code.fbi.h-da.de/cocsn/gosdn/nucleus/pnd" //nolint
 	"context"
+	"github.com/openconfig/ygot/ygot"
+	"github.com/openconfig/ygot/ytypes"
 	log "github.com/sirupsen/logrus"
 
 	"encoding/json"
@@ -16,7 +19,10 @@ type PrincipalNetworkDomain interface {
 	AddSbi(interface{}) error
 	RemoveSbi(uuid.UUID) error
 	AddDevice(interface{}) error
+	GetDevice(uuid uuid.UUID) (ygot.GoStruct, error)
 	RemoveDevice(uuid.UUID) error
+	Devices() []uuid.UUID
+	ChangeOND(uuid uuid.UUID, operation interface{}, path string, value ...string) error
 	Request(uuid.UUID, string) error
 	RequestAll(string) error
 	GetName() string
@@ -25,24 +31,24 @@ type PrincipalNetworkDomain interface {
 	ContainsDevice(uuid.UUID) bool
 	GetSBIs() interface{}
 	ID() uuid.UUID
-}
-
-type pndImplementation struct {
-	name        string
-	description string
-	sbic        sbiStore
-	devices     deviceStore
-	id          uuid.UUID
+	Pending() []uuid.UUID
+	Committed() []uuid.UUID
+	Commit(uuid.UUID) error
+	Confirm(uuid.UUID) error
 }
 
 // NewPND creates a Principle Network Domain
 func NewPND(name, description string, id uuid.UUID, sbi SouthboundInterface) (PrincipalNetworkDomain, error) {
 	pnd := &pndImplementation{
-		name:        name,
-		description: description,
-		sbic:        sbiStore{store{}},
-		devices:     deviceStore{store{}},
-		id:          id,
+		name:             name,
+		description:      description,
+		sbic:             sbiStore{store{}},
+		devices:          deviceStore{store{}},
+		pendingChanges:   changeStore{store{}},
+		committedChanges: changeStore{store{}},
+		confirmedChanges: changeStore{store{}},
+		id:               id,
+		errChans:         make(map[uuid.UUID]chan error),
 	}
 	if err := pnd.sbic.add(sbi); err != nil {
 		return nil, err
@@ -50,10 +56,72 @@ func NewPND(name, description string, id uuid.UUID, sbi SouthboundInterface) (Pr
 	return pnd, nil
 }
 
+type pndImplementation struct {
+	name             string
+	description      string
+	sbic             sbiStore
+	devices          deviceStore
+	pendingChanges   changeStore
+	committedChanges changeStore
+	confirmedChanges changeStore
+	id               uuid.UUID
+	errChans         map[uuid.UUID]chan error
+}
+
+func (pnd *pndImplementation) Pending() []uuid.UUID {
+	return pnd.pendingChanges.UUIDs()
+}
+
+func (pnd *pndImplementation) Committed() []uuid.UUID {
+	return pnd.committedChanges.UUIDs()
+}
+
+func (pnd *pndImplementation) Commit(u uuid.UUID) error {
+	change, err := pnd.pendingChanges.get(u)
+	if err != nil {
+		return err
+	}
+	if err := change.Commit(); err != nil {
+		return err
+	}
+	go func() {
+		for {
+			select {
+			case err := <-pnd.errChans[u]:
+				handleRollbackError(change.ID(), err)
+			case <-change.Done:
+			}
+		}
+	}()
+	if err := pnd.committedChanges.add(change); err != nil {
+		return err
+	}
+	return pnd.pendingChanges.delete(u)
+}
+
+func (pnd *pndImplementation) Confirm(u uuid.UUID) error {
+	change, err := pnd.committedChanges.get(u)
+	if err != nil {
+		return err
+	}
+	if err := change.Confirm(); err != nil {
+		return err
+	}
+	if err := pnd.confirmedChanges.add(change); err != nil {
+		return err
+	}
+	close(pnd.errChans[u])
+	return pnd.committedChanges.delete(u)
+}
+
 func (pnd *pndImplementation) ID() uuid.UUID {
 	return pnd.id
 }
 
+func (pnd *pndImplementation) Devices() []uuid.UUID {
+	return pnd.devices.UUIDs()
+}
+
 // GetName returns the name of the PND
 func (pnd *pndImplementation) GetName() string {
 	return pnd.name
@@ -91,7 +159,7 @@ func (pnd *pndImplementation) AddSbi(sbi interface{}) error {
 	return pnd.addSbi(s)
 }
 
-// AddSbi removes a SBI from the PND
+// RemoveSbi removes a SBI from the PND
 // TODO: this should to recursivly through
 // devices and remove the devices using
 // this SBI
@@ -111,6 +179,14 @@ func (pnd *pndImplementation) AddDevice(device interface{}) error {
 	return pnd.addDevice(d)
 }
 
+func (pnd *pndImplementation) GetDevice(uuid uuid.UUID) (ygot.GoStruct, error) {
+	d, err := pnd.devices.get(uuid)
+	if err != nil {
+		return nil, err
+	}
+	return ygot.DeepCopy(d.GoStruct)
+}
+
 // RemoveDevice removes a device from the PND
 func (pnd *pndImplementation) RemoveDevice(uuid uuid.UUID) error {
 	return pnd.removeDevice(uuid)
@@ -190,24 +266,54 @@ func (pnd *pndImplementation) RequestAll(path string) error {
 	return nil
 }
 
-// Set sets the value to the given device path
-// TODO: Design commit/confirm mechanism
-func (pnd *pndImplementation) Set(uuid uuid.UUID, path string, value string) (interface{}, error) {
+// ChangeOND creates a change from the provided Operation, path and value. The Change is pending and
+func (pnd *pndImplementation) ChangeOND(uuid uuid.UUID, operation interface{}, path string, value ...string) error {
 	d, err := pnd.getDevice(uuid)
 	if err != nil {
-		return nil, err
+		return err
 	}
-	ctx := context.Background()
+	cpy, err := ygot.DeepCopy(d.GoStruct)
+	ygot.BuildEmptyTree(cpy)
+
+	p, err := ygot.StringToStructuredPath(path)
+	if err != nil {
+		return err
+	}
+
+	if len(value) > 1 {
+		return &ErrInvalidParameters{
+			f: pnd.ChangeOND,
+			r: value,
+		}
+	}
+
+	switch operation {
+	case TransportUpdate, TransportReplace:
+		typedValue := gnmi.TypedValue(value[0])
+		if err := ytypes.SetNode(d.SBI.Schema().RootSchema(), cpy, p, typedValue); err != nil {
+			return err
+		}
+	case TransportDelete:
+		if err := ytypes.DeleteNode(d.SBI.Schema().RootSchema(), cpy, p); err != nil {
+			return err
+		}
+	default:
+		return &ErrOperationNotSupported{o: operation}
+	}
+
+	callback := func(state ygot.GoStruct, change ygot.GoStruct) error {
+		ctx := context.Background()
+		return d.Transport.Set(ctx, state, change)
+	}
+
+	errChan := make(chan error)
+	change := NewChange(uuid, d.GoStruct, cpy, callback, errChan)
+	pnd.errChans[change.ID()] = errChan
+
+	return pnd.pendingChanges.add(change)
+}
 
-	// TODO: Move to transport dependent func
-	opts := []interface{}{
-		&gnmi.Operation{
-			Type:   "update",
-			Origin: "",
-			Target: "",
-			Path:   gnmi.SplitPath(path),
-			Val:    value,
-		},
-	}
-	return d.Transport.Set(ctx, opts...)
+func handleRollbackError(id uuid.UUID, err error) {
+	log.Error(err)
+	// TODO: Notion of invalid state needed.
 }
diff --git a/nucleus/principalNetworkDomain_test.go b/nucleus/principalNetworkDomain_test.go
index f02f840bc948d4887983a4beb532808d9e8dc2c7..8b4ff39d341034c9a38379884b29bfb50dfd5b04 100644
--- a/nucleus/principalNetworkDomain_test.go
+++ b/nucleus/principalNetworkDomain_test.go
@@ -522,3 +522,114 @@ func Test_pndImplementation_RequestAll(t *testing.T) {
 		})
 	}
 }
+
+func Test_pndImplementation_ChangeOND(t *testing.T) {
+	type fields struct {
+	}
+	type args struct {
+		uuid      uuid.UUID
+		operation interface{}
+		path      string
+		value     []string
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr bool
+	}{
+		{
+			name:   "update",
+			fields: fields{},
+			args: args{
+				uuid:      mdid,
+				operation: TransportUpdate,
+				path:      "/system/config/hostname",
+				value:     []string{"ceos3000"},
+			},
+			wantErr: false,
+		},
+		{
+			name:   "replace",
+			fields: fields{},
+			args: args{
+				uuid:      mdid,
+				operation: TransportReplace,
+				path:      "/system/config/hostname",
+				value:     []string{"ceos3000"},
+			},
+			wantErr: false,
+		},
+		{
+			name:   "delete",
+			fields: fields{},
+			args: args{
+				uuid:      mdid,
+				operation: TransportDelete,
+				path:      "/system/config/hostname",
+			},
+			wantErr: false,
+		},
+		{
+			name:   "delete w/args",
+			fields: fields{},
+			args: args{
+				uuid:      mdid,
+				operation: TransportDelete,
+				path:      "/system/config/hostname",
+				value:     []string{"ceos3000"},
+			},
+			wantErr: false,
+		},
+
+		// Negative test cases
+		{
+			name:   "invalid operation",
+			fields: fields{},
+			args: args{
+				uuid:      mdid,
+				operation: "INVALID",
+			},
+			wantErr: true,
+		},
+		{
+			name:   "invalid arg count",
+			fields: fields{},
+			args: args{
+				uuid:      mdid,
+				operation: TransportUpdate,
+				path:      "/system/config/hostname",
+				value:     []string{"ceos3000", "ceos3001"},
+			},
+			wantErr: true,
+		},
+		{
+			name:   "device not found",
+			fields: fields{},
+			args: args{
+				uuid:      did,
+				operation: TransportUpdate,
+			},
+			wantErr: true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			p := newPnd()
+			d := mockDevice()
+			if err := p.AddDevice(&d); err != nil {
+				t.Error(err)
+				return
+			}
+			if err := p.ChangeOND(tt.args.uuid, tt.args.operation, tt.args.path, tt.args.value...); (err != nil) != tt.wantErr {
+				t.Errorf("ChangeOND() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !tt.wantErr {
+				if len(p.pendingChanges.store) != 1 {
+					t.Errorf("ChangeOND() unexpected change count. got %v, want 1", len(p.pendingChanges.store))
+				}
+			}
+		})
+	}
+}
diff --git a/nucleus/restconf_transport.go b/nucleus/restconf_transport.go
index 0dd477196745a83fda3b8460e1c5755b377748a1..44411bf26586abbbbe7f499f122aa624d9d6e17d 100644
--- a/nucleus/restconf_transport.go
+++ b/nucleus/restconf_transport.go
@@ -7,30 +7,34 @@ import (
 
 // Restconf implements the Transport interface and provides an SBI with the
 // possibility to access a Restconf endpoint.
-type Restconf struct {
-}
+type Restconf struct{}
 
-//Get not implemented yet
+// Get not yet implemented
 func (r Restconf) Get(ctx context.Context, params ...string) (interface{}, error) {
 	return nil, &ErrNotYetImplemented{}
 }
 
-//Set not implemented yet
-func (r Restconf) Set(ctx context.Context, params ...string) (interface{}, error) {
-	return nil, &ErrNotYetImplemented{}
+// Set not yet implemented
+func (r Restconf) Set(ctx context.Context, params ...interface{}) error {
+	return &ErrNotYetImplemented{}
 }
 
-// Subscribe not implemented yet
+// Subscribe not yet implemented
 func (r Restconf) Subscribe(ctx context.Context, params ...string) error {
 	return &ErrNotYetImplemented{}
 }
 
-// Type returns the RESTCONF transport type
+// Type not yet implemented
 func (r Restconf) Type() string {
 	return "restconf"
 }
 
-// ProcessResponse not implemented yet
+// GetOptions not yet implemented
+func (r Restconf) GetOptions() interface{} {
+	return &ErrNotYetImplemented{}
+}
+
+// ProcessResponse not yet implemented
 func (r Restconf) ProcessResponse(resp interface{}, root interface{}, models *ytypes.Schema) error {
 	return &ErrNotYetImplemented{}
 }
diff --git a/nucleus/restconf_transport_test.go b/nucleus/restconf_transport_test.go
index 5f1eb1e352f2cb8214686c5215eea419c465dcd4..b31df33d665563cb12c64aac28f98788454e7272 100644
--- a/nucleus/restconf_transport_test.go
+++ b/nucleus/restconf_transport_test.go
@@ -61,26 +61,21 @@ func TestRestconf_ProcessResponse(t *testing.T) {
 func TestRestconf_Set(t *testing.T) {
 	type args struct {
 		ctx    context.Context
-		params []string
+		params []interface{}
 	}
 	tests := []struct {
 		name    string
 		args    args
-		want    interface{}
 		wantErr bool
 	}{
-		{name: "not implemented", args: args{}, want: nil, wantErr: true},
+		{name: "not implemented", args: args{}, wantErr: true},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			r := Restconf{}
-			got, err := r.Set(tt.args.ctx, tt.args.params...)
+			err := r.Set(tt.args.ctx, tt.args.params...)
 			if (err != nil) != tt.wantErr {
 				t.Errorf("Set() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("Set() got = %v, want %v", got, tt.want)
 			}
 		})
 	}
diff --git a/nucleus/sbi-openconfig.go b/nucleus/sbi-openconfig.go
deleted file mode 100644
index 0fa4ffa903a1f894325aaf5211341e19a2df754a..0000000000000000000000000000000000000000
--- a/nucleus/sbi-openconfig.go
+++ /dev/null
@@ -1 +0,0 @@
-package nucleus
diff --git a/nucleus/southbound_test.go b/nucleus/southbound_test.go
index ab46901446e0cac93464c4aa111436953a51436a..5df2efeab8351538bea042965fb384d0c8affe53 100644
--- a/nucleus/southbound_test.go
+++ b/nucleus/southbound_test.go
@@ -1,6 +1,7 @@
 package nucleus
 
 import (
+	"code.fbi.h-da.de/cocsn/gosdn/nucleus/util/path"
 	"code.fbi.h-da.de/cocsn/gosdn/nucleus/util/proto"
 	"code.fbi.h-da.de/cocsn/yang-models/generated/openconfig"
 	"github.com/google/uuid"
@@ -161,7 +162,7 @@ func Test_unmarshal(t *testing.T) {
 			if err != nil {
 				t.Error(err)
 			}
-			fields := extraxtPathElements(resp.Notification[0].Update[0].Path)
+			fields := path.ToStrings(resp.Notification[0].Update[0].Path)
 			bytes := resp.Notification[0].Update[0].Val.GetJsonIetfVal()
 			if err := unmarshal(bytes, fields, tt.args.goStruct, tt.args.opt...); (err != nil) != tt.wantErr {
 				t.Errorf("unmarshal() error = %v, wantErr %v", err, tt.wantErr)
diff --git a/nucleus/store.go b/nucleus/store.go
index 0563a5a30533467809380ac25d949bfc4b578e68..7f6b98fed1ed15b2e23a4c3efb9ed2dce25d83e7 100644
--- a/nucleus/store.go
+++ b/nucleus/store.go
@@ -1,6 +1,7 @@
 package nucleus
 
 import (
+	p "code.fbi.h-da.de/cocsn/gosdn/nucleus/pnd"
 	"github.com/google/uuid"
 	log "github.com/sirupsen/logrus"
 	"reflect"
@@ -131,7 +132,7 @@ func (s deviceStore) get(id uuid.UUID) (*Device, error) {
 	if !ok {
 		return nil, &ErrInvalidTypeAssertion{
 			v: device,
-			t: "Device",
+			t: reflect.TypeOf(&Device{}),
 		}
 	}
 	log.WithFields(log.Fields{
@@ -139,3 +140,25 @@ func (s deviceStore) get(id uuid.UUID) (*Device, error) {
 	}).Debug("device was accessed")
 	return device, nil
 }
+
+type changeStore struct {
+	store
+}
+
+func (s changeStore) get(id uuid.UUID) (*p.Change, error) {
+	item, err := s.store.get(id)
+	if err != nil {
+		return nil, err
+	}
+	change, ok := item.(*p.Change)
+	if !ok {
+		return nil, &ErrInvalidTypeAssertion{
+			v: change,
+			t: reflect.TypeOf(&p.Change{}),
+		}
+	}
+	log.WithFields(log.Fields{
+		"uuid": id,
+	}).Debug("change was accessed")
+	return change, nil
+}
diff --git a/nucleus/transport.go b/nucleus/transport.go
index 36dda96300e226ac74de3682d86885e20332191a..6df6e6b7de23206a7b8e1c692d897cfe5fbb9e0b 100644
--- a/nucleus/transport.go
+++ b/nucleus/transport.go
@@ -7,12 +7,25 @@ import (
 	"io"
 )
 
-// Transport provides an interface for
-// Transport implementations like RESTCONF
-// or gnmi
+// Operation codes numerous operations used to change the state of remote resources.
+// It is used as a unified code. Each Transport implementation needs to map these
+// accordingly to its specification.
+type Operation int
+
+const (
+	// TransportUpdate codes an update operation
+	TransportUpdate Operation = iota
+	// TransportReplace codes a replace operation
+	TransportReplace
+	// TransportDelete codes a delete operation
+	TransportDelete
+)
+
+// Transport provides an interface for Transport implementations
+// like RESTCONF or gnmi
 type Transport interface {
 	Get(ctx context.Context, params ...string) (interface{}, error)
-	Set(ctx context.Context, params ...interface{}) (interface{}, error)
+	Set(ctx context.Context, params ...interface{}) error
 	Subscribe(ctx context.Context, params ...string) error
 	Type() string
 	GetOptions() interface{}
diff --git a/nucleus/util/path/translate.go b/nucleus/util/path/translate.go
new file mode 100644
index 0000000000000000000000000000000000000000..e245344085d02130b5277334df9546aab98bc197
--- /dev/null
+++ b/nucleus/util/path/translate.go
@@ -0,0 +1,15 @@
+package path
+
+import (
+	gpb "github.com/openconfig/gnmi/proto/gnmi"
+	"strings"
+)
+
+// ToStrings translates a gNMI path to a slice of strings
+func ToStrings(path *gpb.Path) []string {
+	elems := make([]string, len(path.Elem))
+	for i, e := range path.Elem {
+		elems[i] = strings.Title(e.Name)
+	}
+	return elems
+}
diff --git a/nucleus/util/path/path_traversal.go b/nucleus/util/path/traverse.go
similarity index 100%
rename from nucleus/util/path/path_traversal.go
rename to nucleus/util/path/traverse.go
diff --git a/nucleus/util/path/path_traversal_test.go b/nucleus/util/path/traverse_test.go
similarity index 100%
rename from nucleus/util/path/path_traversal_test.go
rename to nucleus/util/path/traverse_test.go
diff --git a/test/integration/cmdIntegration_test.go b/test/integration/cmdIntegration_test.go
index 0aefff4db74566a9dc411cc76de8c4965766570a..bb57a774ce0a63ec970bbfa6c1e82f06159b81ec 100644
--- a/test/integration/cmdIntegration_test.go
+++ b/test/integration/cmdIntegration_test.go
@@ -28,7 +28,6 @@ func TestMain(m *testing.M) {
 	os.Exit(m.Run())
 }
 
-
 func testSetupIntegration() {
 	if os.Getenv("GOSDN_LOG") == "nolog" {
 		log.SetLevel(log.PanicLevel)
diff --git a/test/integration/nucleusIntegration_test.go b/test/integration/nucleusIntegration_test.go
index 816888d6f77f857225f34d22b794017efe641629..54f310491d161b597762bc4028e5bbfebd07c8f1 100644
--- a/test/integration/nucleusIntegration_test.go
+++ b/test/integration/nucleusIntegration_test.go
@@ -23,13 +23,12 @@ func TestGnmi_SetIntegration(t *testing.T) {
 	}
 	type args struct {
 		ctx    context.Context
-		params []interface{}
+		params []string
 	}
 	tests := []struct {
 		name    string
 		fields  fields
 		args    args
-		want    interface{}
 		wantErr bool
 	}{
 		{
@@ -42,31 +41,17 @@ func TestGnmi_SetIntegration(t *testing.T) {
 			},
 			args: args{
 				ctx:    context.Background(),
-				params: []interface{}{&gnmi.Operation{}},
+				params: []string{},
 			},
-			want:    nil,
 			wantErr: true,
 		},
 		{
 			name:   "valid update",
 			fields: fields{opt: opt},
 			args: args{
-				ctx: context.Background(),
-				params: []interface{}{
-					&gnmi.Operation{
-						Type:   "update",
-						Origin: "",
-						Target: "",
-						Path: []string{
-							"system",
-							"config",
-							"hostname",
-						},
-						Val: "ceos3000",
-					},
-				},
+				ctx:    context.Background(),
+				params: []string{"/system/config/hostname", "ceos3000"},
 			},
-			want:    gnmiMessages["../proto/resp-set-system-config-hostname"],
 			wantErr: false,
 		},
 	}
@@ -77,21 +62,11 @@ func TestGnmi_SetIntegration(t *testing.T) {
 				t.Errorf("NewGnmiTransport() error = %v, wantErr %v", err, tt.wantErr)
 				return
 			}
-			resp, err := g.Set(tt.args.ctx, tt.args.params...)
+			err = g.Set(tt.args.ctx, tt.args.params)
 			if (err != nil) != tt.wantErr {
 				t.Errorf("Set() error = %v, wantErr %v", err, tt.wantErr)
 				return
 			}
-			got, ok := resp.(*gpb.SetResponse)
-			if !ok {
-				t.Errorf("want: %v, got %v, error: %v", reflect.TypeOf(&gpb.SetResponse{}), reflect.TypeOf(resp), &nucleus.ErrInvalidTypeAssertion{})
-			}
-			if err != nil && tt.wantErr {
-				return
-			} else if got.Prefix.Target != testAddress ||
-				got.Response[0].Op != gpb.UpdateResult_UPDATE {
-				t.Errorf("Set() got = %v, want %v", got, tt.want)
-			}
 		})
 	}
 }