Skip to content

Commit

Permalink
Merge pull request #473 from openziti/zrok_copy_p1
Browse files Browse the repository at this point in the history
'zrok copy' (phase 1) (#438)
  • Loading branch information
michaelquigley authored Jan 22, 2024
2 parents bd81ed2 + 8f624f8 commit 8d88e32
Show file tree
Hide file tree
Showing 44 changed files with 18,277 additions and 4 deletions.
59 changes: 59 additions & 0 deletions ACKNOWLEDGEMENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# ACKNOWLEDGEMENTS

## github.com/openziti/zrok/drives/davServer

The `davServer` package is based on code from `https://cs.opensource.google/go/go/`, which included the following license:

> Copyright (c) 2009 The Go Authors. All rights reserved.
>
> Redistribution and use in source and binary forms, with or without
> modification, are permitted provided that the following conditions are
> met:
>
> * Redistributions of source code must retain the above copyright
> notice, this list of conditions and the following disclaimer.
> * 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.
> * Neither the name of Google Inc. 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
> OWNER 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
## github.com/openziti/zrok/drives/davClient

The `davClient` package is based on code from `github.com/emersion/go-webdav`, which included the following license:

> The MIT License (MIT)
>
> Copyright (c) 2020 Simon Ser
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all
> copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> SOFTWARE.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## v0.4.23

FEATURE: New CLI commands have been implemented for working with the `drive` share backend mode (part of the "zrok Drives" functionality). These commands include `zrok cp`, `zrok mkdir` `zrok mv`, `zrok ls`, and `zrok rm`. These are initial, minimal versions of these commands and very likely contain bugs and ergonomic annoyances. There is a guide available at (`docs/guides/drives/cli.md`) that explains how to work with these tools in detail (https://github.com/openziti/zrok/issues/438)

FEATURE: Python SDK now has a decorator for integrating with various server side frameworks. See the `http-server` example.

FEATURE: Python SDK share and access handling now supports context management.
Expand Down
106 changes: 106 additions & 0 deletions cmd/zrok/copy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package main

import (
"fmt"
"github.com/openziti/zrok/drives/sync"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/sdk/golang/sdk"
"github.com/openziti/zrok/tui"
"github.com/spf13/cobra"
"net/url"
"os"
)

func init() {
rootCmd.AddCommand(newCopyCommand().cmd)
}

type copyCommand struct {
cmd *cobra.Command
sync bool
basicAuth string
}

func newCopyCommand() *copyCommand {
cmd := &cobra.Command{
Use: "copy <source> [<target>] (<target> defaults to 'file://.`)",
Short: "Copy (unidirectional sync) zrok drive contents from <source> to <target> ('http://', 'file://', and 'zrok://' supported)",
Aliases: []string{"cp"},
Args: cobra.RangeArgs(1, 2),
}
command := &copyCommand{cmd: cmd}
cmd.Run = command.run
cmd.Flags().BoolVarP(&command.sync, "sync", "s", false, "Only copy modified files (one-way synchronize)")
cmd.Flags().StringVarP(&command.basicAuth, "basic-auth", "a", "", "Basic authentication <username:password>")
return command
}

func (cmd *copyCommand) run(_ *cobra.Command, args []string) {
if cmd.basicAuth == "" {
cmd.basicAuth = os.Getenv("ZROK_DRIVES_BASIC_AUTH")
}

sourceUrl, err := url.Parse(args[0])
if err != nil {
tui.Error(fmt.Sprintf("invalid source '%v'", args[0]), err)
}
if sourceUrl.Scheme == "" {
sourceUrl.Scheme = "file"
}

targetStr := "."
if len(args) == 2 {
targetStr = args[1]
}
targetUrl, err := url.Parse(targetStr)
if err != nil {
tui.Error(fmt.Sprintf("invalid target '%v'", targetStr), err)
}
if targetUrl.Scheme == "" {
targetUrl.Scheme = "file"
}

root, err := environment.LoadRoot()
if err != nil {
tui.Error("error loading root", err)
}

var allocatedAccesses []*sdk.Access
if sourceUrl.Scheme == "zrok" {
access, err := sdk.CreateAccess(root, &sdk.AccessRequest{ShareToken: sourceUrl.Host})
if err != nil {
tui.Error("error creating access", err)
}
allocatedAccesses = append(allocatedAccesses, access)
}
if targetUrl.Scheme == "zrok" {
access, err := sdk.CreateAccess(root, &sdk.AccessRequest{ShareToken: targetUrl.Host})
if err != nil {
tui.Error("error creating access", err)
}
allocatedAccesses = append(allocatedAccesses, access)
}
defer func() {
for _, access := range allocatedAccesses {
err := sdk.DeleteAccess(root, access)
if err != nil {
tui.Warning("error deleting target access", err)
}
}
}()

source, err := sync.TargetForURL(sourceUrl, root, cmd.basicAuth)
if err != nil {
tui.Error(fmt.Sprintf("error creating target for '%v'", sourceUrl), err)
}
target, err := sync.TargetForURL(targetUrl, root, cmd.basicAuth)
if err != nil {
tui.Error(fmt.Sprintf("error creating target for '%v'", targetUrl), err)
}

if err := sync.OneWay(source, target, cmd.sync); err != nil {
tui.Error("error copying", err)
}

fmt.Println("copy complete!")
}
95 changes: 95 additions & 0 deletions cmd/zrok/ls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package main

import (
"fmt"
"github.com/jedib0t/go-pretty/v6/table"
"github.com/openziti/zrok/drives/sync"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/sdk/golang/sdk"
"github.com/openziti/zrok/tui"
"github.com/openziti/zrok/util"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"net/url"
"os"
"sort"
)

func init() {
rootCmd.AddCommand(newLsCommand().cmd)
}

type lsCommand struct {
cmd *cobra.Command
basicAuth string
}

func newLsCommand() *lsCommand {
cmd := &cobra.Command{
Use: "ls <target>",
Short: "List the contents of drive <target> ('http://', 'zrok://','file://')",
Aliases: []string{"dir"},
Args: cobra.ExactArgs(1),
}
command := &lsCommand{cmd: cmd}
cmd.Run = command.run
cmd.Flags().StringVarP(&command.basicAuth, "basic-auth", "a", "", "Basic authentication <username:password>")
return command
}

func (cmd *lsCommand) run(_ *cobra.Command, args []string) {
if cmd.basicAuth == "" {
cmd.basicAuth = os.Getenv("ZROK_DRIVES_BASIC_AUTH")
}

targetUrl, err := url.Parse(args[0])
if err != nil {
tui.Error(fmt.Sprintf("invalid target '%v'", args[0]), err)
}
if targetUrl.Scheme == "" {
targetUrl.Scheme = "file"
}

root, err := environment.LoadRoot()
if err != nil {
tui.Error("error loading root", err)
}

if targetUrl.Scheme == "zrok" {
access, err := sdk.CreateAccess(root, &sdk.AccessRequest{ShareToken: targetUrl.Host})
if err != nil {
tui.Error("error creating access", err)
}
defer func() {
if err := sdk.DeleteAccess(root, access); err != nil {
logrus.Warningf("error freeing access: %v", err)
}
}()
}

target, err := sync.TargetForURL(targetUrl, root, cmd.basicAuth)
if err != nil {
tui.Error(fmt.Sprintf("error creating target for '%v'", targetUrl), err)
}

objects, err := target.Dir("/")
if err != nil {
tui.Error("error listing directory", err)
}
sort.Slice(objects, func(i, j int) bool {
return objects[i].Path < objects[j].Path
})

tw := table.NewWriter()
tw.SetOutputMirror(os.Stdout)
tw.SetStyle(table.StyleLight)
tw.AppendHeader(table.Row{"type", "Name", "Size", "Modified"})
for _, object := range objects {
if object.IsDir {
tw.AppendRow(table.Row{"DIR", object.Path, "", ""})
} else {
tw.AppendRow(table.Row{"", object.Path, util.BytesToSize(object.Size), object.Modified.Local()})
}
}
tw.Render()
}
75 changes: 75 additions & 0 deletions cmd/zrok/md.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package main

import (
"fmt"
"github.com/openziti/zrok/drives/sync"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/sdk/golang/sdk"
"github.com/openziti/zrok/tui"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"net/url"
"os"
)

func init() {
rootCmd.AddCommand(newMdCommand().cmd)
}

type mdCommand struct {
cmd *cobra.Command
basicAuth string
}

func newMdCommand() *mdCommand {
cmd := &cobra.Command{
Use: "md <target>",
Short: "Make directory at <target> ('http://', 'zrok://', 'file://')",
Aliases: []string{"mkdir"},
Args: cobra.ExactArgs(1),
}
command := &mdCommand{cmd: cmd}
cmd.Run = command.run
cmd.Flags().StringVarP(&command.basicAuth, "basic-auth", "a", "", "Basic authentication <username:password>")
return command
}

func (cmd *mdCommand) run(_ *cobra.Command, args []string) {
if cmd.basicAuth == "" {
cmd.basicAuth = os.Getenv("ZROK_DRIVES_BASIC_AUTH")
}

targetUrl, err := url.Parse(args[0])
if err != nil {
tui.Error(fmt.Sprintf("invalid target '%v'", args[0]), err)
}
if targetUrl.Scheme == "" {
targetUrl.Scheme = "file"
}

root, err := environment.LoadRoot()
if err != nil {
tui.Error("error loading root", err)
}

if targetUrl.Scheme == "zrok" {
access, err := sdk.CreateAccess(root, &sdk.AccessRequest{ShareToken: targetUrl.Host})
if err != nil {
tui.Error("error creating access", err)
}
defer func() {
if err := sdk.DeleteAccess(root, access); err != nil {
logrus.Warningf("error freeing access: %v", err)
}
}()
}

target, err := sync.TargetForURL(targetUrl, root, cmd.basicAuth)
if err != nil {
tui.Error(fmt.Sprintf("error creating target for '%v'", targetUrl), err)
}

if err := target.Mkdir("/"); err != nil {
tui.Error("error creating directory", err)
}
}
Loading

1 comment on commit 8d88e32

@vercel
Copy link

@vercel vercel bot commented on 8d88e32 Jan 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

zrok – ./

zrok.vercel.app
zrok-openziti.vercel.app
zrok-git-main-openziti.vercel.app

Please sign in to comment.