From 2a89556693674b665334730dba1bccdf0f35a633 Mon Sep 17 00:00:00 2001 From: lixiaojun Date: Thu, 30 Aug 2018 20:55:37 +0800 Subject: [PATCH] first commit --- .gitignore | 1 + CHANGELOG.md | 4 + LICENSE | 202 + Makefile | 25 + README.md | 32 + cmd/completion.go | 281 + cmd/configure.go | 169 + cmd/eip.go | 206 + cmd/globalssh.go | 214 + cmd/list.go | 117 + cmd/root.go | 129 + cmd/signup.go | 57 + cmd/uhost.go | 55 + cmd/version.go | 35 + main.go | 23 + model/config.go | 190 + model/context.go | 34 + util/sdk.go | 84 + .../github.com/Sirupsen/logrus/CHANGELOG.md | 123 + vendor/github.com/Sirupsen/logrus/LICENSE | 21 + vendor/github.com/Sirupsen/logrus/README.md | 461 + vendor/github.com/Sirupsen/logrus/alt_exit.go | 64 + .../github.com/Sirupsen/logrus/appveyor.yml | 14 + vendor/github.com/Sirupsen/logrus/doc.go | 26 + vendor/github.com/Sirupsen/logrus/entry.go | 300 + vendor/github.com/Sirupsen/logrus/exported.go | 201 + .../github.com/Sirupsen/logrus/formatter.go | 51 + vendor/github.com/Sirupsen/logrus/hooks.go | 34 + .../Sirupsen/logrus/json_formatter.go | 96 + vendor/github.com/Sirupsen/logrus/logger.go | 338 + vendor/github.com/Sirupsen/logrus/logrus.go | 143 + .../Sirupsen/logrus/terminal_bsd.go | 10 + .../logrus/terminal_check_appengine.go | 11 + .../Sirupsen/logrus/terminal_check_js.go | 11 + .../logrus/terminal_check_notappengine.go | 19 + .../Sirupsen/logrus/terminal_linux.go | 14 + .../Sirupsen/logrus/text_formatter.go | 213 + vendor/github.com/Sirupsen/logrus/writer.go | 62 + .../inconshreveable/mousetrap/LICENSE | 13 + .../inconshreveable/mousetrap/README.md | 23 + .../inconshreveable/mousetrap/trap_others.go | 15 + .../inconshreveable/mousetrap/trap_windows.go | 98 + .../mousetrap/trap_windows_1.4.go | 46 + vendor/github.com/moul/http2curl/LICENSE | 22 + vendor/github.com/moul/http2curl/Makefile | 50 + vendor/github.com/moul/http2curl/README.md | 42 + vendor/github.com/moul/http2curl/http2curl.go | 71 + .../github.com/parnurzeal/gorequest/CHANGELOG | 123 + .../parnurzeal/gorequest/CONTRIBUTING.md | 73 + .../github.com/parnurzeal/gorequest/LICENSE | 20 + .../github.com/parnurzeal/gorequest/README.md | 328 + .../parnurzeal/gorequest/gorequest.go | 1238 +++ vendor/github.com/pkg/errors/LICENSE | 23 + vendor/github.com/pkg/errors/README.md | 52 + vendor/github.com/pkg/errors/appveyor.yml | 32 + vendor/github.com/pkg/errors/errors.go | 269 + vendor/github.com/pkg/errors/stack.go | 147 + vendor/github.com/satori/go.uuid/LICENSE | 20 + vendor/github.com/satori/go.uuid/README.md | 65 + vendor/github.com/satori/go.uuid/codec.go | 206 + vendor/github.com/satori/go.uuid/generator.go | 239 + vendor/github.com/satori/go.uuid/sql.go | 78 + vendor/github.com/satori/go.uuid/uuid.go | 161 + vendor/github.com/spf13/cobra/LICENSE.txt | 174 + vendor/github.com/spf13/cobra/README.md | 734 ++ vendor/github.com/spf13/cobra/args.go | 89 + .../spf13/cobra/bash_completions.go | 590 + .../spf13/cobra/bash_completions.md | 256 + vendor/github.com/spf13/cobra/cobra.go | 200 + vendor/github.com/spf13/cobra/command.go | 1517 +++ .../github.com/spf13/cobra/command_notwin.go | 5 + vendor/github.com/spf13/cobra/command_win.go | 20 + .../github.com/spf13/cobra/zsh_completions.go | 126 + vendor/github.com/spf13/pflag/LICENSE | 28 + vendor/github.com/spf13/pflag/README.md | 296 + vendor/github.com/spf13/pflag/bool.go | 94 + vendor/github.com/spf13/pflag/bool_slice.go | 147 + vendor/github.com/spf13/pflag/bytes.go | 209 + vendor/github.com/spf13/pflag/count.go | 96 + vendor/github.com/spf13/pflag/duration.go | 86 + .../github.com/spf13/pflag/duration_slice.go | 128 + vendor/github.com/spf13/pflag/flag.go | 1224 +++ vendor/github.com/spf13/pflag/float32.go | 88 + vendor/github.com/spf13/pflag/float64.go | 84 + vendor/github.com/spf13/pflag/golangflag.go | 105 + vendor/github.com/spf13/pflag/int.go | 84 + vendor/github.com/spf13/pflag/int16.go | 88 + vendor/github.com/spf13/pflag/int32.go | 88 + vendor/github.com/spf13/pflag/int64.go | 84 + vendor/github.com/spf13/pflag/int8.go | 88 + vendor/github.com/spf13/pflag/int_slice.go | 128 + vendor/github.com/spf13/pflag/ip.go | 94 + vendor/github.com/spf13/pflag/ip_slice.go | 148 + vendor/github.com/spf13/pflag/ipmask.go | 122 + vendor/github.com/spf13/pflag/ipnet.go | 98 + vendor/github.com/spf13/pflag/string.go | 80 + vendor/github.com/spf13/pflag/string_array.go | 103 + vendor/github.com/spf13/pflag/string_slice.go | 149 + .../github.com/spf13/pflag/string_to_int.go | 149 + .../spf13/pflag/string_to_string.go | 160 + vendor/github.com/spf13/pflag/uint.go | 88 + vendor/github.com/spf13/pflag/uint16.go | 88 + vendor/github.com/spf13/pflag/uint32.go | 88 + vendor/github.com/spf13/pflag/uint64.go | 88 + vendor/github.com/spf13/pflag/uint8.go | 88 + vendor/github.com/spf13/pflag/uint_slice.go | 126 + .../ucloud-sdk-go/sdk/auth/credential.go | 45 + .../ucloud/ucloud-sdk-go/sdk/client.go | 278 + .../ucloud/ucloud-sdk-go/sdk/config.go | 56 + .../ucloud/ucloud-sdk-go/sdk/defaults.go | 7 + .../ucloud-sdk-go/sdk/error/client_error.go | 11 + .../ucloud-sdk-go/sdk/error/server_error.go | 9 + .../ucloud/ucloud-sdk-go/sdk/log/logger.go | 13 + .../ucloud-sdk-go/sdk/request/common.go | 35 + .../ucloud-sdk-go/sdk/request/request.go | 17 + .../ucloud-sdk-go/sdk/response/common.go | 33 + .../ucloud-sdk-go/sdk/response/response.go | 5 + .../ucloud/ucloud-sdk-go/sdk/trace/das.go | 105 + .../ucloud/ucloud-sdk-go/sdk/trace/iface.go | 25 + .../ucloud/ucloud-sdk-go/sdk/trace/record.go | 88 + .../ucloud/ucloud-sdk-go/sdk/trace/stack.go | 24 + .../ucloud-sdk-go/sdk/utils/collection.go | 19 + .../ucloud/ucloud-sdk-go/sdk/utils/encoder.go | 153 + .../ucloud/ucloud-sdk-go/sdk/utils/request.go | 27 + .../ucloud/ucloud-sdk-go/sdk/utils/style.go | 35 + .../ucloud-sdk-go/sdk/utils/validator.go | 90 + .../ucloud/ucloud-sdk-go/sdk/utils/waiter.go | 53 + .../ucloud/ucloud-sdk-go/sdk/version.go | 5 + .../ucloud-sdk-go/sdk/version/version.go | 5 + .../ucloud/ucloud-sdk-go/service/client.go | 42 + .../ucloud-sdk-go/service/pathx/client.go | 17 + .../pathx/create_global_sshinstance.go | 68 + .../pathx/delete_global_sshinstance.go | 44 + .../pathx/describe_global_sshinstance.go | 48 + .../ucloud/ucloud-sdk-go/service/pathx/doc.go | 11 + .../service/pathx/modify_global_sshport.go | 47 + .../service/pathx/modify_global_sshremark.go | 47 + .../service/pathx/types/global_sshinfo.go | 32 + .../ucloud-sdk-go/service/uaccount/client.go | 17 + .../ucloud-sdk-go/service/uaccount/doc.go | 11 + .../service/uaccount/get_project_list.go | 51 + .../service/uaccount/get_region.go | 45 + .../service/uaccount/get_user_info.go | 45 + .../uaccount/types/project_list_info.go | 29 + .../service/uaccount/types/region_info.go | 23 + .../service/uaccount/types/user_info.go | 53 + .../ucloud-sdk-go/service/uhost/client.go | 17 + .../service/uhost/create_uhost_instance.go | 138 + .../service/uhost/describe_image.go | 69 + .../service/uhost/describe_uhost_instance.go | 63 + .../ucloud/ucloud-sdk-go/service/uhost/doc.go | 11 + .../ucloud-sdk-go/service/uhost/enums.go | 15 + .../service/uhost/stop_uhost_instance.go | 50 + .../service/uhost/terminate_uhost_instance.go | 56 + .../service/uhost/types/uhost_disk_set.go | 32 + .../service/uhost/types/uhost_image_set.go | 50 + .../service/uhost/types/uhost_instance_set.go | 95 + .../service/uhost/types/uhost_ipset.go | 20 + .../uhost/wait_until_uhost_instance_state.go | 66 + .../service/ulb/allocate_backend.go | 62 + .../ucloud-sdk-go/service/ulb/client.go | 17 + .../service/ulb/create_policy.go | 59 + .../ucloud-sdk-go/service/ulb/create_ulb.go | 71 + .../service/ulb/create_vserver.go | 71 + .../service/ulb/delete_policy.go | 50 + .../ucloud-sdk-go/service/ulb/delete_ulb.go | 44 + .../service/ulb/delete_vserver.go | 47 + .../ucloud-sdk-go/service/ulb/describe_ulb.go | 66 + .../service/ulb/describe_vserver.go | 54 + .../ucloud/ucloud-sdk-go/service/ulb/doc.go | 11 + .../service/ulb/release_backend.go | 47 + .../service/ulb/types/sslbinded_target_set.go | 17 + .../service/ulb/types/ulbbackend_set.go | 32 + .../service/ulb/types/ulbipset.go | 14 + .../ucloud-sdk-go/service/ulb/types/ulbset.go | 56 + .../service/ulb/types/ulbsslset.go | 11 + .../service/ulb/types/ulbvserver_set.go | 41 + .../service/ulb/update_vserver_attribute.go | 74 + .../service/unet/allocate_eip.go | 75 + .../ucloud-sdk-go/service/unet/bind_eip.go | 50 + .../ucloud-sdk-go/service/unet/client.go | 17 + .../service/unet/describe_eip.go | 60 + .../ucloud/ucloud-sdk-go/service/unet/doc.go | 11 + .../ucloud-sdk-go/service/unet/release_eip.go | 44 + .../service/unet/types/share_bandwidth_set.go | 14 + .../unet/types/unet_allocate_eipset.go | 11 + .../service/unet/types/unet_eipaddr_set.go | 11 + .../unet/types/unet_eipresource_set.go | 17 + .../service/unet/types/unet_eipset.go | 53 + .../ucloud-sdk-go/service/unet/un_bind_eip.go | 50 + .../service/vpc/add_vpcnetwork.go | 47 + .../ucloud-sdk-go/service/vpc/client.go | 17 + .../service/vpc/create_subnet.go | 62 + .../ucloud-sdk-go/service/vpc/create_vpc.go | 56 + .../service/vpc/create_vpcintercom.go | 53 + .../service/vpc/delete_subnet.go | 44 + .../ucloud-sdk-go/service/vpc/delete_vpc.go | 44 + .../service/vpc/delete_vpcintercom.go | 53 + .../service/vpc/describe_subnet.go | 69 + .../service/vpc/describe_subnet_resource.go | 60 + .../ucloud-sdk-go/service/vpc/describe_vpc.go | 51 + .../service/vpc/describe_vpcintercom.go | 68 + .../service/vpc/types/resource_info.go | 17 + .../service/vpc/types/vpcinfo_set.go | 29 + .../service/vpc/types/vpcsubnet_info_set.go | 50 + .../service/vpc/update_subnet_attribute.go | 50 + vendor/golang.org/x/crypto/LICENSE | 27 + vendor/golang.org/x/crypto/PATENTS | 22 + .../x/crypto/ssh/terminal/terminal.go | 951 ++ .../golang.org/x/crypto/ssh/terminal/util.go | 114 + .../x/crypto/ssh/terminal/util_bsd.go | 12 + .../x/crypto/ssh/terminal/util_linux.go | 10 + .../x/crypto/ssh/terminal/util_plan9.go | 58 + .../x/crypto/ssh/terminal/util_solaris.go | 124 + .../x/crypto/ssh/terminal/util_windows.go | 103 + vendor/golang.org/x/net/LICENSE | 27 + vendor/golang.org/x/net/PATENTS | 22 + vendor/golang.org/x/net/publicsuffix/list.go | 170 + vendor/golang.org/x/net/publicsuffix/table.go | 9748 +++++++++++++++++ vendor/golang.org/x/sys/LICENSE | 27 + vendor/golang.org/x/sys/PATENTS | 22 + vendor/golang.org/x/sys/unix/README.md | 173 + .../golang.org/x/sys/unix/affinity_linux.go | 124 + vendor/golang.org/x/sys/unix/aliases.go | 14 + vendor/golang.org/x/sys/unix/asm_darwin_386.s | 29 + .../golang.org/x/sys/unix/asm_darwin_amd64.s | 29 + vendor/golang.org/x/sys/unix/asm_darwin_arm.s | 30 + .../golang.org/x/sys/unix/asm_darwin_arm64.s | 30 + .../x/sys/unix/asm_dragonfly_amd64.s | 29 + .../golang.org/x/sys/unix/asm_freebsd_386.s | 29 + .../golang.org/x/sys/unix/asm_freebsd_amd64.s | 29 + .../golang.org/x/sys/unix/asm_freebsd_arm.s | 29 + vendor/golang.org/x/sys/unix/asm_linux_386.s | 65 + .../golang.org/x/sys/unix/asm_linux_amd64.s | 57 + vendor/golang.org/x/sys/unix/asm_linux_arm.s | 56 + .../golang.org/x/sys/unix/asm_linux_arm64.s | 52 + .../golang.org/x/sys/unix/asm_linux_mips64x.s | 56 + .../golang.org/x/sys/unix/asm_linux_mipsx.s | 54 + .../golang.org/x/sys/unix/asm_linux_ppc64x.s | 56 + .../golang.org/x/sys/unix/asm_linux_s390x.s | 56 + vendor/golang.org/x/sys/unix/asm_netbsd_386.s | 29 + .../golang.org/x/sys/unix/asm_netbsd_amd64.s | 29 + vendor/golang.org/x/sys/unix/asm_netbsd_arm.s | 29 + .../golang.org/x/sys/unix/asm_openbsd_386.s | 29 + .../golang.org/x/sys/unix/asm_openbsd_amd64.s | 29 + .../golang.org/x/sys/unix/asm_openbsd_arm.s | 29 + .../golang.org/x/sys/unix/asm_solaris_amd64.s | 17 + .../golang.org/x/sys/unix/bluetooth_linux.go | 35 + vendor/golang.org/x/sys/unix/cap_freebsd.go | 195 + vendor/golang.org/x/sys/unix/constants.go | 13 + vendor/golang.org/x/sys/unix/dev_darwin.go | 24 + vendor/golang.org/x/sys/unix/dev_dragonfly.go | 30 + vendor/golang.org/x/sys/unix/dev_freebsd.go | 30 + vendor/golang.org/x/sys/unix/dev_linux.go | 42 + vendor/golang.org/x/sys/unix/dev_netbsd.go | 29 + vendor/golang.org/x/sys/unix/dev_openbsd.go | 29 + vendor/golang.org/x/sys/unix/dirent.go | 17 + vendor/golang.org/x/sys/unix/endian_big.go | 9 + vendor/golang.org/x/sys/unix/endian_little.go | 9 + vendor/golang.org/x/sys/unix/env_unix.go | 31 + .../x/sys/unix/errors_freebsd_386.go | 227 + .../x/sys/unix/errors_freebsd_amd64.go | 227 + .../x/sys/unix/errors_freebsd_arm.go | 226 + vendor/golang.org/x/sys/unix/fcntl.go | 32 + .../x/sys/unix/fcntl_linux_32bit.go | 13 + vendor/golang.org/x/sys/unix/gccgo.go | 61 + vendor/golang.org/x/sys/unix/gccgo_c.c | 38 + .../x/sys/unix/gccgo_linux_amd64.go | 20 + vendor/golang.org/x/sys/unix/ioctl.go | 30 + vendor/golang.org/x/sys/unix/mkall.sh | 188 + vendor/golang.org/x/sys/unix/mkerrors.sh | 611 ++ vendor/golang.org/x/sys/unix/mksyscall.pl | 341 + .../x/sys/unix/mksyscall_solaris.pl | 289 + .../golang.org/x/sys/unix/mksysctl_openbsd.pl | 264 + .../golang.org/x/sys/unix/mksysnum_darwin.pl | 39 + .../x/sys/unix/mksysnum_dragonfly.pl | 50 + .../golang.org/x/sys/unix/mksysnum_freebsd.pl | 50 + .../golang.org/x/sys/unix/mksysnum_netbsd.pl | 58 + .../golang.org/x/sys/unix/mksysnum_openbsd.pl | 50 + .../golang.org/x/sys/unix/openbsd_pledge.go | 95 + vendor/golang.org/x/sys/unix/pagesize_unix.go | 15 + vendor/golang.org/x/sys/unix/race.go | 30 + vendor/golang.org/x/sys/unix/race0.go | 25 + .../golang.org/x/sys/unix/sockcmsg_linux.go | 36 + vendor/golang.org/x/sys/unix/sockcmsg_unix.go | 104 + vendor/golang.org/x/sys/unix/str.go | 26 + vendor/golang.org/x/sys/unix/syscall.go | 54 + vendor/golang.org/x/sys/unix/syscall_bsd.go | 624 ++ .../golang.org/x/sys/unix/syscall_darwin.go | 700 ++ .../x/sys/unix/syscall_darwin_386.go | 68 + .../x/sys/unix/syscall_darwin_amd64.go | 68 + .../x/sys/unix/syscall_darwin_arm.go | 66 + .../x/sys/unix/syscall_darwin_arm64.go | 68 + .../x/sys/unix/syscall_dragonfly.go | 523 + .../x/sys/unix/syscall_dragonfly_amd64.go | 52 + .../golang.org/x/sys/unix/syscall_freebsd.go | 528 + .../x/sys/unix/syscall_freebsd_386.go | 52 + .../x/sys/unix/syscall_freebsd_amd64.go | 52 + .../x/sys/unix/syscall_freebsd_arm.go | 52 + vendor/golang.org/x/sys/unix/syscall_linux.go | 1600 +++ .../x/sys/unix/syscall_linux_386.go | 385 + .../x/sys/unix/syscall_linux_amd64.go | 162 + .../x/sys/unix/syscall_linux_amd64_gc.go | 13 + .../x/sys/unix/syscall_linux_arm.go | 259 + .../x/sys/unix/syscall_linux_arm64.go | 212 + .../golang.org/x/sys/unix/syscall_linux_gc.go | 14 + .../x/sys/unix/syscall_linux_gc_386.go | 16 + .../x/sys/unix/syscall_linux_gccgo_386.go | 30 + .../x/sys/unix/syscall_linux_gccgo_arm.go | 20 + .../x/sys/unix/syscall_linux_mips64x.go | 214 + .../x/sys/unix/syscall_linux_mipsx.go | 233 + .../x/sys/unix/syscall_linux_ppc64x.go | 131 + .../x/sys/unix/syscall_linux_s390x.go | 324 + .../x/sys/unix/syscall_linux_sparc64.go | 146 + .../golang.org/x/sys/unix/syscall_netbsd.go | 580 + .../x/sys/unix/syscall_netbsd_386.go | 33 + .../x/sys/unix/syscall_netbsd_amd64.go | 33 + .../x/sys/unix/syscall_netbsd_arm.go | 33 + .../golang.org/x/sys/unix/syscall_openbsd.go | 368 + .../x/sys/unix/syscall_openbsd_386.go | 33 + .../x/sys/unix/syscall_openbsd_amd64.go | 37 + .../x/sys/unix/syscall_openbsd_arm.go | 33 + .../golang.org/x/sys/unix/syscall_solaris.go | 730 ++ .../x/sys/unix/syscall_solaris_amd64.go | 23 + vendor/golang.org/x/sys/unix/syscall_unix.go | 394 + .../golang.org/x/sys/unix/syscall_unix_gc.go | 15 + vendor/golang.org/x/sys/unix/timestruct.go | 82 + vendor/golang.org/x/sys/unix/xattr_bsd.go | 231 + .../x/sys/unix/zerrors_darwin_386.go | 1783 +++ .../x/sys/unix/zerrors_darwin_amd64.go | 1783 +++ .../x/sys/unix/zerrors_darwin_arm.go | 1783 +++ .../x/sys/unix/zerrors_darwin_arm64.go | 1783 +++ .../x/sys/unix/zerrors_dragonfly_amd64.go | 1616 +++ .../x/sys/unix/zerrors_freebsd_386.go | 1793 +++ .../x/sys/unix/zerrors_freebsd_amd64.go | 1794 +++ .../x/sys/unix/zerrors_freebsd_arm.go | 1802 +++ .../x/sys/unix/zerrors_linux_386.go | 2620 +++++ .../x/sys/unix/zerrors_linux_amd64.go | 2620 +++++ .../x/sys/unix/zerrors_linux_arm.go | 2626 +++++ .../x/sys/unix/zerrors_linux_arm64.go | 2611 +++++ .../x/sys/unix/zerrors_linux_mips.go | 2627 +++++ .../x/sys/unix/zerrors_linux_mips64.go | 2627 +++++ .../x/sys/unix/zerrors_linux_mips64le.go | 2627 +++++ .../x/sys/unix/zerrors_linux_mipsle.go | 2627 +++++ .../x/sys/unix/zerrors_linux_ppc64.go | 2680 +++++ .../x/sys/unix/zerrors_linux_ppc64le.go | 2680 +++++ .../x/sys/unix/zerrors_linux_s390x.go | 2680 +++++ .../x/sys/unix/zerrors_linux_sparc64.go | 2142 ++++ .../x/sys/unix/zerrors_netbsd_386.go | 1732 +++ .../x/sys/unix/zerrors_netbsd_amd64.go | 1722 +++ .../x/sys/unix/zerrors_netbsd_arm.go | 1711 +++ .../x/sys/unix/zerrors_openbsd_386.go | 1628 +++ .../x/sys/unix/zerrors_openbsd_amd64.go | 1735 +++ .../x/sys/unix/zerrors_openbsd_arm.go | 1630 +++ .../x/sys/unix/zerrors_solaris_amd64.go | 1532 +++ .../golang.org/x/sys/unix/zptrace386_linux.go | 80 + .../golang.org/x/sys/unix/zptracearm_linux.go | 41 + .../x/sys/unix/zptracemips_linux.go | 50 + .../x/sys/unix/zptracemipsle_linux.go | 50 + .../x/sys/unix/zsyscall_darwin_386.go | 1769 +++ .../x/sys/unix/zsyscall_darwin_amd64.go | 1769 +++ .../x/sys/unix/zsyscall_darwin_arm.go | 1769 +++ .../x/sys/unix/zsyscall_darwin_arm64.go | 1769 +++ .../x/sys/unix/zsyscall_dragonfly_amd64.go | 1508 +++ .../x/sys/unix/zsyscall_freebsd_386.go | 1937 ++++ .../x/sys/unix/zsyscall_freebsd_amd64.go | 1937 ++++ .../x/sys/unix/zsyscall_freebsd_arm.go | 1937 ++++ .../x/sys/unix/zsyscall_linux_386.go | 2105 ++++ .../x/sys/unix/zsyscall_linux_amd64.go | 2272 ++++ .../x/sys/unix/zsyscall_linux_arm.go | 2207 ++++ .../x/sys/unix/zsyscall_linux_arm64.go | 2114 ++++ .../x/sys/unix/zsyscall_linux_mips.go | 2285 ++++ .../x/sys/unix/zsyscall_linux_mips64.go | 2256 ++++ .../x/sys/unix/zsyscall_linux_mips64le.go | 2256 ++++ .../x/sys/unix/zsyscall_linux_mipsle.go | 2285 ++++ .../x/sys/unix/zsyscall_linux_ppc64.go | 2319 ++++ .../x/sys/unix/zsyscall_linux_ppc64le.go | 2319 ++++ .../x/sys/unix/zsyscall_linux_s390x.go | 2089 ++++ .../x/sys/unix/zsyscall_linux_sparc64.go | 2172 ++++ .../x/sys/unix/zsyscall_netbsd_386.go | 1653 +++ .../x/sys/unix/zsyscall_netbsd_amd64.go | 1653 +++ .../x/sys/unix/zsyscall_netbsd_arm.go | 1653 +++ .../x/sys/unix/zsyscall_openbsd_386.go | 1508 +++ .../x/sys/unix/zsyscall_openbsd_amd64.go | 1508 +++ .../x/sys/unix/zsyscall_openbsd_arm.go | 1508 +++ .../x/sys/unix/zsyscall_solaris_amd64.go | 1697 +++ .../x/sys/unix/zsysctl_openbsd_386.go | 270 + .../x/sys/unix/zsysctl_openbsd_amd64.go | 257 + .../x/sys/unix/zsysctl_openbsd_arm.go | 270 + .../x/sys/unix/zsysnum_darwin_386.go | 436 + .../x/sys/unix/zsysnum_darwin_amd64.go | 436 + .../x/sys/unix/zsysnum_darwin_arm.go | 436 + .../x/sys/unix/zsysnum_darwin_arm64.go | 436 + .../x/sys/unix/zsysnum_dragonfly_amd64.go | 315 + .../x/sys/unix/zsysnum_freebsd_386.go | 403 + .../x/sys/unix/zsysnum_freebsd_amd64.go | 403 + .../x/sys/unix/zsysnum_freebsd_arm.go | 403 + .../x/sys/unix/zsysnum_linux_386.go | 392 + .../x/sys/unix/zsysnum_linux_amd64.go | 344 + .../x/sys/unix/zsysnum_linux_arm.go | 363 + .../x/sys/unix/zsysnum_linux_arm64.go | 287 + .../x/sys/unix/zsysnum_linux_mips.go | 377 + .../x/sys/unix/zsysnum_linux_mips64.go | 337 + .../x/sys/unix/zsysnum_linux_mips64le.go | 337 + .../x/sys/unix/zsysnum_linux_mipsle.go | 377 + .../x/sys/unix/zsysnum_linux_ppc64.go | 375 + .../x/sys/unix/zsysnum_linux_ppc64le.go | 375 + .../x/sys/unix/zsysnum_linux_s390x.go | 337 + .../x/sys/unix/zsysnum_linux_sparc64.go | 348 + .../x/sys/unix/zsysnum_netbsd_386.go | 274 + .../x/sys/unix/zsysnum_netbsd_amd64.go | 274 + .../x/sys/unix/zsysnum_netbsd_arm.go | 274 + .../x/sys/unix/zsysnum_openbsd_386.go | 207 + .../x/sys/unix/zsysnum_openbsd_amd64.go | 218 + .../x/sys/unix/zsysnum_openbsd_arm.go | 213 + .../x/sys/unix/ztypes_darwin_386.go | 489 + .../x/sys/unix/ztypes_darwin_amd64.go | 499 + .../x/sys/unix/ztypes_darwin_arm.go | 490 + .../x/sys/unix/ztypes_darwin_arm64.go | 499 + .../x/sys/unix/ztypes_dragonfly_amd64.go | 469 + .../x/sys/unix/ztypes_freebsd_386.go | 536 + .../x/sys/unix/ztypes_freebsd_amd64.go | 539 + .../x/sys/unix/ztypes_freebsd_arm.go | 539 + .../golang.org/x/sys/unix/ztypes_linux_386.go | 1884 ++++ .../x/sys/unix/ztypes_linux_amd64.go | 1906 ++++ .../golang.org/x/sys/unix/ztypes_linux_arm.go | 1874 ++++ .../x/sys/unix/ztypes_linux_arm64.go | 1885 ++++ .../x/sys/unix/ztypes_linux_mips.go | 1879 ++++ .../x/sys/unix/ztypes_linux_mips64.go | 1887 ++++ .../x/sys/unix/ztypes_linux_mips64le.go | 1887 ++++ .../x/sys/unix/ztypes_linux_mipsle.go | 1879 ++++ .../x/sys/unix/ztypes_linux_ppc64.go | 1895 ++++ .../x/sys/unix/ztypes_linux_ppc64le.go | 1895 ++++ .../x/sys/unix/ztypes_linux_s390x.go | 1912 ++++ .../x/sys/unix/ztypes_linux_sparc64.go | 690 ++ .../x/sys/unix/ztypes_netbsd_386.go | 448 + .../x/sys/unix/ztypes_netbsd_amd64.go | 455 + .../x/sys/unix/ztypes_netbsd_arm.go | 453 + .../x/sys/unix/ztypes_openbsd_386.go | 467 + .../x/sys/unix/ztypes_openbsd_amd64.go | 467 + .../x/sys/unix/ztypes_openbsd_arm.go | 460 + .../x/sys/unix/ztypes_solaris_amd64.go | 442 + vendor/golang.org/x/sys/windows/aliases.go | 13 + .../x/sys/windows/asm_windows_386.s | 13 + .../x/sys/windows/asm_windows_amd64.s | 13 + .../golang.org/x/sys/windows/dll_windows.go | 378 + .../golang.org/x/sys/windows/env_windows.go | 29 + vendor/golang.org/x/sys/windows/eventlog.go | 20 + .../golang.org/x/sys/windows/exec_windows.go | 97 + .../x/sys/windows/memory_windows.go | 26 + vendor/golang.org/x/sys/windows/mksyscall.go | 7 + vendor/golang.org/x/sys/windows/race.go | 30 + vendor/golang.org/x/sys/windows/race0.go | 25 + .../x/sys/windows/security_windows.go | 478 + vendor/golang.org/x/sys/windows/service.go | 183 + vendor/golang.org/x/sys/windows/str.go | 22 + vendor/golang.org/x/sys/windows/syscall.go | 74 + .../x/sys/windows/syscall_windows.go | 1155 ++ .../golang.org/x/sys/windows/types_windows.go | 1467 +++ .../x/sys/windows/types_windows_386.go | 22 + .../x/sys/windows/types_windows_amd64.go | 22 + .../x/sys/windows/zsyscall_windows.go | 2700 +++++ vendor/vendor.json | 213 + 463 files changed, 201035 insertions(+) create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 cmd/completion.go create mode 100644 cmd/configure.go create mode 100644 cmd/eip.go create mode 100644 cmd/globalssh.go create mode 100644 cmd/list.go create mode 100644 cmd/root.go create mode 100644 cmd/signup.go create mode 100644 cmd/uhost.go create mode 100644 cmd/version.go create mode 100644 main.go create mode 100644 model/config.go create mode 100644 model/context.go create mode 100644 util/sdk.go create mode 100644 vendor/github.com/Sirupsen/logrus/CHANGELOG.md create mode 100644 vendor/github.com/Sirupsen/logrus/LICENSE create mode 100644 vendor/github.com/Sirupsen/logrus/README.md create mode 100644 vendor/github.com/Sirupsen/logrus/alt_exit.go create mode 100644 vendor/github.com/Sirupsen/logrus/appveyor.yml create mode 100644 vendor/github.com/Sirupsen/logrus/doc.go create mode 100644 vendor/github.com/Sirupsen/logrus/entry.go create mode 100644 vendor/github.com/Sirupsen/logrus/exported.go create mode 100644 vendor/github.com/Sirupsen/logrus/formatter.go create mode 100644 vendor/github.com/Sirupsen/logrus/hooks.go create mode 100644 vendor/github.com/Sirupsen/logrus/json_formatter.go create mode 100644 vendor/github.com/Sirupsen/logrus/logger.go create mode 100644 vendor/github.com/Sirupsen/logrus/logrus.go create mode 100644 vendor/github.com/Sirupsen/logrus/terminal_bsd.go create mode 100644 vendor/github.com/Sirupsen/logrus/terminal_check_appengine.go create mode 100644 vendor/github.com/Sirupsen/logrus/terminal_check_js.go create mode 100644 vendor/github.com/Sirupsen/logrus/terminal_check_notappengine.go create mode 100644 vendor/github.com/Sirupsen/logrus/terminal_linux.go create mode 100644 vendor/github.com/Sirupsen/logrus/text_formatter.go create mode 100644 vendor/github.com/Sirupsen/logrus/writer.go create mode 100644 vendor/github.com/inconshreveable/mousetrap/LICENSE create mode 100644 vendor/github.com/inconshreveable/mousetrap/README.md create mode 100644 vendor/github.com/inconshreveable/mousetrap/trap_others.go create mode 100644 vendor/github.com/inconshreveable/mousetrap/trap_windows.go create mode 100644 vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go create mode 100644 vendor/github.com/moul/http2curl/LICENSE create mode 100644 vendor/github.com/moul/http2curl/Makefile create mode 100644 vendor/github.com/moul/http2curl/README.md create mode 100644 vendor/github.com/moul/http2curl/http2curl.go create mode 100644 vendor/github.com/parnurzeal/gorequest/CHANGELOG create mode 100644 vendor/github.com/parnurzeal/gorequest/CONTRIBUTING.md create mode 100644 vendor/github.com/parnurzeal/gorequest/LICENSE create mode 100644 vendor/github.com/parnurzeal/gorequest/README.md create mode 100644 vendor/github.com/parnurzeal/gorequest/gorequest.go create mode 100644 vendor/github.com/pkg/errors/LICENSE create mode 100644 vendor/github.com/pkg/errors/README.md create mode 100644 vendor/github.com/pkg/errors/appveyor.yml create mode 100644 vendor/github.com/pkg/errors/errors.go create mode 100644 vendor/github.com/pkg/errors/stack.go create mode 100644 vendor/github.com/satori/go.uuid/LICENSE create mode 100644 vendor/github.com/satori/go.uuid/README.md create mode 100644 vendor/github.com/satori/go.uuid/codec.go create mode 100644 vendor/github.com/satori/go.uuid/generator.go create mode 100644 vendor/github.com/satori/go.uuid/sql.go create mode 100644 vendor/github.com/satori/go.uuid/uuid.go create mode 100644 vendor/github.com/spf13/cobra/LICENSE.txt create mode 100644 vendor/github.com/spf13/cobra/README.md create mode 100644 vendor/github.com/spf13/cobra/args.go create mode 100644 vendor/github.com/spf13/cobra/bash_completions.go create mode 100644 vendor/github.com/spf13/cobra/bash_completions.md create mode 100644 vendor/github.com/spf13/cobra/cobra.go create mode 100644 vendor/github.com/spf13/cobra/command.go create mode 100644 vendor/github.com/spf13/cobra/command_notwin.go create mode 100644 vendor/github.com/spf13/cobra/command_win.go create mode 100644 vendor/github.com/spf13/cobra/zsh_completions.go create mode 100644 vendor/github.com/spf13/pflag/LICENSE create mode 100644 vendor/github.com/spf13/pflag/README.md create mode 100644 vendor/github.com/spf13/pflag/bool.go create mode 100644 vendor/github.com/spf13/pflag/bool_slice.go create mode 100644 vendor/github.com/spf13/pflag/bytes.go create mode 100644 vendor/github.com/spf13/pflag/count.go create mode 100644 vendor/github.com/spf13/pflag/duration.go create mode 100644 vendor/github.com/spf13/pflag/duration_slice.go create mode 100644 vendor/github.com/spf13/pflag/flag.go create mode 100644 vendor/github.com/spf13/pflag/float32.go create mode 100644 vendor/github.com/spf13/pflag/float64.go create mode 100644 vendor/github.com/spf13/pflag/golangflag.go create mode 100644 vendor/github.com/spf13/pflag/int.go create mode 100644 vendor/github.com/spf13/pflag/int16.go create mode 100644 vendor/github.com/spf13/pflag/int32.go create mode 100644 vendor/github.com/spf13/pflag/int64.go create mode 100644 vendor/github.com/spf13/pflag/int8.go create mode 100644 vendor/github.com/spf13/pflag/int_slice.go create mode 100644 vendor/github.com/spf13/pflag/ip.go create mode 100644 vendor/github.com/spf13/pflag/ip_slice.go create mode 100644 vendor/github.com/spf13/pflag/ipmask.go create mode 100644 vendor/github.com/spf13/pflag/ipnet.go create mode 100644 vendor/github.com/spf13/pflag/string.go create mode 100644 vendor/github.com/spf13/pflag/string_array.go create mode 100644 vendor/github.com/spf13/pflag/string_slice.go create mode 100644 vendor/github.com/spf13/pflag/string_to_int.go create mode 100644 vendor/github.com/spf13/pflag/string_to_string.go create mode 100644 vendor/github.com/spf13/pflag/uint.go create mode 100644 vendor/github.com/spf13/pflag/uint16.go create mode 100644 vendor/github.com/spf13/pflag/uint32.go create mode 100644 vendor/github.com/spf13/pflag/uint64.go create mode 100644 vendor/github.com/spf13/pflag/uint8.go create mode 100644 vendor/github.com/spf13/pflag/uint_slice.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/auth/credential.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/client.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/config.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/defaults.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/error/client_error.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/error/server_error.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/log/logger.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/request/common.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/request/request.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/response/common.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/response/response.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/das.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/iface.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/record.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/stack.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/collection.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/encoder.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/request.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/style.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/validator.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/waiter.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/version.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/sdk/version/version.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/client.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/client.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/create_global_sshinstance.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/delete_global_sshinstance.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/describe_global_sshinstance.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/doc.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/modify_global_sshport.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/modify_global_sshremark.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/types/global_sshinfo.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/client.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/doc.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/get_project_list.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/get_region.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/get_user_info.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/types/project_list_info.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/types/region_info.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/types/user_info.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/client.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/create_uhost_instance.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/describe_image.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/describe_uhost_instance.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/doc.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/enums.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/stop_uhost_instance.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/terminate_uhost_instance.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_disk_set.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_image_set.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_instance_set.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_ipset.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/wait_until_uhost_instance_state.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/allocate_backend.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/client.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/create_policy.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/create_ulb.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/create_vserver.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/delete_policy.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/delete_ulb.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/delete_vserver.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/describe_ulb.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/describe_vserver.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/doc.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/release_backend.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/sslbinded_target_set.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbbackend_set.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbipset.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbset.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbsslset.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbvserver_set.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/update_vserver_attribute.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/unet/allocate_eip.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/unet/bind_eip.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/unet/client.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/unet/describe_eip.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/unet/doc.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/unet/release_eip.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/share_bandwidth_set.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_allocate_eipset.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_eipaddr_set.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_eipresource_set.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_eipset.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/unet/un_bind_eip.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/add_vpcnetwork.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/client.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/create_subnet.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/create_vpc.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/create_vpcintercom.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/delete_subnet.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/delete_vpc.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/delete_vpcintercom.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_subnet.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_subnet_resource.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_vpc.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_vpcintercom.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/types/resource_info.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/types/vpcinfo_set.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/types/vpcsubnet_info_set.go create mode 100644 vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/update_subnet_attribute.go create mode 100644 vendor/golang.org/x/crypto/LICENSE create mode 100644 vendor/golang.org/x/crypto/PATENTS create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/terminal.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_linux.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go create mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_windows.go create mode 100644 vendor/golang.org/x/net/LICENSE create mode 100644 vendor/golang.org/x/net/PATENTS create mode 100644 vendor/golang.org/x/net/publicsuffix/list.go create mode 100644 vendor/golang.org/x/net/publicsuffix/table.go create mode 100644 vendor/golang.org/x/sys/LICENSE create mode 100644 vendor/golang.org/x/sys/PATENTS create mode 100644 vendor/golang.org/x/sys/unix/README.md create mode 100644 vendor/golang.org/x/sys/unix/affinity_linux.go create mode 100644 vendor/golang.org/x/sys/unix/aliases.go create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_darwin_arm64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_freebsd_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_arm64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_mips64x.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_mipsx.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s create mode 100644 vendor/golang.org/x/sys/unix/asm_linux_s390x.s create mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_netbsd_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_386.s create mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/asm_openbsd_arm.s create mode 100644 vendor/golang.org/x/sys/unix/asm_solaris_amd64.s create mode 100644 vendor/golang.org/x/sys/unix/bluetooth_linux.go create mode 100644 vendor/golang.org/x/sys/unix/cap_freebsd.go create mode 100644 vendor/golang.org/x/sys/unix/constants.go create mode 100644 vendor/golang.org/x/sys/unix/dev_darwin.go create mode 100644 vendor/golang.org/x/sys/unix/dev_dragonfly.go create mode 100644 vendor/golang.org/x/sys/unix/dev_freebsd.go create mode 100644 vendor/golang.org/x/sys/unix/dev_linux.go create mode 100644 vendor/golang.org/x/sys/unix/dev_netbsd.go create mode 100644 vendor/golang.org/x/sys/unix/dev_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/dirent.go create mode 100644 vendor/golang.org/x/sys/unix/endian_big.go create mode 100644 vendor/golang.org/x/sys/unix/endian_little.go create mode 100644 vendor/golang.org/x/sys/unix/env_unix.go create mode 100644 vendor/golang.org/x/sys/unix/errors_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/errors_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/errors_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/fcntl.go create mode 100644 vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go create mode 100644 vendor/golang.org/x/sys/unix/gccgo.go create mode 100644 vendor/golang.org/x/sys/unix/gccgo_c.c create mode 100644 vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ioctl.go create mode 100755 vendor/golang.org/x/sys/unix/mkall.sh create mode 100755 vendor/golang.org/x/sys/unix/mkerrors.sh create mode 100755 vendor/golang.org/x/sys/unix/mksyscall.pl create mode 100755 vendor/golang.org/x/sys/unix/mksyscall_solaris.pl create mode 100755 vendor/golang.org/x/sys/unix/mksysctl_openbsd.pl create mode 100755 vendor/golang.org/x/sys/unix/mksysnum_darwin.pl create mode 100755 vendor/golang.org/x/sys/unix/mksysnum_dragonfly.pl create mode 100755 vendor/golang.org/x/sys/unix/mksysnum_freebsd.pl create mode 100755 vendor/golang.org/x/sys/unix/mksysnum_netbsd.pl create mode 100755 vendor/golang.org/x/sys/unix/mksysnum_openbsd.pl create mode 100644 vendor/golang.org/x/sys/unix/openbsd_pledge.go create mode 100644 vendor/golang.org/x/sys/unix/pagesize_unix.go create mode 100644 vendor/golang.org/x/sys/unix/race.go create mode 100644 vendor/golang.org/x/sys/unix/race0.go create mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_linux.go create mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_unix.go create mode 100644 vendor/golang.org/x/sys/unix/str.go create mode 100644 vendor/golang.org/x/sys/unix/syscall.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_bsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_dragonfly.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_amd64_gc.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_gc.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_gc_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_gccgo_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_gccgo_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_mipsx.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_linux_sparc64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_solaris.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_unix.go create mode 100644 vendor/golang.org/x/sys/unix/syscall_unix_gc.go create mode 100644 vendor/golang.org/x/sys/unix/timestruct.go create mode 100644 vendor/golang.org/x/sys/unix/xattr_bsd.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_mips.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zptrace386_linux.go create mode 100644 vendor/golang.org/x/sys/unix/zptracearm_linux.go create mode 100644 vendor/golang.org/x/sys/unix/zptracemips_linux.go create mode 100644 vendor/golang.org/x/sys/unix/zptracemipsle_linux.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_mips.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_linux_sparc64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysctl_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysctl_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysctl_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/zsysnum_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_mips.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_netbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go create mode 100644 vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go create mode 100644 vendor/golang.org/x/sys/windows/aliases.go create mode 100644 vendor/golang.org/x/sys/windows/asm_windows_386.s create mode 100644 vendor/golang.org/x/sys/windows/asm_windows_amd64.s create mode 100644 vendor/golang.org/x/sys/windows/dll_windows.go create mode 100644 vendor/golang.org/x/sys/windows/env_windows.go create mode 100644 vendor/golang.org/x/sys/windows/eventlog.go create mode 100644 vendor/golang.org/x/sys/windows/exec_windows.go create mode 100644 vendor/golang.org/x/sys/windows/memory_windows.go create mode 100644 vendor/golang.org/x/sys/windows/mksyscall.go create mode 100644 vendor/golang.org/x/sys/windows/race.go create mode 100644 vendor/golang.org/x/sys/windows/race0.go create mode 100644 vendor/golang.org/x/sys/windows/security_windows.go create mode 100644 vendor/golang.org/x/sys/windows/service.go create mode 100644 vendor/golang.org/x/sys/windows/str.go create mode 100644 vendor/golang.org/x/sys/windows/syscall.go create mode 100644 vendor/golang.org/x/sys/windows/syscall_windows.go create mode 100644 vendor/golang.org/x/sys/windows/types_windows.go create mode 100644 vendor/golang.org/x/sys/windows/types_windows_386.go create mode 100644 vendor/golang.org/x/sys/windows/types_windows_amd64.go create mode 100644 vendor/golang.org/x/sys/windows/zsyscall_windows.go create mode 100644 vendor/vendor.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..1fcb1529f8 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +out diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..ca5856194b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4 @@ +## Change Log + +v0.1.1 +* UHost list; EIP list,delete and allocate; GlobalSSH list,delete,modify and create. \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..5589a38a5d --- /dev/null +++ b/Makefile @@ -0,0 +1,25 @@ +export VERSION=0.1.1 + +.PHONY : build +build: + go install && mv ../../../../bin/ucloud-cli ../../../../bin/ucloud + +.PHONY : build_mac +build_mac: + GOOS=darwin GOARCH=amd64 go build -o out/ucloud main.go + tar zcvf out/ucloud-cli-macosx-${VERSION}-amd64.tgz -C out ucloud + +.PHONY : build_linux +build_linux: + GOOS=linux GOARCH=amd64 go build -o out/ucloud main.go + tar zcvf out/ucloud-cli-linux-${VERSION}-amd64.tgz -C out ucloud + +.PHONY : build_windows +build_windows: + GOOS=windows GOARCH=amd64 go build -o out/ucloud.exe main.go + zip -r out/ucloud-cli-windows-${VERSION}-amd64.zip out/ucloud.exe + +.PHONY : install +install: + go build -o out/ucloud main.go + cp out/ucloud /usr/local/bin diff --git a/README.md b/README.md new file mode 100644 index 0000000000..9213980d96 --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +## UCloud Command Line Interface + +The UCloud Command Line Interface is a tool to manage your UCloud services. It's built on the [UCloud API](https://docs.ucloud.cn/api/summary/index). + + +### Install UCloud CLI: + +You can install UCloud CLI by downloading executable binary file or building from the source code by yourself. + +* Download binary file: +[Mac](https://github.com/ucloud/ucloud-cli/releases/download/v0.1.1/ucloud-cli-darwin-amd64.tar.gz) [Linux](https://github.com/ucloud/ucloud-cli/releases/download/v0.1.1/ucloud-cli-linux-amd64.tar.gz) +[Windows](https://github.com/ucloud/ucloud-cli/releases/download/v0.1.1/ucloud-cli-windows-amd64.exe.zip) + +Download the binary file and extract to /usr/local/bin directory or add it to the $PATH + +* Build from source code + +If you have installed golang, run the following commands to install the UCloud CLI. + +``` +$ mkdir -p $GOPATH/src/github.com/ucloud +$ cd $GOPATH/src/github.com/ucloud +$ git clone http://github.com/ucloud/ucloud-cli.git +$ cd ucloud-cli +$ make install +``` + +###Config UCloud CLI + +After install the cli, run 'ucloud config' to complete the cli configuration following the tips. + + diff --git a/cmd/completion.go b/cmd/completion.go new file mode 100644 index 0000000000..93eb1ba05c --- /dev/null +++ b/cmd/completion.go @@ -0,0 +1,281 @@ +// Copyright © 2018 NAME HERE tony.li@ucloud.cn +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "bytes" + "fmt" + "io" + "os" + "strings" + + "github.com/spf13/cobra" + "github.com/ucloud/ucloud-cli/util" +) + +// NewCmdCompletion ucloud completion +func NewCmdCompletion() *cobra.Command { + var desc = `Description: + On macOS, using bash + + On macOS, you will need to install bash-completion support via Homebrew first: + If running Bash 3.2 included with macOS + > brew install bash-completion + or, if running Bash 4.1+ + > brew install bash-completion@2 + Follow the “caveats” section of brew’s output to add the appropriate bash completion path to your local .bash_profile. + and then generate bash completion scripts for ucloud + > ucloud completion + + On Linux, using bash + + On CentOS Linux, you may need to install the bash-completion package which is not installed by default. + > yum install bash-completion -y + and then genreate bash completion scripts for ucloud + > ucloud completion + + Using zsh + > ucloud completion + + Restart session after auto completion +` + var completionCmd = &cobra.Command{ + Use: "completion", + Short: "Generates bash/zsh completion scripts", + Long: desc, + Run: func(cmd *cobra.Command, args []string) { + shell, ok := os.LookupEnv("SHELL") + if ok { + if strings.HasSuffix(shell, "bash") { + bashCompletion(cmd.Parent()) + } else if strings.HasSuffix(shell, "zsh") { + zshCompletion(cmd.Parent()) + } else { + fmt.Println("Unknow shell: %", shell) + } + } else { + fmt.Println("Lookup shell failed") + } + }, + } + return completionCmd +} + +func bashCompletion(cmd *cobra.Command) { + home := util.GetHomePath() + shellPath := home + "/" + util.ConfigPath + "/ucloud.sh" + cmd.GenBashCompletionFile(shellPath) + for _, rc := range [...]string{".bashrc", ".bash_profile", ".bash_login", ".profile"} { + rcPath := home + "/" + rc + if _, err := os.Stat(rcPath); err == nil { + cmd := "source " + shellPath + if util.LineInFile(rcPath, cmd) == false { + util.AppendToFile(rcPath, cmd) + fmt.Println("Auto completion is on. Please install bash-completion on your platform using brew,yum or apt-get. ucloud completion --help for more information") + } else { + fmt.Println("Auto completion update. Restart session") + } + } + } +} + +func zshCompletion(cmd *cobra.Command) { + home := util.GetHomePath() + shellPath := home + "/" + util.ConfigPath + "/_ucloud" + file, err := os.Create(shellPath) + if err != nil { + fmt.Println(err) + return + } + defer file.Close() + runCompletionZsh(file, cmd) + + rcPath := home + "/.zshrc" + if _, err = os.Stat(rcPath); err == nil { + cmd := fmt.Sprintf("fpath=(%s/%s $fpath);", home, util.ConfigPath) + cmd += "autoload -U +X compinit && compinit" + if util.LineInFile(rcPath, cmd) == false { + util.AppendToFile(rcPath, cmd) + fmt.Println("Auto completion is on") + } else { + fmt.Println("Auto completion update. Restart session") + } + } +} + +//参考自 k8s.io/kubernetes/pkg/kubectl/cmd/completion.go +func runCompletionZsh(out io.Writer, cmd *cobra.Command) error { + zsh_head := "#compdef ucloud\n" + + out.Write([]byte(zsh_head)) + + zsh_initialization := ` +__ucloud_bash_source() { + alias shopt=':' + alias _expand=_bash_expand + alias _complete=_bash_comp + emulate -L sh + setopt kshglob noshglob braceexpand + + source "$@" +} + +__ucloud_type() { + # -t is not supported by zsh + if [ "$1" == "-t" ]; then + shift + + # fake Bash 4 to disable "complete -o nospace". Instead + # "compopt +-o nospace" is used in the code to toggle trailing + # spaces. We don't support that, but leave trailing spaces on + # all the time + if [ "$1" = "__ucloud_compopt" ]; then + echo builtin + return 0 + fi + fi + type "$@" +} + +__ucloud_compgen() { + local completions w + completions=( $(compgen "$@") ) || return $? + + # filter by given word as prefix + while [[ "$1" = -* && "$1" != -- ]]; do + shift + shift + done + if [[ "$1" == -- ]]; then + shift + fi + for w in "${completions[@]}"; do + if [[ "${w}" = "$1"* ]]; then + echo "${w}" + fi + done +} + +__ucloud_compopt() { + true # don't do anything. Not supported by bashcompinit in zsh +} + +__ucloud_ltrim_colon_completions() +{ + if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then + # Remove colon-word prefix from COMPREPLY items + local colon_word=${1%${1##*:}} + local i=${#COMPREPLY[*]} + while [[ $((--i)) -ge 0 ]]; do + COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"} + done + fi +} + +__ucloud_get_comp_words_by_ref() { + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[${COMP_CWORD}-1]}" + words=("${COMP_WORDS[@]}") + cword=("${COMP_CWORD[@]}") +} + +__ucloud_filedir() { + local RET OLD_IFS w qw + + __ucloud_debug "_filedir $@ cur=$cur" + if [[ "$1" = \~* ]]; then + # somehow does not work. Maybe, zsh does not call this at all + eval echo "$1" + return 0 + fi + + OLD_IFS="$IFS" + IFS=$'\n' + if [ "$1" = "-d" ]; then + shift + RET=( $(compgen -d) ) + else + RET=( $(compgen -f) ) + fi + IFS="$OLD_IFS" + + IFS="," __ucloud_debug "RET=${RET[@]} len=${#RET[@]}" + + for w in ${RET[@]}; do + if [[ ! "${w}" = "${cur}"* ]]; then + continue + fi + if eval "[[ \"\${w}\" = *.$1 || -d \"\${w}\" ]]"; then + qw="$(__ucloud_quote "${w}")" + if [ -d "${w}" ]; then + COMPREPLY+=("${qw}/") + else + COMPREPLY+=("${qw}") + fi + fi + done +} + +__ucloud_quote() { + if [[ $1 == \'* || $1 == \"* ]]; then + # Leave out first character + printf %q "${1:1}" + else + printf %q "$1" + fi +} + +autoload -U +X bashcompinit && bashcompinit + +# use word boundary patterns for BSD or GNU sed +LWORD='[[:<:]]' +RWORD='[[:>:]]' +if sed --help 2>&1 | grep -q GNU; then + LWORD='\<' + RWORD='\>' +fi + +__ucloud_convert_bash_to_zsh() { + sed \ + -e 's/declare -F/whence -w/' \ + -e 's/_get_comp_words_by_ref "\$@"/_get_comp_words_by_ref "\$*"/' \ + -e 's/local \([a-zA-Z0-9_]*\)=/local \1; \1=/' \ + -e 's/flags+=("\(--.*\)=")/flags+=("\1"); two_word_flags+=("\1")/' \ + -e 's/must_have_one_flag+=("\(--.*\)=")/must_have_one_flag+=("\1")/' \ + -e "s/${LWORD}_filedir${RWORD}/__ucloud_filedir/g" \ + -e "s/${LWORD}_get_comp_words_by_ref${RWORD}/__ucloud_get_comp_words_by_ref/g" \ + -e "s/${LWORD}__ltrim_colon_completions${RWORD}/__ucloud_ltrim_colon_completions/g" \ + -e "s/${LWORD}compgen${RWORD}/__ucloud_compgen/g" \ + -e "s/${LWORD}compopt${RWORD}/__ucloud_compopt/g" \ + -e "s/${LWORD}declare${RWORD}/builtin declare/g" \ + -e "s/\\\$(type${RWORD}/\$(__ucloud_type/g" \ + <<'BASH_COMPLETION_EOF' +` + out.Write([]byte(zsh_initialization)) + + buf := new(bytes.Buffer) + cmd.GenBashCompletion(buf) + out.Write(buf.Bytes()) + + zsh_tail := ` +BASH_COMPLETION_EOF +} + +__ucloud_bash_source <(__ucloud_convert_bash_to_zsh) +_complete ucloud 2>/dev/null +` + out.Write([]byte(zsh_tail)) + return nil +} diff --git a/cmd/configure.go b/cmd/configure.go new file mode 100644 index 0000000000..fec9e1a72b --- /dev/null +++ b/cmd/configure.go @@ -0,0 +1,169 @@ +// Copyright © 2018 NAME HERE tony.li@ucloud.cn +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + "strings" + + "github.com/spf13/cobra" + + "github.com/ucloud/ucloud-cli/model" +) + +var config = model.ConfigInstance + +//NewCmdConfig ucloud config +func NewCmdConfig() *cobra.Command { + + var configDesc = `Command 'ucloud config' is used to configure public-key,private-key and other settings. + +Public-key and private-key could be acquired from https://console.ucloud.cn/uapi/apikey. + +If you don’t have an UCloud account yet, run 'ucloud sign-up', and authenticate the account with your valid documentation. + +If you just want to configure default region or project, please run 'ucloud config set region/project xxx'. Run 'ucloud config --help' for more infomation. + +` + var helloUcloud = ` + _ _ _ _ _ _ _____ _ _ + | | | | | | | | | | / __ \ | | | + | |_| | ___| | | ___ | | | | / \/ | ___ _ _ __| | + | _ |/ _ \ | |/ _ \ | | | | | | |/ _ \| | | |/ _\ | + | | | | __/ | | (_) | | |_| | \__/\ | (_) | |_| | (_| | + \_| |_/\___|_|_|\___/ \___/ \____/_|\___/ \__,_|\__,_| + ` + + var configCmd = &cobra.Command{ + Use: "config", + Short: "Config UCloud CLI options", + Long: `Config UCloud CLI options such as credentials and other settings.`, + Example: "ucloud config; ucloud config set region cn-bj2", + Run: func(cmd *cobra.Command, args []string) { + fmt.Printf(configDesc) + if len(config.PrivateKey) != 0 && len(config.PublicKey) != 0 { + fmt.Printf("Your have already configured public-key and private-key. Do you want to overwrite it? (y/n):") + var overwrite string + _, err := fmt.Scanf("%s\n", &overwrite) + if err != nil { + fmt.Println(err) + return + } + overwrite = strings.Trim(overwrite, " ") + overwrite = strings.ToLower(overwrite) + if overwrite != "yes" && overwrite != "y" { + return + } + } + config.ConfigPublicKey() + config.ConfigPrivateKey() + fmt.Println("Fetching regions...") + err := listRegion() + if err != nil { + fmt.Println(err) + return + } + config.ConfigRegion() + + fmt.Println("Fetching projects...") + err = listProject() + if err != nil { + fmt.Println(err) + return + } + + config.ConfigProjectID() + config.SaveConfig() + certified, err := isUserCertified() + if err != nil { + fmt.Println(err) + } else if certified == false { + fmt.Println("\nWarning: Please authenticate the account with your valid documentation at 'https://accountv2.ucloud.cn/authentication'.") + } + fmt.Println(helloUcloud) + }, + } + + configCmd.AddCommand(NewCmdConfigList()) + configCmd.AddCommand(NewCmdConfigClear()) + configCmd.AddCommand(NewCmdConfigSet()) + + originHelpFunc := configCmd.HelpFunc() + + configCmd.SetHelpFunc(func(cmd *cobra.Command, args []string) { + rootCmd := cmd.Parent() + rootCmd.Flags().MarkHidden("region") + rootCmd.Flags().MarkHidden("project-id") + originHelpFunc(cmd, args) + }) + return configCmd +} + +//NewCmdConfigList ucloud config ls +func NewCmdConfigList() *cobra.Command { + var configListCmd = &cobra.Command{ + Use: "ls", + Short: "list all settings", + Long: `list all settings`, + Run: func(cmd *cobra.Command, args []string) { + config.ListConfig() + }, + } + return configListCmd +} + +//NewCmdConfigClear ucloud config clear +func NewCmdConfigClear() *cobra.Command { + var configClearCmd = &cobra.Command{ + Use: "clear", + Short: "clear all settings", + Long: "clear all settings", + Run: func(cmd *cobra.Command, args []string) { + config.ClearConfig() + }, + } + return configClearCmd +} + +//NewCmdConfigSet ucloud config set +func NewCmdConfigSet() *cobra.Command { + + var configSetCmd = &cobra.Command{ + Use: "set", + Short: "Set a config value", + Long: "Set a config value, including private-key public-key region and project-id.", + Example: "ucloud configure set region cn-bj2", + Run: func(cmd *cobra.Command, args []string) { + if len(args) != 2 { + fmt.Printf("Error: accepts 2 arg(s), received %d\n", len(args)) + return + } + switch args[0] { + case "region": + config.Region = args[1] + case "project-id": + config.ProjectID = args[1] + case "public-key": + config.PublicKey = args[1] + case "private-key": + config.PrivateKey = args[1] + default: + fmt.Println("Only public-key, private-key, region, project-id supported") + } + config.SaveConfig() + }, + } + return configSetCmd +} diff --git a/cmd/eip.go b/cmd/eip.go new file mode 100644 index 0000000000..d235e71d98 --- /dev/null +++ b/cmd/eip.go @@ -0,0 +1,206 @@ +// Copyright © 2018 NAME HERE tony.li@ucloud.cn +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +//NewCmdEIP ucloud eip +func NewCmdEIP() *cobra.Command { + var cmd = &cobra.Command{ + Use: "eip", + Short: "EIP managment", + Long: `EIP managment, such as list,allocate and release`, + Args: cobra.NoArgs, + } + cmd.AddCommand(NewCmdEIPList()) + cmd.AddCommand(NewCmdEIPAllocate()) + cmd.AddCommand(NewCmdEIPRelease()) + cmd.AddCommand(NewCmdEIPBind()) + cmd.AddCommand(NewCmdEIPUnbind()) + return cmd +} + +//NewCmdEIPList ucloud eip ls +func NewCmdEIPList() *cobra.Command { + req := client.NewDescribeEIPRequest() + var cmd = &cobra.Command{ + Use: "ls", + Short: "List all EIP instances", + Long: `List all EIP instances`, + Example: "ucloud eip ls", + Run: func(cmd *cobra.Command, args []string) { + bindGlobalParam(req) + resp, err := client.DescribeEIP(req) + if err != nil { + fmt.Println("Error:", err) + return + } + if resp.RetCode == 0 { + for _, eip := range resp.EIPSet { + fmt.Printf("EIPId:%s, ", eip.EIPId) + for _, ip := range eip.EIPAddr { + fmt.Printf("IP:%-15s, Line:%s, ", ip.IP, ip.OperatorName) + } + fmt.Printf("BindResource: %s \n", eip.Resource.ResourceId) + } + } else { + fmt.Printf("Something wrong. RetCode:%d, Message: %s \n", resp.RetCode, resp.Message) + } + }, + } + return cmd +} + +//NewCmdEIPAllocate ucloud eip allocate +func NewCmdEIPAllocate() *cobra.Command { + var eipAllocateReq = client.NewAllocateEIPRequest() + var cmd = &cobra.Command{ + Use: "allocate", + Short: "Allocate EIP", + Long: "Allocate EIP", + Example: "ucloud eip allocate --line Bgp --bandwidth 2", + Run: func(cmd *cobra.Command, args []string) { + bindGlobalParam(eipAllocateReq) + resp, err := client.AllocateEIP(eipAllocateReq) + if err != nil { + fmt.Println(err) + } else { + if resp.RetCode == 0 { + for _, eip := range resp.EIPSet { + fmt.Printf("EIPId:%s,", eip.EIPId) + for _, ip := range eip.EIPAddr { + fmt.Printf("IP:%s,Line:%s \n", ip.IP, ip.OperatorName) + } + } + } else { + fmt.Printf("Something wrong. RetCode:%d, Message: %s \n", resp.RetCode, resp.Message) + } + } + }, + } + cmd.Flags().SortFlags = false + cmd.Flags().StringVar(&eipAllocateReq.OperatorName, "line", "", "Line 'Bgp' or 'International'. 'Bgp' can be set in region cn-sh1,cn-sh2,cn-gd,cn-bj1 and cn-bj2. 'International' can be set in region hk,us-ca,th-bkk,kr-seoul,us-ws,ge-fra,sg,tw-kh and other oversea regions. Required") + cmd.Flags().IntVar(&eipAllocateReq.Bandwidth, "bandwidth", 0, "Bandwidth(Unit:Mbps). When paying by traffic, it ranges from 1 to 200; when paying by bandwidth, it ranges from 1 to 800, and when shared bandwidth is used, its value is 0. Required") + cmd.Flags().StringVar(&eipAllocateReq.PayMode, "pay-mode", "Bandwidth", "pay-mode is an enumeration value. 'Traffic','Bandwidth' or 'ShareBandwidth'") + cmd.Flags().IntVar(&eipAllocateReq.Quantity, "quantity", 1, "The quantity of EIP") + cmd.Flags().StringVar(&eipAllocateReq.ChargeType, "charge-type", "Month", "charge-type is an enumeration value. 'Year','Month', 'Dynamic'(Pay by the hour), 'Trial'(Need permission)") + cmd.Flags().StringVar(&eipAllocateReq.Tag, "tag", "Default", "Tag of your EIP.") + cmd.Flags().StringVar(&eipAllocateReq.Name, "name", "EIP", "Name of your EIP.") + cmd.Flags().StringVar(&eipAllocateReq.Remark, "remark", "", "Remark of your EIP.") + cmd.Flags().StringVar(&eipAllocateReq.CouponId, "coupon-id", "", "Coupon ID, The Coupon can deducte part of the payment") + cmd.MarkFlagRequired("line") + cmd.MarkFlagRequired("bandwidth") + return cmd +} + +//NewCmdEIPBind ucloud eip bind +func NewCmdEIPBind() *cobra.Command { + var eipBindReq = client.NewBindEIPRequest() + var eipBindCmd = &cobra.Command{ + Use: "bind", + Short: "Bind EIP with uhost", + Long: "Bind EIP with uhost", + Example: "ucloud eip bind --eip-id eip-xxx --resource-id uhost-xxx", + Run: func(cmd *cobra.Command, args []string) { + bindGlobalParam(eipBindReq) + eipBindReq.ResourceType = "uhost" + resp, err := client.BindEIP(eipBindReq) + if err != nil { + fmt.Println(err) + } else { + if resp.RetCode == 0 { + fmt.Printf("EIP: %v bind with %v:%v successfully \n", eipBindReq.EIPId, eipBindReq.ResourceType, eipBindReq.ResourceId) + } else { + fmt.Printf("Something wrong. RetCode:%d, Message: %s \n", resp.RetCode, resp.Message) + } + } + }, + } + eipBindCmd.Flags().SortFlags = false + eipBindCmd.Flags().StringVar(&eipBindReq.EIPId, "eip-id", "", "EIPId to bind. Required") + eipBindCmd.Flags().StringVar(&eipBindReq.ResourceId, "resource-id", "", "ResourceID , which is the UHostId of uhost. Required") + eipBindCmd.MarkFlagRequired("eip-id") + eipBindCmd.MarkFlagRequired("resource-id") + return eipBindCmd +} + +//NewCmdEIPUnbind ucloud eip unbind +func NewCmdEIPUnbind() *cobra.Command { + + var eipUnBindReq = client.NewUnBindEIPRequest() + var eipUnBindCmd = &cobra.Command{ + Use: "unbind", + Short: "Unbind EIP with uhost", + Long: "Unbind EIP with uhost", + Example: "ucloud eip unbind --eip-id eip-xxx --resource-id uhost-xxx", + Run: func(cmd *cobra.Command, args []string) { + bindGlobalParam(eipUnBindReq) + eipUnBindReq.ResourceType = "uhost" + resp, err := client.UnBindEIP(eipUnBindReq) + if err != nil { + fmt.Println(err) + } else { + if resp.RetCode == 0 { + fmt.Printf("EIP: %v unbind with %v:%v successfully \n", eipUnBindReq.EIPId, eipUnBindReq.ResourceType, eipUnBindReq.ResourceId) + } else { + fmt.Printf("Something wrong. RetCode:%d, Message: %s \n", resp.RetCode, resp.Message) + } + } + }, + } + eipUnBindCmd.Flags().SortFlags = false + eipUnBindCmd.Flags().StringVar(&eipUnBindReq.EIPId, "eip-id", "", "EIPId to unbind. Required") + eipUnBindCmd.Flags().StringVar(&eipUnBindReq.ResourceId, "resource-id", "", "ResourceID , which is the UHostId of uhost. Required") + eipUnBindCmd.MarkFlagRequired("eip-id") + eipUnBindCmd.MarkFlagRequired("resource-id") + + return eipUnBindCmd +} + +//NewCmdEIPRelease ucloud eip release +func NewCmdEIPRelease() *cobra.Command { + var ids []string + var eipReleaseCmd = &cobra.Command{ + Use: "release", + Short: "Release EIP", + Long: "Release EIP", + Example: "ucloud eip release --eip-id eip-xx1 --eip-id eip-xx2", + Run: func(cmd *cobra.Command, args []string) { + for _, id := range ids { + var eipReleaseReq = client.NewReleaseEIPRequest() + bindGlobalParam(eipReleaseReq) + eipReleaseReq.EIPId = id + resp, err := client.ReleaseEIP(eipReleaseReq) + if err != nil { + fmt.Println(err) + } else { + if resp.RetCode == 0 { + fmt.Printf("EIP: %v released \n", eipReleaseReq.EIPId) + } else { + fmt.Printf("Something wrong. RetCode:%d, Message: %s \n", resp.RetCode, resp.Message) + } + } + } + }, + } + eipReleaseCmd.Flags().StringArrayVarP(&ids, "eip-id", "", make([]string, 0), "EIPId of the EIP you want to release. Required") + eipReleaseCmd.MarkFlagRequired("eip-id") + eipReleaseCmd.MarkFlagRequired("bandwidth") + return eipReleaseCmd +} diff --git a/cmd/globalssh.go b/cmd/globalssh.go new file mode 100644 index 0000000000..c19d273e28 --- /dev/null +++ b/cmd/globalssh.go @@ -0,0 +1,214 @@ +// Copyright © 2018 NAME HERE tony.li@ucloud.cn +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + "strconv" + + "github.com/spf13/cobra" +) + +//NewCmdGssh ucloud gssh +func NewCmdGssh() *cobra.Command { + var cmd = &cobra.Command{ + Use: "gssh", + Short: "GlobalSSH management", + Long: `GlobalSSH management, such as create,modify,list and delete`, + } + cmd.AddCommand(NewCmdGsshList()) + cmd.AddCommand(NewCmdGsshCreate()) + cmd.AddCommand(NewCmdGsshDelete()) + cmd.AddCommand(NewCmdGsshModify()) + return cmd +} + +//NewCmdGsshList ucloud gssh list +func NewCmdGsshList() *cobra.Command { + req := client.NewDescribeGlobalSSHInstanceRequest() + var cmd = &cobra.Command{ + Use: "ls", + Short: "List all GlobalSSH instances", + Long: `List all GlobalSSH instances`, + Example: "ucloud gssh ls", + Run: func(cmd *cobra.Command, args []string) { + bindGlobalParam(req) + resp, err := client.DescribeGlobalSSHInstance(req) + if err != nil { + fmt.Println("Error", err) + } else { + if resp.RetCode == 0 { + for _, ins := range resp.InstanceSet { + fmt.Printf("InstanceID:%s, AcceleratingDomain:%s, TargetIP:%v, Port:%v, Remark:%s\n", ins.InstanceId, ins.AcceleratingDomain, ins.TargetIP, ins.Port, ins.Remark) + } + } else { + fmt.Printf("Something wrong, RetCode:%d, Message:%s\n", resp.RetCode, resp.Message) + } + } + }, + } + return cmd +} + +//NewCmdGsshCreate ucloud gssh create +func NewCmdGsshCreate() *cobra.Command { + var gsshCreateReq = client.NewCreateGlobalSSHInstanceRequest() + var cmd = &cobra.Command{ + Use: "create", + Short: "Create GlobalSSH instance", + Long: "Create GlobalSSH instance", + Example: "ucloud gssh create --area Washington --target-ip 8.8.8.8", + Run: func(cmd *cobra.Command, args []string) { + bindGlobalParam(gsshCreateReq) + var areaMap = map[string]string{ + "LosAngeles": "洛杉矶", + "Singapore": "新加坡", + "HongKong": "香港", + "Tokyo": "东京", + "Washington": "华盛顿", + "Frankfurt": "法兰克福", + } + + port, err := strconv.Atoi(gsshCreateReq.Port) + if err != nil { + fmt.Println("Error:", err) + return + } + if port <= 1 || port >= 65535 || port == 80 || port == 443 { + fmt.Println("The port number should be between 1 and 65535, and cannot be equal to 80 or 443") + return + } + + if area, ok := areaMap[gsshCreateReq.Area]; ok { + gsshCreateReq.Area = area + } else { + fmt.Println("Area should be one of LosAngeles,Singapore,HongKong,Tokyo,Washington,Frankfurt.") + return + } + resp, err := client.CreateGlobalSSHInstance(gsshCreateReq) + if err != nil { + fmt.Println("Error:", err) + } else { + if resp.RetCode == 0 { + fmt.Println("Succeed, GlobalSSHInstanceId:", resp.InstanceId) + } else { + fmt.Printf("Something wrong. RetCode:%d,Message:%s\n", resp.RetCode, resp.Message) + } + } + }, + } + cmd.Flags().SortFlags = false + cmd.Flags().StringVar(&gsshCreateReq.Area, "area", "", "Location of the source server.Only supports six cities,LosAngeles,Singapore,HongKong,Tokyo,Washington,Frankfurt. Required") + cmd.Flags().StringVar(&gsshCreateReq.TargetIP, "target-ip", "", "IP of the source server. Required") + cmd.Flags().StringVar(&gsshCreateReq.Port, "port", "22", "Port of The SSH service between 1 and 65535. Do not use ports such as 80,443.") + cmd.Flags().StringVar(&gsshCreateReq.Remark, "remark", "", "Remark of your GlobalSSH.") + cmd.Flags().StringVar(&gsshCreateReq.CouponId, "coupon-id", "", "Coupon ID, The Coupon can deduct part of the payment") + cmd.MarkFlagRequired("area") + cmd.MarkFlagRequired("target-ip") + return cmd +} + +//NewCmdGsshDelete ucloud gssh delete +func NewCmdGsshDelete() *cobra.Command { + var gsshDeleteReq = client.NewDeleteGlobalSSHInstanceRequest() + var gsshIds []string + var cmd = &cobra.Command{ + Use: "delete", + Short: "Delete GlobalSSH instance", + Long: "Delete GlobalSSH instance", + Example: "ucloud gssh delete --id uga-xx1 --id uga-xx2", + Run: func(cmd *cobra.Command, args []string) { + bindGlobalParam(gsshDeleteReq) + for _, id := range gsshIds { + gsshDeleteReq.InstanceId = id + + if global.projectID != "" { + gsshDeleteReq.ProjectId = global.projectID + } + resp, err := client.DeleteGlobalSSHInstance(gsshDeleteReq) + if err != nil { + fmt.Println("Error:", err) + } else { + if resp.RetCode == 0 { + fmt.Printf("GlobalSSH(%s) was successfully deleted\n", id) + } else { + fmt.Printf("Something wrong. RetCode:%d, Message:%s\n", resp.RetCode, resp.Message) + } + } + } + }, + } + cmd.Flags().StringArrayVar(&gsshIds, "id", make([]string, 0), "ID of the GlobalSSH instances you want to delete. Multiple values specified by multiple flags. Required") + cmd.MarkFlagRequired("id") + return cmd +} + +//NewCmdGsshModify ucloud gssh modify +func NewCmdGsshModify() *cobra.Command { + var gsshModifyPortReq = client.NewModifyGlobalSSHPortRequest() + var gsshModifyRemarkReq = client.NewModifyGlobalSSHRemarkRequest() + var cmd = &cobra.Command{ + Use: "modify", + Short: "Modify GlobalSSH instance", + Long: "Modify GlobalSSH instance, including port and remark attribute", + Example: "ucloud gssh modify --id uga-xxx --port 22", + Run: func(cmd *cobra.Command, args []string) { + bindGlobalParam(gsshModifyPortReq) + bindGlobalParam(gsshModifyRemarkReq) + if gsshModifyPortReq.Port == "" && gsshModifyRemarkReq.Remark == "" { + fmt.Println("port or remark required") + } + if gsshModifyPortReq.Port != "" { + port, err := strconv.Atoi(gsshModifyPortReq.Port) + if err != nil { + fmt.Println("Error:", err) + return + } + if port <= 1 || port >= 65535 || port == 80 || port == 443 { + fmt.Println("The port number should be between 1 and 65535, and cannot be equal to 80 or 443") + return + } + gsshModifyPortReq.InstanceId = gsshModifyRemarkReq.InstanceId + resp, err := client.ModifyGlobalSSHPort(gsshModifyPortReq) + if err != nil { + fmt.Println("Error:", err) + } else { + if resp.RetCode == 0 { + fmt.Println("Successfully modified") + } else { + fmt.Printf("Something wrong. RetCode:%d, Message: %s\n", resp.RetCode, resp.Message) + } + } + } + if gsshModifyRemarkReq.Remark != "" { + resp, err := client.ModifyGlobalSSHRemark(gsshModifyRemarkReq) + if err != nil { + fmt.Println("Error:", err) + } else { + if resp.RetCode == 0 { + fmt.Println("Successfully modified") + } else { + fmt.Printf("Something wrong. RetCode:%d, Message: %s\n", resp.RetCode, resp.Message) + } + } + } + }, + } + cmd.Flags().StringVar(&gsshModifyPortReq.Port, "port", "", "Port of SSH service.") + cmd.Flags().StringVar(&gsshModifyRemarkReq.Remark, "remark", "", "Remark of your GlobalSSH.") + cmd.Flags().StringVar(&gsshModifyRemarkReq.InstanceId, "id", "", "InstanceID of your GlobalSSH. Required") + cmd.MarkFlagRequired("id") + return cmd +} diff --git a/cmd/list.go b/cmd/list.go new file mode 100644 index 0000000000..15d395c0c4 --- /dev/null +++ b/cmd/list.go @@ -0,0 +1,117 @@ +// Copyright © 2018 NAME HERE tony.li@ucloud.cn +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "encoding/json" + "fmt" + "io/ioutil" + + "github.com/spf13/cobra" + "github.com/ucloud/ucloud-cli/util" + "github.com/ucloud/ucloud-sdk-go/service/uaccount" + "github.com/ucloud/ucloud-sdk-go/service/uaccount/types" +) + +//NewCmdList ucloud ls +func NewCmdList() *cobra.Command { + var listObject string + var cmd = &cobra.Command{ + Use: "ls", + Short: "List all regions or projects", + Long: "List all regions or projects", + Example: "ucloud ls --object region; ucloud ls --object project", + Run: func(cmd *cobra.Command, args []string) { + switch listObject { + case "region": + listRegion() + case "project": + listProject() + default: + fmt.Println("object should be region or project") + } + }, + } + cmd.Flags().StringVar(&listObject, "object", "", "Object to list,region or project. Required") + cmd.MarkFlagRequired("object") + return cmd +} + +func listRegion() error { + req := &uaccount.GetRegionRequest{} + resp, err := client.GetRegion(req) + if err != nil { + return err + } + if resp.RetCode != 0 { + return fmt.Errorf("Something wrong. RetCode:%d, Message:%s", resp.RetCode, resp.Message) + } + for _, region := range resp.Regions { + fmt.Printf("Region: %s, Zone: %s\n", region.Region, region.Zone) + } + return nil +} + +func listProject() error { + req := &uaccount.GetProjectListRequest{} + resp, err := client.GetProjectList(req) + if err != nil { + return err + } + if resp.RetCode != 0 { + return fmt.Errorf("Something wrong. RetCode:%d, Message:%s", resp.RetCode, resp.Message) + } + for _, project := range resp.ProjectSet { + fmt.Printf("ProjectId: %s, ProjectName:%s\n", project.ProjectId, project.ProjectName) + } + return nil +} + +func isUserCertified() (bool, error) { + userInfo, err := getUserInfo() + if err != nil { + return false, err + } + return userInfo.AuthState == "CERTIFIED", nil +} + +func getUserInfo() (*types.UserInfo, error) { + req := client.NewGetUserInfoRequest() + var userInfo types.UserInfo + resp, err := client.GetUserInfo(req) + + if err != nil { + return nil, err + } + + if resp.RetCode != 0 { + return nil, fmt.Errorf("Something wrong. RetCode:%d, Message:%s", resp.RetCode, resp.Message) + } + if len(resp.DataSet) == 1 { + userInfo = resp.DataSet[0] + bytes, err := json.Marshal(userInfo) + if err != nil { + return nil, err + } + fileFullPath := util.GetConfigPath() + "/user.json" + err = ioutil.WriteFile(fileFullPath, bytes, 0600) + if err != nil { + return nil, err + } + } else { + return nil, fmt.Errorf("GetUserInfo DataSet length: %d", len(resp.DataSet)) + } + return &userInfo, nil +} diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000000..5d0c5ce6c8 --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,129 @@ +// Copyright © 2018 NAME HERE tony.li@ucloud.cn +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + "github.com/ucloud/ucloud-cli/model" + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/service" +) + +//GlobalFlag 几乎所有接口都需要的参数,例如 region zone projectID +type GlobalFlag struct { + region string + projectID string + debug bool +} + +var global GlobalFlag +var client = service.NewClient(model.ClientConfig, model.Credential) + +//NewCmdRoot 创建rootCmd rootCmd represents the base command when called without any subcommands +func NewCmdRoot() *cobra.Command { + var cmd = &cobra.Command{ + Use: "ucloud", + Short: "The UCloud Command Line Interface v" + version, + Long: `The UCloud Command Line Interface is a tool to manage your UCloud services`, + BashCompletionFunction: "__ucloud_init_completion", + } + + cmd.PersistentFlags().StringVarP(&global.region, "region", "r", "", "Assign region(override default region of your config)") + cmd.PersistentFlags().StringVarP(&global.projectID, "project-id", "p", "", "Assign projectId(override default projecId of your config)") + cmd.PersistentFlags().BoolVarP(&global.debug, "debug", "d", false, "Running in debug mode") + + cmd.AddCommand(NewCmdVersion()) + cmd.AddCommand(NewCmdCompletion()) + cmd.AddCommand(NewCmdList()) + cmd.AddCommand(NewCmdConfig()) + cmd.AddCommand(NewCmdSignup()) + cmd.AddCommand(NewCmdUHost()) + cmd.AddCommand(NewCmdGssh()) + cmd.AddCommand(NewCmdEIP()) + + return cmd +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + command := NewCmdRoot() + if err := command.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func init() { + cobra.OnInitialize(initialize) + model.ClientConfig.UserAgent = fmt.Sprintf("UCloud CLI v%s", version) + model.ClientConfig.TracerData["command"] = fmt.Sprintf("%v", os.Args) + model.GetContext() +} + +func initialize(cmd *cobra.Command) { + if global.debug { + model.ClientConfig.LogLevel = 5 + model.ClientConfig.Logger = nil + } + client = service.NewClient(model.ClientConfig, model.Credential) + + userInfo, err := model.LoadUserInfo() + if err == nil { + model.ClientConfig.TracerData["userName"] = userInfo.UserEmail + model.ClientConfig.TracerData["userID"] = userInfo.UserEmail + model.ClientConfig.TracerData["companyName"] = userInfo.CompanyName + } else { + errorStr, ok := model.ClientConfig.TracerData["error"].(string) + if ok { + model.ClientConfig.TracerData["error"] = errorStr + "->" + err.Error() + } else { + model.ClientConfig.TracerData["error"] = err.Error() + } + } + //上报服务对Origin请求头有限制,必须以'.ucloud.cn'结尾,因此这里伪造了一个sdk.ucloud.cn,跟其他上报区分 + model.ClientConfig.HTTPHeaders["Origin"] = "https://sdk.ucloud.cn" + + if (cmd.Name() != "config" && cmd.Name() != "completion" && cmd.Name() != "version") && cmd.Parent().Name() != "config" { + if config.PrivateKey == "" { + fmt.Println("private-key is empty. Execute command 'ucloud config' to configure your private-key") + os.Exit(0) + } + if config.PublicKey == "" { + fmt.Println("public-key is empty. Execute command 'ucloud config' to configure your public-key") + os.Exit(0) + } + if config.Region == "" { + fmt.Println("Default region is empty. Execute command 'ucloud config set region' to configure your default region") + os.Exit(0) + } + if config.ProjectID == "" { + fmt.Println("Default project-id is empty. Execute command 'ucloud config set project' to configure your default project-id") + os.Exit(0) + } + } +} + +func bindGlobalParam(req request.Common) { + if global.region != "" { + req.SetRegion(global.region) + } + if global.projectID != "" { + req.SetProjectId(global.projectID) + } +} diff --git a/cmd/signup.go b/cmd/signup.go new file mode 100644 index 0000000000..b913671254 --- /dev/null +++ b/cmd/signup.go @@ -0,0 +1,57 @@ +// Copyright © 2018 NAME HERE tony.li@ucloud.cn +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + "os/exec" + "runtime" + + "github.com/spf13/cobra" +) + +//NewCmdSignup ucloud signup +func NewCmdSignup() *cobra.Command { + + var cmd = &cobra.Command{ + Use: "sign-up", + Short: "Open sign up page of ucloud in your browser", + Long: `Open sign up page of ucloud in your browser`, + Args: cobra.NoArgs, + Example: "ucloud sign-up", + Run: func(cmd *cobra.Command, args []string) { + openbrowser("https://passport.ucloud.cn/#register") + }, + } + return cmd +} + +func openbrowser(url string) { + var err error + + switch runtime.GOOS { + case "linux": + err = exec.Command("xdg-open", url).Start() + case "windows": + err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start() + case "darwin": + err = exec.Command("open", url).Start() + default: + err = fmt.Errorf("Open url: %s in your browser", url) + } + if err != nil { + fmt.Printf("Open url: %s in your browser\n", url) + } +} diff --git a/cmd/uhost.go b/cmd/uhost.go new file mode 100644 index 0000000000..39c612468e --- /dev/null +++ b/cmd/uhost.go @@ -0,0 +1,55 @@ +// Copyright © 2018 NAME HERE tony.li@ucloud.cn +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +//NewCmdUHost ucloud uhost +func NewCmdUHost() *cobra.Command { + var cmd = &cobra.Command{ + Use: "uhost", + Short: "UHost managment", + Long: `UHost managment. Only list`, + Args: cobra.NoArgs, + } + cmd.AddCommand(NewCmdUHostList()) + return cmd +} + +//NewCmdUHostList ucloud uhost list +func NewCmdUHostList() *cobra.Command { + var cmd = &cobra.Command{ + Use: "ls", + Short: "List all UHost Instances", + Long: `List all UHost Instances`, + Run: func(cmd *cobra.Command, args []string) { + req := client.NewDescribeUHostInstanceRequest() + bindGlobalParam(req) + resp, err := client.DescribeUHostInstance(req) + if err != nil { + fmt.Println("Error:", err) + return + } + for _, uhost := range resp.UHostSet { + fmt.Printf("UHostID:%s\n", uhost.UHostId) + } + }, + } + return cmd +} diff --git a/cmd/version.go b/cmd/version.go new file mode 100644 index 0000000000..ad3a1fc234 --- /dev/null +++ b/cmd/version.go @@ -0,0 +1,35 @@ +// Copyright © 2018 NAME HERE tony.li@ucloud.cn +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +var version = "0.1.1" + +//NewCmdVersion ucloud version +func NewCmdVersion() *cobra.Command { + return &cobra.Command{ + Use: "version", + Short: "Show the version of ucloud", + Long: `Show the version of ucloud`, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println(version) + }, + } +} diff --git a/main.go b/main.go new file mode 100644 index 0000000000..9df448afa8 --- /dev/null +++ b/main.go @@ -0,0 +1,23 @@ +// Copyright © 2018 NAME HERE +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "github.com/ucloud/ucloud-cli/cmd" +) + +func main() { + cmd.Execute() +} diff --git a/model/config.go b/model/config.go new file mode 100644 index 0000000000..8f8ae95103 --- /dev/null +++ b/model/config.go @@ -0,0 +1,190 @@ +package model + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "strings" + "time" + + "github.com/ucloud/ucloud-cli/util" + "github.com/ucloud/ucloud-sdk-go/sdk" + "github.com/ucloud/ucloud-sdk-go/sdk/auth" + "github.com/ucloud/ucloud-sdk-go/service/uaccount/types" +) + +const configFile = "config.json" + +//ConfigPath 配置文件路径 + +//ConfigInstance 配置实例, 程序加载时生成 +var ConfigInstance = &Config{} + +//ClientConfig 创建sdk client参数 +var ClientConfig *sdk.ClientConfig + +//Credential 创建sdk client参数 +var Credential *auth.Credential + +// Config 全局配置 +type Config struct { + PublicKey string `json:"public_key"` + PrivateKey string `json:"private_key"` + Region string `json:"region"` + ProjectID string `json:"project_id"` +} + +//ConfigPublicKey 输入公钥 +func (p *Config) ConfigPublicKey() error { + context.Print("Your public-key:") + _, err := fmt.Scanf("%s\n", &p.PublicKey) + p.PublicKey = strings.TrimSpace(p.PublicKey) + Credential.PublicKey = p.PublicKey + p.SaveConfig() + if err != nil { + context.Println(err) + } + return err +} + +//ConfigPrivateKey 输入私钥 +func (p *Config) ConfigPrivateKey() error { + context.Print("Your private-key:") + _, err := fmt.Scanf("%s\n", &p.PrivateKey) + p.PrivateKey = strings.TrimSpace(p.PrivateKey) + Credential.PrivateKey = p.PrivateKey + p.SaveConfig() + if err != nil { + context.Println(err) + } + return err +} + +//ConfigRegion 输入默认Region +func (p *Config) ConfigRegion() error { + p.LoadConfig() + context.Print("Default region:") + _, err := fmt.Scanf("%s\n", &p.Region) + if err != nil { + context.Println(err) + return err + } + p.Region = strings.TrimSpace(p.Region) + ClientConfig.Region = p.Region + p.SaveConfig() + return nil +} + +//ConfigProjectID 输入默认ProjectID +func (p *Config) ConfigProjectID() error { + p.LoadConfig() + context.Print("Default project-id:") + _, err := fmt.Scanf("%s\n", &p.ProjectID) + if err != nil { + context.Println(err) + return err + } + p.ProjectID = strings.TrimSpace(p.ProjectID) + ClientConfig.ProjectId = p.ProjectID + p.SaveConfig() + return nil +} + +//GetClientConfig 用来生成sdkClient +func (p *Config) GetClientConfig(isDebug bool) *sdk.ClientConfig { + p.LoadConfig() + clientConfig := &sdk.ClientConfig{ + Region: p.Region, + ProjectId: p.ProjectID, + BaseUrl: "https://api.ucloud.cn/", + Timeout: 10 * time.Second, + LogLevel: 1, + } + if isDebug == true { + clientConfig.LogLevel = 5 + } + return clientConfig +} + +//GetCredential 用来生成SDkClient +func (p *Config) GetCredential() *auth.Credential { + p.LoadConfig() + return &auth.Credential{ + PublicKey: p.PublicKey, + PrivateKey: p.PrivateKey, + } +} + +//ListConfig 查看配置 +func (p *Config) ListConfig() error { + + tmpConfig := *p + tmpConfig.PrivateKey = util.MosaicString(tmpConfig.PrivateKey, 8, 5) + tmpConfig.PublicKey = util.MosaicString(tmpConfig.PublicKey, 8, 5) + + bytes, err := json.MarshalIndent(tmpConfig, "", " ") + if err != nil { + return err + } + context.Println(string(bytes)) + return nil +} + +//ClearConfig 清空配置 +func (p *Config) ClearConfig() error { + p = &Config{} + return p.SaveConfig() +} + +//SaveConfig 保存配置到本地文件,以后可以直接使用 +func (p *Config) SaveConfig() error { + bytes, err := json.Marshal(p) + if err != nil { + return err + } + fileFullPath := util.GetConfigPath() + "/" + configFile + err = ioutil.WriteFile(fileFullPath, bytes, 0600) + return err +} + +//LoadConfig 从本地文件加载配置 +func (p *Config) LoadConfig() error { + fileFullPath := util.GetConfigPath() + "/" + configFile + content, err := ioutil.ReadFile(fileFullPath) + if err != nil { + return err + } + json.Unmarshal(content, p) + return nil +} + +//LoadUserInfo 从~/.ucloud/user.json加载用户信息 +func LoadUserInfo() (*types.UserInfo, error) { + fileFullPath := util.GetConfigPath() + "/user.json" + content, err := ioutil.ReadFile(fileFullPath) + if err != nil { + return nil, err + } + var user types.UserInfo + err = json.Unmarshal(content, &user) + if err != nil { + return nil, err + } + return &user, nil +} + +func init() { + ConfigInstance.LoadConfig() + ClientConfig = &sdk.ClientConfig{ + Region: ConfigInstance.Region, + ProjectId: ConfigInstance.ProjectID, + BaseUrl: "https://api.ucloud.cn/", + LogLevel: 1, + } + + Credential = &auth.Credential{ + PublicKey: ConfigInstance.PublicKey, + PrivateKey: ConfigInstance.PrivateKey, + } + +} diff --git a/model/context.go b/model/context.go new file mode 100644 index 0000000000..747c906a40 --- /dev/null +++ b/model/context.go @@ -0,0 +1,34 @@ +package model + +import ( + "fmt" + "io" + "os" + "sync" +) + +var context *Context +var once sync.Once + +// Context 执行环境 +type Context struct { + writer io.Writer +} + +// Println 在当前执行环境打印一行 +func (p *Context) Println(a ...interface{}) (n int, err error) { + return fmt.Fprintln(p.writer, a...) +} + +// Print 在当前执行环境打印一串 +func (p *Context) Print(a ...interface{}) (n int, err error) { + return fmt.Fprint(p.writer, a...) +} + +// GetContext 创建一个单例的Context +func GetContext() *Context { + once.Do(func() { + context = &Context{os.Stdout} + }) + return context +} diff --git a/util/sdk.go b/util/sdk.go new file mode 100644 index 0000000000..9777ddaded --- /dev/null +++ b/util/sdk.go @@ -0,0 +1,84 @@ +package util + +import ( + "bufio" + "fmt" + "io" + "os" + "runtime" + "strings" +) + +const ConfigPath = ".ucloud" + +//GetHomePath 获取家目录 +func GetHomePath() string { + if runtime.GOOS == "windows" { + home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") + if home == "" { + home = os.Getenv("USERPROFILE") + } + return home + } + return os.Getenv("HOME") +} + +//MosaicString 对字符串敏感部分打马赛克 如公钥私钥 +func MosaicString(s string, beginChars, lastChars int) string { + r := len(s) - lastChars - beginChars + if r > 0 { + return s[:beginChars] + strings.Repeat("*", r) + s[(r+beginChars):] + } + return strings.Repeat("*", len(s)) +} + +//AppendToFile 添加到文件中 +func AppendToFile(name string, content string) error { + f, err := os.OpenFile(name, os.O_RDWR|os.O_APPEND, 0) + if err != nil { + return err + } + defer f.Close() + _, err = f.WriteString(fmt.Sprintf("\n%s\n", content)) + return err +} + +//LineInFile 检查某一行是否在某文件中 +func LineInFile(fileName string, lookFor string) bool { + f, err := os.Open(fileName) + if err != nil { + return false + } + defer f.Close() + r := bufio.NewReader(f) + prefix := []byte{} + for { + line, isPrefix, err := r.ReadLine() + if err == io.EOF { + return false + } + if err != nil { + return false + } + if isPrefix { + prefix = append(prefix, line...) + continue + } + line = append(prefix, line...) + if string(line) == lookFor { + return true + } + prefix = prefix[:0] + } +} + +func GetConfigPath() string { + path := GetHomePath() + "/" + ConfigPath + if _, err := os.Stat(path); os.IsNotExist(err) { + err = os.MkdirAll(path, 0755) + if err != nil { + panic(err) + } + } + return path +} diff --git a/vendor/github.com/Sirupsen/logrus/CHANGELOG.md b/vendor/github.com/Sirupsen/logrus/CHANGELOG.md new file mode 100644 index 0000000000..1bd1deb294 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/CHANGELOG.md @@ -0,0 +1,123 @@ +# 1.0.5 + +* Fix hooks race (#707) +* Fix panic deadlock (#695) + +# 1.0.4 + +* Fix race when adding hooks (#612) +* Fix terminal check in AppEngine (#635) + +# 1.0.3 + +* Replace example files with testable examples + +# 1.0.2 + +* bug: quote non-string values in text formatter (#583) +* Make (*Logger) SetLevel a public method + +# 1.0.1 + +* bug: fix escaping in text formatter (#575) + +# 1.0.0 + +* Officially changed name to lower-case +* bug: colors on Windows 10 (#541) +* bug: fix race in accessing level (#512) + +# 0.11.5 + +* feature: add writer and writerlevel to entry (#372) + +# 0.11.4 + +* bug: fix undefined variable on solaris (#493) + +# 0.11.3 + +* formatter: configure quoting of empty values (#484) +* formatter: configure quoting character (default is `"`) (#484) +* bug: fix not importing io correctly in non-linux environments (#481) + +# 0.11.2 + +* bug: fix windows terminal detection (#476) + +# 0.11.1 + +* bug: fix tty detection with custom out (#471) + +# 0.11.0 + +* performance: Use bufferpool to allocate (#370) +* terminal: terminal detection for app-engine (#343) +* feature: exit handler (#375) + +# 0.10.0 + +* feature: Add a test hook (#180) +* feature: `ParseLevel` is now case-insensitive (#326) +* feature: `FieldLogger` interface that generalizes `Logger` and `Entry` (#308) +* performance: avoid re-allocations on `WithFields` (#335) + +# 0.9.0 + +* logrus/text_formatter: don't emit empty msg +* logrus/hooks/airbrake: move out of main repository +* logrus/hooks/sentry: move out of main repository +* logrus/hooks/papertrail: move out of main repository +* logrus/hooks/bugsnag: move out of main repository +* logrus/core: run tests with `-race` +* logrus/core: detect TTY based on `stderr` +* logrus/core: support `WithError` on logger +* logrus/core: Solaris support + +# 0.8.7 + +* logrus/core: fix possible race (#216) +* logrus/doc: small typo fixes and doc improvements + + +# 0.8.6 + +* hooks/raven: allow passing an initialized client + +# 0.8.5 + +* logrus/core: revert #208 + +# 0.8.4 + +* formatter/text: fix data race (#218) + +# 0.8.3 + +* logrus/core: fix entry log level (#208) +* logrus/core: improve performance of text formatter by 40% +* logrus/core: expose `LevelHooks` type +* logrus/core: add support for DragonflyBSD and NetBSD +* formatter/text: print structs more verbosely + +# 0.8.2 + +* logrus: fix more Fatal family functions + +# 0.8.1 + +* logrus: fix not exiting on `Fatalf` and `Fatalln` + +# 0.8.0 + +* logrus: defaults to stderr instead of stdout +* hooks/sentry: add special field for `*http.Request` +* formatter/text: ignore Windows for colors + +# 0.7.3 + +* formatter/\*: allow configuration of timestamp layout + +# 0.7.2 + +* formatter/text: Add configuration option for time format (#158) diff --git a/vendor/github.com/Sirupsen/logrus/LICENSE b/vendor/github.com/Sirupsen/logrus/LICENSE new file mode 100644 index 0000000000..f090cb42f3 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Simon Eskildsen + +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. diff --git a/vendor/github.com/Sirupsen/logrus/README.md b/vendor/github.com/Sirupsen/logrus/README.md new file mode 100644 index 0000000000..072e99be31 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/README.md @@ -0,0 +1,461 @@ +# Logrus :walrus: [![Build Status](https://travis-ci.org/sirupsen/logrus.svg?branch=master)](https://travis-ci.org/sirupsen/logrus) [![GoDoc](https://godoc.org/github.com/sirupsen/logrus?status.svg)](https://godoc.org/github.com/sirupsen/logrus) + +Logrus is a structured logger for Go (golang), completely API compatible with +the standard library logger. + +**Seeing weird case-sensitive problems?** It's in the past been possible to +import Logrus as both upper- and lower-case. Due to the Go package environment, +this caused issues in the community and we needed a standard. Some environments +experienced problems with the upper-case variant, so the lower-case was decided. +Everything using `logrus` will need to use the lower-case: +`github.com/sirupsen/logrus`. Any package that isn't, should be changed. + +To fix Glide, see [these +comments](https://github.com/sirupsen/logrus/issues/553#issuecomment-306591437). +For an in-depth explanation of the casing issue, see [this +comment](https://github.com/sirupsen/logrus/issues/570#issuecomment-313933276). + +**Are you interested in assisting in maintaining Logrus?** Currently I have a +lot of obligations, and I am unable to provide Logrus with the maintainership it +needs. If you'd like to help, please reach out to me at `simon at author's +username dot com`. + +Nicely color-coded in development (when a TTY is attached, otherwise just +plain text): + +![Colored](http://i.imgur.com/PY7qMwd.png) + +With `log.SetFormatter(&log.JSONFormatter{})`, for easy parsing by logstash +or Splunk: + +```json +{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the +ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"} + +{"level":"warning","msg":"The group's number increased tremendously!", +"number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"} + +{"animal":"walrus","level":"info","msg":"A giant walrus appears!", +"size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"} + +{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.", +"size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"} + +{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true, +"time":"2014-03-10 19:57:38.562543128 -0400 EDT"} +``` + +With the default `log.SetFormatter(&log.TextFormatter{})` when a TTY is not +attached, the output is compatible with the +[logfmt](http://godoc.org/github.com/kr/logfmt) format: + +```text +time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8 +time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10 +time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true +time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4 +time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009 +time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true +exit status 1 +``` + +#### Case-sensitivity + +The organization's name was changed to lower-case--and this will not be changed +back. If you are getting import conflicts due to case sensitivity, please use +the lower-case import: `github.com/sirupsen/logrus`. + +#### Example + +The simplest way to use Logrus is simply the package-level exported logger: + +```go +package main + +import ( + log "github.com/sirupsen/logrus" +) + +func main() { + log.WithFields(log.Fields{ + "animal": "walrus", + }).Info("A walrus appears") +} +``` + +Note that it's completely api-compatible with the stdlib logger, so you can +replace your `log` imports everywhere with `log "github.com/sirupsen/logrus"` +and you'll now have the flexibility of Logrus. You can customize it all you +want: + +```go +package main + +import ( + "os" + log "github.com/sirupsen/logrus" +) + +func init() { + // Log as JSON instead of the default ASCII formatter. + log.SetFormatter(&log.JSONFormatter{}) + + // Output to stdout instead of the default stderr + // Can be any io.Writer, see below for File example + log.SetOutput(os.Stdout) + + // Only log the warning severity or above. + log.SetLevel(log.WarnLevel) +} + +func main() { + log.WithFields(log.Fields{ + "animal": "walrus", + "size": 10, + }).Info("A group of walrus emerges from the ocean") + + log.WithFields(log.Fields{ + "omg": true, + "number": 122, + }).Warn("The group's number increased tremendously!") + + log.WithFields(log.Fields{ + "omg": true, + "number": 100, + }).Fatal("The ice breaks!") + + // A common pattern is to re-use fields between logging statements by re-using + // the logrus.Entry returned from WithFields() + contextLogger := log.WithFields(log.Fields{ + "common": "this is a common field", + "other": "I also should be logged always", + }) + + contextLogger.Info("I'll be logged with common and other field") + contextLogger.Info("Me too") +} +``` + +For more advanced usage such as logging to multiple locations from the same +application, you can also create an instance of the `logrus` Logger: + +```go +package main + +import ( + "os" + "github.com/sirupsen/logrus" +) + +// Create a new instance of the logger. You can have any number of instances. +var log = logrus.New() + +func main() { + // The API for setting attributes is a little different than the package level + // exported logger. See Godoc. + log.Out = os.Stdout + + // You could set this to any `io.Writer` such as a file + // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666) + // if err == nil { + // log.Out = file + // } else { + // log.Info("Failed to log to file, using default stderr") + // } + + log.WithFields(logrus.Fields{ + "animal": "walrus", + "size": 10, + }).Info("A group of walrus emerges from the ocean") +} +``` + +#### Fields + +Logrus encourages careful, structured logging through logging fields instead of +long, unparseable error messages. For example, instead of: `log.Fatalf("Failed +to send event %s to topic %s with key %d")`, you should log the much more +discoverable: + +```go +log.WithFields(log.Fields{ + "event": event, + "topic": topic, + "key": key, +}).Fatal("Failed to send event") +``` + +We've found this API forces you to think about logging in a way that produces +much more useful logging messages. We've been in countless situations where just +a single added field to a log statement that was already there would've saved us +hours. The `WithFields` call is optional. + +In general, with Logrus using any of the `printf`-family functions should be +seen as a hint you should add a field, however, you can still use the +`printf`-family functions with Logrus. + +#### Default Fields + +Often it's helpful to have fields _always_ attached to log statements in an +application or parts of one. For example, you may want to always log the +`request_id` and `user_ip` in the context of a request. Instead of writing +`log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})` on +every line, you can create a `logrus.Entry` to pass around instead: + +```go +requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip}) +requestLogger.Info("something happened on that request") # will log request_id and user_ip +requestLogger.Warn("something not great happened") +``` + +#### Hooks + +You can add hooks for logging levels. For example to send errors to an exception +tracking service on `Error`, `Fatal` and `Panic`, info to StatsD or log to +multiple places simultaneously, e.g. syslog. + +Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in +`init`: + +```go +import ( + log "github.com/sirupsen/logrus" + "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "airbrake" + logrus_syslog "github.com/sirupsen/logrus/hooks/syslog" + "log/syslog" +) + +func init() { + + // Use the Airbrake hook to report errors that have Error severity or above to + // an exception tracker. You can create custom hooks, see the Hooks section. + log.AddHook(airbrake.NewHook(123, "xyz", "production")) + + hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "") + if err != nil { + log.Error("Unable to connect to local syslog daemon") + } else { + log.AddHook(hook) + } +} +``` +Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md). + +A list of currently known of service hook can be found in this wiki [page](https://github.com/sirupsen/logrus/wiki/Hooks) + + +#### Level logging + +Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic. + +```go +log.Debug("Useful debugging information.") +log.Info("Something noteworthy happened!") +log.Warn("You should probably take a look at this.") +log.Error("Something failed but I'm not quitting.") +// Calls os.Exit(1) after logging +log.Fatal("Bye.") +// Calls panic() after logging +log.Panic("I'm bailing.") +``` + +You can set the logging level on a `Logger`, then it will only log entries with +that severity or anything above it: + +```go +// Will log anything that is info or above (warn, error, fatal, panic). Default. +log.SetLevel(log.InfoLevel) +``` + +It may be useful to set `log.Level = logrus.DebugLevel` in a debug or verbose +environment if your application has that. + +#### Entries + +Besides the fields added with `WithField` or `WithFields` some fields are +automatically added to all logging events: + +1. `time`. The timestamp when the entry was created. +2. `msg`. The logging message passed to `{Info,Warn,Error,Fatal,Panic}` after + the `AddFields` call. E.g. `Failed to send event.` +3. `level`. The logging level. E.g. `info`. + +#### Environments + +Logrus has no notion of environment. + +If you wish for hooks and formatters to only be used in specific environments, +you should handle that yourself. For example, if your application has a global +variable `Environment`, which is a string representation of the environment you +could do: + +```go +import ( + log "github.com/sirupsen/logrus" +) + +init() { + // do something here to set environment depending on an environment variable + // or command-line flag + if Environment == "production" { + log.SetFormatter(&log.JSONFormatter{}) + } else { + // The TextFormatter is default, you don't actually have to do this. + log.SetFormatter(&log.TextFormatter{}) + } +} +``` + +This configuration is how `logrus` was intended to be used, but JSON in +production is mostly only useful if you do log aggregation with tools like +Splunk or Logstash. + +#### Formatters + +The built-in logging formatters are: + +* `logrus.TextFormatter`. Logs the event in colors if stdout is a tty, otherwise + without colors. + * *Note:* to force colored output when there is no TTY, set the `ForceColors` + field to `true`. To force no colored output even if there is a TTY set the + `DisableColors` field to `true`. For Windows, see + [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable). + * When colors are enabled, levels are truncated to 4 characters by default. To disable + truncation set the `DisableLevelTruncation` field to `true`. + * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter). +* `logrus.JSONFormatter`. Logs fields as JSON. + * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter). + +Third party logging formatters: + +* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can be parsed by Kubernetes and Google Container Engine. +* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events. +* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout. +* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦. + +You can define your formatter by implementing the `Formatter` interface, +requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a +`Fields` type (`map[string]interface{}`) with all your fields as well as the +default ones (see Entries section above): + +```go +type MyJSONFormatter struct { +} + +log.SetFormatter(new(MyJSONFormatter)) + +func (f *MyJSONFormatter) Format(entry *Entry) ([]byte, error) { + // Note this doesn't include Time, Level and Message which are available on + // the Entry. Consult `godoc` on information about those fields or read the + // source of the official loggers. + serialized, err := json.Marshal(entry.Data) + if err != nil { + return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) + } + return append(serialized, '\n'), nil +} +``` + +#### Logger as an `io.Writer` + +Logrus can be transformed into an `io.Writer`. That writer is the end of an `io.Pipe` and it is your responsibility to close it. + +```go +w := logger.Writer() +defer w.Close() + +srv := http.Server{ + // create a stdlib log.Logger that writes to + // logrus.Logger. + ErrorLog: log.New(w, "", 0), +} +``` + +Each line written to that writer will be printed the usual way, using formatters +and hooks. The level for those entries is `info`. + +This means that we can override the standard library logger easily: + +```go +logger := logrus.New() +logger.Formatter = &logrus.JSONFormatter{} + +// Use logrus for standard log output +// Note that `log` here references stdlib's log +// Not logrus imported under the name `log`. +log.SetOutput(logger.Writer()) +``` + +#### Rotation + +Log rotation is not provided with Logrus. Log rotation should be done by an +external program (like `logrotate(8)`) that can compress and delete old log +entries. It should not be a feature of the application-level logger. + +#### Tools + +| Tool | Description | +| ---- | ----------- | +|[Logrus Mate](https://github.com/gogap/logrus_mate)|Logrus mate is a tool for Logrus to manage loggers, you can initial logger's level, hook and formatter by config file, the logger will generated with different config at different environment.| +|[Logrus Viper Helper](https://github.com/heirko/go-contrib/tree/master/logrusHelper)|An Helper around Logrus to wrap with spf13/Viper to load configuration with fangs! And to simplify Logrus configuration use some behavior of [Logrus Mate](https://github.com/gogap/logrus_mate). [sample](https://github.com/heirko/iris-contrib/blob/master/middleware/logrus-logger/example) | + +#### Testing + +Logrus has a built in facility for asserting the presence of log messages. This is implemented through the `test` hook and provides: + +* decorators for existing logger (`test.NewLocal` and `test.NewGlobal`) which basically just add the `test` hook +* a test logger (`test.NewNullLogger`) that just records log messages (and does not output any): + +```go +import( + "github.com/sirupsen/logrus" + "github.com/sirupsen/logrus/hooks/test" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestSomething(t*testing.T){ + logger, hook := test.NewNullLogger() + logger.Error("Helloerror") + + assert.Equal(t, 1, len(hook.Entries)) + assert.Equal(t, logrus.ErrorLevel, hook.LastEntry().Level) + assert.Equal(t, "Helloerror", hook.LastEntry().Message) + + hook.Reset() + assert.Nil(t, hook.LastEntry()) +} +``` + +#### Fatal handlers + +Logrus can register one or more functions that will be called when any `fatal` +level message is logged. The registered handlers will be executed before +logrus performs a `os.Exit(1)`. This behavior may be helpful if callers need +to gracefully shutdown. Unlike a `panic("Something went wrong...")` call which can be intercepted with a deferred `recover` a call to `os.Exit(1)` can not be intercepted. + +``` +... +handler := func() { + // gracefully shutdown something... +} +logrus.RegisterExitHandler(handler) +... +``` + +#### Thread safety + +By default, Logger is protected by a mutex for concurrent writes. The mutex is held when calling hooks and writing logs. +If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking. + +Situation when locking is not needed includes: + +* You have no hooks registered, or hooks calling is already thread-safe. + +* Writing to logger.Out is already thread-safe, for example: + + 1) logger.Out is protected by locks. + + 2) logger.Out is a os.File handler opened with `O_APPEND` flag, and every write is smaller than 4k. (This allow multi-thread/multi-process writing) + + (Refer to http://www.notthewizard.com/2014/06/17/are-files-appends-really-atomic/) diff --git a/vendor/github.com/Sirupsen/logrus/alt_exit.go b/vendor/github.com/Sirupsen/logrus/alt_exit.go new file mode 100644 index 0000000000..8af90637a9 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/alt_exit.go @@ -0,0 +1,64 @@ +package logrus + +// The following code was sourced and modified from the +// https://github.com/tebeka/atexit package governed by the following license: +// +// Copyright (c) 2012 Miki Tebeka . +// +// 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. + +import ( + "fmt" + "os" +) + +var handlers = []func(){} + +func runHandler(handler func()) { + defer func() { + if err := recover(); err != nil { + fmt.Fprintln(os.Stderr, "Error: Logrus exit handler error:", err) + } + }() + + handler() +} + +func runHandlers() { + for _, handler := range handlers { + runHandler(handler) + } +} + +// Exit runs all the Logrus atexit handlers and then terminates the program using os.Exit(code) +func Exit(code int) { + runHandlers() + os.Exit(code) +} + +// RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke +// all handlers. The handlers will also be invoked when any Fatal log entry is +// made. +// +// This method is useful when a caller wishes to use logrus to log a fatal +// message but also needs to gracefully shutdown. An example usecase could be +// closing database connections, or sending a alert that the application is +// closing. +func RegisterExitHandler(handler func()) { + handlers = append(handlers, handler) +} diff --git a/vendor/github.com/Sirupsen/logrus/appveyor.yml b/vendor/github.com/Sirupsen/logrus/appveyor.yml new file mode 100644 index 0000000000..96c2ce15f8 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/appveyor.yml @@ -0,0 +1,14 @@ +version: "{build}" +platform: x64 +clone_folder: c:\gopath\src\github.com\sirupsen\logrus +environment: + GOPATH: c:\gopath +branches: + only: + - master +install: + - set PATH=%GOPATH%\bin;c:\go\bin;%PATH% + - go version +build_script: + - go get -t + - go test diff --git a/vendor/github.com/Sirupsen/logrus/doc.go b/vendor/github.com/Sirupsen/logrus/doc.go new file mode 100644 index 0000000000..da67aba06d --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/doc.go @@ -0,0 +1,26 @@ +/* +Package logrus is a structured logger for Go, completely API compatible with the standard library logger. + + +The simplest way to use Logrus is simply the package-level exported logger: + + package main + + import ( + log "github.com/sirupsen/logrus" + ) + + func main() { + log.WithFields(log.Fields{ + "animal": "walrus", + "number": 1, + "size": 10, + }).Info("A walrus appears") + } + +Output: + time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10 + +For a full guide visit https://github.com/sirupsen/logrus +*/ +package logrus diff --git a/vendor/github.com/Sirupsen/logrus/entry.go b/vendor/github.com/Sirupsen/logrus/entry.go new file mode 100644 index 0000000000..c2b2e493d8 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/entry.go @@ -0,0 +1,300 @@ +package logrus + +import ( + "bytes" + "fmt" + "os" + "sync" + "time" +) + +var bufferPool *sync.Pool + +func init() { + bufferPool = &sync.Pool{ + New: func() interface{} { + return new(bytes.Buffer) + }, + } +} + +// Defines the key when adding errors using WithError. +var ErrorKey = "error" + +// An entry is the final or intermediate Logrus logging entry. It contains all +// the fields passed with WithField{,s}. It's finally logged when Debug, Info, +// Warn, Error, Fatal or Panic is called on it. These objects can be reused and +// passed around as much as you wish to avoid field duplication. +type Entry struct { + Logger *Logger + + // Contains all the fields set by the user. + Data Fields + + // Time at which the log entry was created + Time time.Time + + // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic + // This field will be set on entry firing and the value will be equal to the one in Logger struct field. + Level Level + + // Message passed to Debug, Info, Warn, Error, Fatal or Panic + Message string + + // When formatter is called in entry.log(), an Buffer may be set to entry + Buffer *bytes.Buffer +} + +func NewEntry(logger *Logger) *Entry { + return &Entry{ + Logger: logger, + // Default is five fields, give a little extra room + Data: make(Fields, 5), + } +} + +// Returns the string representation from the reader and ultimately the +// formatter. +func (entry *Entry) String() (string, error) { + serialized, err := entry.Logger.Formatter.Format(entry) + if err != nil { + return "", err + } + str := string(serialized) + return str, nil +} + +// Add an error as single field (using the key defined in ErrorKey) to the Entry. +func (entry *Entry) WithError(err error) *Entry { + return entry.WithField(ErrorKey, err) +} + +// Add a single field to the Entry. +func (entry *Entry) WithField(key string, value interface{}) *Entry { + return entry.WithFields(Fields{key: value}) +} + +// Add a map of fields to the Entry. +func (entry *Entry) WithFields(fields Fields) *Entry { + data := make(Fields, len(entry.Data)+len(fields)) + for k, v := range entry.Data { + data[k] = v + } + for k, v := range fields { + data[k] = v + } + return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time} +} + +// Overrides the time of the Entry. +func (entry *Entry) WithTime(t time.Time) *Entry { + return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t} +} + +// This function is not declared with a pointer value because otherwise +// race conditions will occur when using multiple goroutines +func (entry Entry) log(level Level, msg string) { + var buffer *bytes.Buffer + + // Default to now, but allow users to override if they want. + // + // We don't have to worry about polluting future calls to Entry#log() + // with this assignment because this function is declared with a + // non-pointer receiver. + if entry.Time.IsZero() { + entry.Time = time.Now() + } + + entry.Level = level + entry.Message = msg + + entry.fireHooks() + + buffer = bufferPool.Get().(*bytes.Buffer) + buffer.Reset() + defer bufferPool.Put(buffer) + entry.Buffer = buffer + + entry.write() + + entry.Buffer = nil + + // To avoid Entry#log() returning a value that only would make sense for + // panic() to use in Entry#Panic(), we avoid the allocation by checking + // directly here. + if level <= PanicLevel { + panic(&entry) + } +} + +func (entry *Entry) fireHooks() { + entry.Logger.mu.Lock() + defer entry.Logger.mu.Unlock() + err := entry.Logger.Hooks.Fire(entry.Level, entry) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) + } +} + +func (entry *Entry) write() { + entry.Logger.mu.Lock() + defer entry.Logger.mu.Unlock() + serialized, err := entry.Logger.Formatter.Format(entry) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) + } else { + _, err = entry.Logger.Out.Write(serialized) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) + } + } +} + +func (entry *Entry) Debug(args ...interface{}) { + if entry.Logger.level() >= DebugLevel { + entry.log(DebugLevel, fmt.Sprint(args...)) + } +} + +func (entry *Entry) Print(args ...interface{}) { + entry.Info(args...) +} + +func (entry *Entry) Info(args ...interface{}) { + if entry.Logger.level() >= InfoLevel { + entry.log(InfoLevel, fmt.Sprint(args...)) + } +} + +func (entry *Entry) Warn(args ...interface{}) { + if entry.Logger.level() >= WarnLevel { + entry.log(WarnLevel, fmt.Sprint(args...)) + } +} + +func (entry *Entry) Warning(args ...interface{}) { + entry.Warn(args...) +} + +func (entry *Entry) Error(args ...interface{}) { + if entry.Logger.level() >= ErrorLevel { + entry.log(ErrorLevel, fmt.Sprint(args...)) + } +} + +func (entry *Entry) Fatal(args ...interface{}) { + if entry.Logger.level() >= FatalLevel { + entry.log(FatalLevel, fmt.Sprint(args...)) + } + Exit(1) +} + +func (entry *Entry) Panic(args ...interface{}) { + if entry.Logger.level() >= PanicLevel { + entry.log(PanicLevel, fmt.Sprint(args...)) + } + panic(fmt.Sprint(args...)) +} + +// Entry Printf family functions + +func (entry *Entry) Debugf(format string, args ...interface{}) { + if entry.Logger.level() >= DebugLevel { + entry.Debug(fmt.Sprintf(format, args...)) + } +} + +func (entry *Entry) Infof(format string, args ...interface{}) { + if entry.Logger.level() >= InfoLevel { + entry.Info(fmt.Sprintf(format, args...)) + } +} + +func (entry *Entry) Printf(format string, args ...interface{}) { + entry.Infof(format, args...) +} + +func (entry *Entry) Warnf(format string, args ...interface{}) { + if entry.Logger.level() >= WarnLevel { + entry.Warn(fmt.Sprintf(format, args...)) + } +} + +func (entry *Entry) Warningf(format string, args ...interface{}) { + entry.Warnf(format, args...) +} + +func (entry *Entry) Errorf(format string, args ...interface{}) { + if entry.Logger.level() >= ErrorLevel { + entry.Error(fmt.Sprintf(format, args...)) + } +} + +func (entry *Entry) Fatalf(format string, args ...interface{}) { + if entry.Logger.level() >= FatalLevel { + entry.Fatal(fmt.Sprintf(format, args...)) + } + Exit(1) +} + +func (entry *Entry) Panicf(format string, args ...interface{}) { + if entry.Logger.level() >= PanicLevel { + entry.Panic(fmt.Sprintf(format, args...)) + } +} + +// Entry Println family functions + +func (entry *Entry) Debugln(args ...interface{}) { + if entry.Logger.level() >= DebugLevel { + entry.Debug(entry.sprintlnn(args...)) + } +} + +func (entry *Entry) Infoln(args ...interface{}) { + if entry.Logger.level() >= InfoLevel { + entry.Info(entry.sprintlnn(args...)) + } +} + +func (entry *Entry) Println(args ...interface{}) { + entry.Infoln(args...) +} + +func (entry *Entry) Warnln(args ...interface{}) { + if entry.Logger.level() >= WarnLevel { + entry.Warn(entry.sprintlnn(args...)) + } +} + +func (entry *Entry) Warningln(args ...interface{}) { + entry.Warnln(args...) +} + +func (entry *Entry) Errorln(args ...interface{}) { + if entry.Logger.level() >= ErrorLevel { + entry.Error(entry.sprintlnn(args...)) + } +} + +func (entry *Entry) Fatalln(args ...interface{}) { + if entry.Logger.level() >= FatalLevel { + entry.Fatal(entry.sprintlnn(args...)) + } + Exit(1) +} + +func (entry *Entry) Panicln(args ...interface{}) { + if entry.Logger.level() >= PanicLevel { + entry.Panic(entry.sprintlnn(args...)) + } +} + +// Sprintlnn => Sprint no newline. This is to get the behavior of how +// fmt.Sprintln where spaces are always added between operands, regardless of +// their type. Instead of vendoring the Sprintln implementation to spare a +// string allocation, we do the simplest thing. +func (entry *Entry) sprintlnn(args ...interface{}) string { + msg := fmt.Sprintln(args...) + return msg[:len(msg)-1] +} diff --git a/vendor/github.com/Sirupsen/logrus/exported.go b/vendor/github.com/Sirupsen/logrus/exported.go new file mode 100644 index 0000000000..eb612a6f3e --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/exported.go @@ -0,0 +1,201 @@ +package logrus + +import ( + "io" + "time" +) + +var ( + // std is the name of the standard logger in stdlib `log` + std = New() +) + +func StandardLogger() *Logger { + return std +} + +// SetOutput sets the standard logger output. +func SetOutput(out io.Writer) { + std.SetOutput(out) +} + +// SetFormatter sets the standard logger formatter. +func SetFormatter(formatter Formatter) { + std.mu.Lock() + defer std.mu.Unlock() + std.Formatter = formatter +} + +// SetLevel sets the standard logger level. +func SetLevel(level Level) { + std.mu.Lock() + defer std.mu.Unlock() + std.SetLevel(level) +} + +// GetLevel returns the standard logger level. +func GetLevel() Level { + std.mu.Lock() + defer std.mu.Unlock() + return std.level() +} + +// AddHook adds a hook to the standard logger hooks. +func AddHook(hook Hook) { + std.mu.Lock() + defer std.mu.Unlock() + std.Hooks.Add(hook) +} + +// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key. +func WithError(err error) *Entry { + return std.WithField(ErrorKey, err) +} + +// WithField creates an entry from the standard logger and adds a field to +// it. If you want multiple fields, use `WithFields`. +// +// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal +// or Panic on the Entry it returns. +func WithField(key string, value interface{}) *Entry { + return std.WithField(key, value) +} + +// WithFields creates an entry from the standard logger and adds multiple +// fields to it. This is simply a helper for `WithField`, invoking it +// once for each field. +// +// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal +// or Panic on the Entry it returns. +func WithFields(fields Fields) *Entry { + return std.WithFields(fields) +} + +// WithTime creats an entry from the standard logger and overrides the time of +// logs generated with it. +// +// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal +// or Panic on the Entry it returns. +func WithTime(t time.Time) *Entry { + return std.WithTime(t) +} + +// Debug logs a message at level Debug on the standard logger. +func Debug(args ...interface{}) { + std.Debug(args...) +} + +// Print logs a message at level Info on the standard logger. +func Print(args ...interface{}) { + std.Print(args...) +} + +// Info logs a message at level Info on the standard logger. +func Info(args ...interface{}) { + std.Info(args...) +} + +// Warn logs a message at level Warn on the standard logger. +func Warn(args ...interface{}) { + std.Warn(args...) +} + +// Warning logs a message at level Warn on the standard logger. +func Warning(args ...interface{}) { + std.Warning(args...) +} + +// Error logs a message at level Error on the standard logger. +func Error(args ...interface{}) { + std.Error(args...) +} + +// Panic logs a message at level Panic on the standard logger. +func Panic(args ...interface{}) { + std.Panic(args...) +} + +// Fatal logs a message at level Fatal on the standard logger then the process will exit with status set to 1. +func Fatal(args ...interface{}) { + std.Fatal(args...) +} + +// Debugf logs a message at level Debug on the standard logger. +func Debugf(format string, args ...interface{}) { + std.Debugf(format, args...) +} + +// Printf logs a message at level Info on the standard logger. +func Printf(format string, args ...interface{}) { + std.Printf(format, args...) +} + +// Infof logs a message at level Info on the standard logger. +func Infof(format string, args ...interface{}) { + std.Infof(format, args...) +} + +// Warnf logs a message at level Warn on the standard logger. +func Warnf(format string, args ...interface{}) { + std.Warnf(format, args...) +} + +// Warningf logs a message at level Warn on the standard logger. +func Warningf(format string, args ...interface{}) { + std.Warningf(format, args...) +} + +// Errorf logs a message at level Error on the standard logger. +func Errorf(format string, args ...interface{}) { + std.Errorf(format, args...) +} + +// Panicf logs a message at level Panic on the standard logger. +func Panicf(format string, args ...interface{}) { + std.Panicf(format, args...) +} + +// Fatalf logs a message at level Fatal on the standard logger then the process will exit with status set to 1. +func Fatalf(format string, args ...interface{}) { + std.Fatalf(format, args...) +} + +// Debugln logs a message at level Debug on the standard logger. +func Debugln(args ...interface{}) { + std.Debugln(args...) +} + +// Println logs a message at level Info on the standard logger. +func Println(args ...interface{}) { + std.Println(args...) +} + +// Infoln logs a message at level Info on the standard logger. +func Infoln(args ...interface{}) { + std.Infoln(args...) +} + +// Warnln logs a message at level Warn on the standard logger. +func Warnln(args ...interface{}) { + std.Warnln(args...) +} + +// Warningln logs a message at level Warn on the standard logger. +func Warningln(args ...interface{}) { + std.Warningln(args...) +} + +// Errorln logs a message at level Error on the standard logger. +func Errorln(args ...interface{}) { + std.Errorln(args...) +} + +// Panicln logs a message at level Panic on the standard logger. +func Panicln(args ...interface{}) { + std.Panicln(args...) +} + +// Fatalln logs a message at level Fatal on the standard logger then the process will exit with status set to 1. +func Fatalln(args ...interface{}) { + std.Fatalln(args...) +} diff --git a/vendor/github.com/Sirupsen/logrus/formatter.go b/vendor/github.com/Sirupsen/logrus/formatter.go new file mode 100644 index 0000000000..83c74947be --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/formatter.go @@ -0,0 +1,51 @@ +package logrus + +import "time" + +const defaultTimestampFormat = time.RFC3339 + +// The Formatter interface is used to implement a custom Formatter. It takes an +// `Entry`. It exposes all the fields, including the default ones: +// +// * `entry.Data["msg"]`. The message passed from Info, Warn, Error .. +// * `entry.Data["time"]`. The timestamp. +// * `entry.Data["level"]. The level the entry was logged at. +// +// Any additional fields added with `WithField` or `WithFields` are also in +// `entry.Data`. Format is expected to return an array of bytes which are then +// logged to `logger.Out`. +type Formatter interface { + Format(*Entry) ([]byte, error) +} + +// This is to not silently overwrite `time`, `msg` and `level` fields when +// dumping it. If this code wasn't there doing: +// +// logrus.WithField("level", 1).Info("hello") +// +// Would just silently drop the user provided level. Instead with this code +// it'll logged as: +// +// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."} +// +// It's not exported because it's still using Data in an opinionated way. It's to +// avoid code duplication between the two default formatters. +func prefixFieldClashes(data Fields, fieldMap FieldMap) { + timeKey := fieldMap.resolve(FieldKeyTime) + if t, ok := data[timeKey]; ok { + data["fields."+timeKey] = t + delete(data, timeKey) + } + + msgKey := fieldMap.resolve(FieldKeyMsg) + if m, ok := data[msgKey]; ok { + data["fields."+msgKey] = m + delete(data, msgKey) + } + + levelKey := fieldMap.resolve(FieldKeyLevel) + if l, ok := data[levelKey]; ok { + data["fields."+levelKey] = l + delete(data, levelKey) + } +} diff --git a/vendor/github.com/Sirupsen/logrus/hooks.go b/vendor/github.com/Sirupsen/logrus/hooks.go new file mode 100644 index 0000000000..3f151cdc39 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/hooks.go @@ -0,0 +1,34 @@ +package logrus + +// A hook to be fired when logging on the logging levels returned from +// `Levels()` on your implementation of the interface. Note that this is not +// fired in a goroutine or a channel with workers, you should handle such +// functionality yourself if your call is non-blocking and you don't wish for +// the logging calls for levels returned from `Levels()` to block. +type Hook interface { + Levels() []Level + Fire(*Entry) error +} + +// Internal type for storing the hooks on a logger instance. +type LevelHooks map[Level][]Hook + +// Add a hook to an instance of logger. This is called with +// `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface. +func (hooks LevelHooks) Add(hook Hook) { + for _, level := range hook.Levels() { + hooks[level] = append(hooks[level], hook) + } +} + +// Fire all the hooks for the passed level. Used by `entry.log` to fire +// appropriate hooks for a log entry. +func (hooks LevelHooks) Fire(level Level, entry *Entry) error { + for _, hook := range hooks[level] { + if err := hook.Fire(entry); err != nil { + return err + } + } + + return nil +} diff --git a/vendor/github.com/Sirupsen/logrus/json_formatter.go b/vendor/github.com/Sirupsen/logrus/json_formatter.go new file mode 100644 index 0000000000..b13f0cda35 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/json_formatter.go @@ -0,0 +1,96 @@ +package logrus + +import ( + "bytes" + "encoding/json" + "fmt" +) + +type fieldKey string + +// FieldMap allows customization of the key names for default fields. +type FieldMap map[fieldKey]string + +// Default key names for the default fields +const ( + FieldKeyMsg = "msg" + FieldKeyLevel = "level" + FieldKeyTime = "time" +) + +func (f FieldMap) resolve(key fieldKey) string { + if k, ok := f[key]; ok { + return k + } + + return string(key) +} + +// JSONFormatter formats logs into parsable json +type JSONFormatter struct { + // TimestampFormat sets the format used for marshaling timestamps. + TimestampFormat string + + // DisableTimestamp allows disabling automatic timestamps in output + DisableTimestamp bool + + // DataKey allows users to put all the log entry parameters into a nested dictionary at a given key. + DataKey string + + // FieldMap allows users to customize the names of keys for default fields. + // As an example: + // formatter := &JSONFormatter{ + // FieldMap: FieldMap{ + // FieldKeyTime: "@timestamp", + // FieldKeyLevel: "@level", + // FieldKeyMsg: "@message", + // }, + // } + FieldMap FieldMap +} + +// Format renders a single log entry +func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { + data := make(Fields, len(entry.Data)+3) + for k, v := range entry.Data { + switch v := v.(type) { + case error: + // Otherwise errors are ignored by `encoding/json` + // https://github.com/sirupsen/logrus/issues/137 + data[k] = v.Error() + default: + data[k] = v + } + } + + if f.DataKey != "" { + newData := make(Fields, 4) + newData[f.DataKey] = data + data = newData + } + + prefixFieldClashes(data, f.FieldMap) + + timestampFormat := f.TimestampFormat + if timestampFormat == "" { + timestampFormat = defaultTimestampFormat + } + + if !f.DisableTimestamp { + data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat) + } + data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message + data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String() + + var b *bytes.Buffer + if entry.Buffer != nil { + b = entry.Buffer + } else { + b = &bytes.Buffer{} + } + err := json.NewEncoder(b).Encode(data) + if err != nil { + return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) + } + return b.Bytes(), nil +} diff --git a/vendor/github.com/Sirupsen/logrus/logger.go b/vendor/github.com/Sirupsen/logrus/logger.go new file mode 100644 index 0000000000..7fa8d7d92a --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/logger.go @@ -0,0 +1,338 @@ +package logrus + +import ( + "io" + "os" + "sync" + "sync/atomic" + "time" +) + +type Logger struct { + // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a + // file, or leave it default which is `os.Stderr`. You can also set this to + // something more adventorous, such as logging to Kafka. + Out io.Writer + // Hooks for the logger instance. These allow firing events based on logging + // levels and log entries. For example, to send errors to an error tracking + // service, log to StatsD or dump the core on fatal errors. + Hooks LevelHooks + // All log entries pass through the formatter before logged to Out. The + // included formatters are `TextFormatter` and `JSONFormatter` for which + // TextFormatter is the default. In development (when a TTY is attached) it + // logs with colors, but to a file it wouldn't. You can easily implement your + // own that implements the `Formatter` interface, see the `README` or included + // formatters for examples. + Formatter Formatter + // The logging level the logger should log at. This is typically (and defaults + // to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be + // logged. + Level Level + // Used to sync writing to the log. Locking is enabled by Default + mu MutexWrap + // Reusable empty entry + entryPool sync.Pool +} + +type MutexWrap struct { + lock sync.Mutex + disabled bool +} + +func (mw *MutexWrap) Lock() { + if !mw.disabled { + mw.lock.Lock() + } +} + +func (mw *MutexWrap) Unlock() { + if !mw.disabled { + mw.lock.Unlock() + } +} + +func (mw *MutexWrap) Disable() { + mw.disabled = true +} + +// Creates a new logger. Configuration should be set by changing `Formatter`, +// `Out` and `Hooks` directly on the default logger instance. You can also just +// instantiate your own: +// +// var log = &Logger{ +// Out: os.Stderr, +// Formatter: new(JSONFormatter), +// Hooks: make(LevelHooks), +// Level: logrus.DebugLevel, +// } +// +// It's recommended to make this a global instance called `log`. +func New() *Logger { + return &Logger{ + Out: os.Stderr, + Formatter: new(TextFormatter), + Hooks: make(LevelHooks), + Level: InfoLevel, + } +} + +func (logger *Logger) newEntry() *Entry { + entry, ok := logger.entryPool.Get().(*Entry) + if ok { + return entry + } + return NewEntry(logger) +} + +func (logger *Logger) releaseEntry(entry *Entry) { + entry.Data = map[string]interface{}{} + logger.entryPool.Put(entry) +} + +// Adds a field to the log entry, note that it doesn't log until you call +// Debug, Print, Info, Warn, Error, Fatal or Panic. It only creates a log entry. +// If you want multiple fields, use `WithFields`. +func (logger *Logger) WithField(key string, value interface{}) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithField(key, value) +} + +// Adds a struct of fields to the log entry. All it does is call `WithField` for +// each `Field`. +func (logger *Logger) WithFields(fields Fields) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithFields(fields) +} + +// Add an error as single field to the log entry. All it does is call +// `WithError` for the given `error`. +func (logger *Logger) WithError(err error) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithError(err) +} + +// Overrides the time of the log entry. +func (logger *Logger) WithTime(t time.Time) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithTime(t) +} + +func (logger *Logger) Debugf(format string, args ...interface{}) { + if logger.level() >= DebugLevel { + entry := logger.newEntry() + entry.Debugf(format, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Infof(format string, args ...interface{}) { + if logger.level() >= InfoLevel { + entry := logger.newEntry() + entry.Infof(format, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Printf(format string, args ...interface{}) { + entry := logger.newEntry() + entry.Printf(format, args...) + logger.releaseEntry(entry) +} + +func (logger *Logger) Warnf(format string, args ...interface{}) { + if logger.level() >= WarnLevel { + entry := logger.newEntry() + entry.Warnf(format, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Warningf(format string, args ...interface{}) { + if logger.level() >= WarnLevel { + entry := logger.newEntry() + entry.Warnf(format, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Errorf(format string, args ...interface{}) { + if logger.level() >= ErrorLevel { + entry := logger.newEntry() + entry.Errorf(format, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Fatalf(format string, args ...interface{}) { + if logger.level() >= FatalLevel { + entry := logger.newEntry() + entry.Fatalf(format, args...) + logger.releaseEntry(entry) + } + Exit(1) +} + +func (logger *Logger) Panicf(format string, args ...interface{}) { + if logger.level() >= PanicLevel { + entry := logger.newEntry() + entry.Panicf(format, args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Debug(args ...interface{}) { + if logger.level() >= DebugLevel { + entry := logger.newEntry() + entry.Debug(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Info(args ...interface{}) { + if logger.level() >= InfoLevel { + entry := logger.newEntry() + entry.Info(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Print(args ...interface{}) { + entry := logger.newEntry() + entry.Info(args...) + logger.releaseEntry(entry) +} + +func (logger *Logger) Warn(args ...interface{}) { + if logger.level() >= WarnLevel { + entry := logger.newEntry() + entry.Warn(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Warning(args ...interface{}) { + if logger.level() >= WarnLevel { + entry := logger.newEntry() + entry.Warn(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Error(args ...interface{}) { + if logger.level() >= ErrorLevel { + entry := logger.newEntry() + entry.Error(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Fatal(args ...interface{}) { + if logger.level() >= FatalLevel { + entry := logger.newEntry() + entry.Fatal(args...) + logger.releaseEntry(entry) + } + Exit(1) +} + +func (logger *Logger) Panic(args ...interface{}) { + if logger.level() >= PanicLevel { + entry := logger.newEntry() + entry.Panic(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Debugln(args ...interface{}) { + if logger.level() >= DebugLevel { + entry := logger.newEntry() + entry.Debugln(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Infoln(args ...interface{}) { + if logger.level() >= InfoLevel { + entry := logger.newEntry() + entry.Infoln(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Println(args ...interface{}) { + entry := logger.newEntry() + entry.Println(args...) + logger.releaseEntry(entry) +} + +func (logger *Logger) Warnln(args ...interface{}) { + if logger.level() >= WarnLevel { + entry := logger.newEntry() + entry.Warnln(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Warningln(args ...interface{}) { + if logger.level() >= WarnLevel { + entry := logger.newEntry() + entry.Warnln(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Errorln(args ...interface{}) { + if logger.level() >= ErrorLevel { + entry := logger.newEntry() + entry.Errorln(args...) + logger.releaseEntry(entry) + } +} + +func (logger *Logger) Fatalln(args ...interface{}) { + if logger.level() >= FatalLevel { + entry := logger.newEntry() + entry.Fatalln(args...) + logger.releaseEntry(entry) + } + Exit(1) +} + +func (logger *Logger) Panicln(args ...interface{}) { + if logger.level() >= PanicLevel { + entry := logger.newEntry() + entry.Panicln(args...) + logger.releaseEntry(entry) + } +} + +//When file is opened with appending mode, it's safe to +//write concurrently to a file (within 4k message on Linux). +//In these cases user can choose to disable the lock. +func (logger *Logger) SetNoLock() { + logger.mu.Disable() +} + +func (logger *Logger) level() Level { + return Level(atomic.LoadUint32((*uint32)(&logger.Level))) +} + +func (logger *Logger) SetLevel(level Level) { + atomic.StoreUint32((*uint32)(&logger.Level), uint32(level)) +} + +func (logger *Logger) SetOutput(out io.Writer) { + logger.mu.Lock() + defer logger.mu.Unlock() + logger.Out = out +} + +func (logger *Logger) AddHook(hook Hook) { + logger.mu.Lock() + defer logger.mu.Unlock() + logger.Hooks.Add(hook) +} diff --git a/vendor/github.com/Sirupsen/logrus/logrus.go b/vendor/github.com/Sirupsen/logrus/logrus.go new file mode 100644 index 0000000000..dd38999741 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/logrus.go @@ -0,0 +1,143 @@ +package logrus + +import ( + "fmt" + "log" + "strings" +) + +// Fields type, used to pass to `WithFields`. +type Fields map[string]interface{} + +// Level type +type Level uint32 + +// Convert the Level to a string. E.g. PanicLevel becomes "panic". +func (level Level) String() string { + switch level { + case DebugLevel: + return "debug" + case InfoLevel: + return "info" + case WarnLevel: + return "warning" + case ErrorLevel: + return "error" + case FatalLevel: + return "fatal" + case PanicLevel: + return "panic" + } + + return "unknown" +} + +// ParseLevel takes a string level and returns the Logrus log level constant. +func ParseLevel(lvl string) (Level, error) { + switch strings.ToLower(lvl) { + case "panic": + return PanicLevel, nil + case "fatal": + return FatalLevel, nil + case "error": + return ErrorLevel, nil + case "warn", "warning": + return WarnLevel, nil + case "info": + return InfoLevel, nil + case "debug": + return DebugLevel, nil + } + + var l Level + return l, fmt.Errorf("not a valid logrus Level: %q", lvl) +} + +// A constant exposing all logging levels +var AllLevels = []Level{ + PanicLevel, + FatalLevel, + ErrorLevel, + WarnLevel, + InfoLevel, + DebugLevel, +} + +// These are the different logging levels. You can set the logging level to log +// on your instance of logger, obtained with `logrus.New()`. +const ( + // PanicLevel level, highest level of severity. Logs and then calls panic with the + // message passed to Debug, Info, ... + PanicLevel Level = iota + // FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the + // logging level is set to Panic. + FatalLevel + // ErrorLevel level. Logs. Used for errors that should definitely be noted. + // Commonly used for hooks to send errors to an error tracking service. + ErrorLevel + // WarnLevel level. Non-critical entries that deserve eyes. + WarnLevel + // InfoLevel level. General operational entries about what's going on inside the + // application. + InfoLevel + // DebugLevel level. Usually only enabled when debugging. Very verbose logging. + DebugLevel +) + +// Won't compile if StdLogger can't be realized by a log.Logger +var ( + _ StdLogger = &log.Logger{} + _ StdLogger = &Entry{} + _ StdLogger = &Logger{} +) + +// StdLogger is what your logrus-enabled library should take, that way +// it'll accept a stdlib logger and a logrus logger. There's no standard +// interface, this is the closest we get, unfortunately. +type StdLogger interface { + Print(...interface{}) + Printf(string, ...interface{}) + Println(...interface{}) + + Fatal(...interface{}) + Fatalf(string, ...interface{}) + Fatalln(...interface{}) + + Panic(...interface{}) + Panicf(string, ...interface{}) + Panicln(...interface{}) +} + +// The FieldLogger interface generalizes the Entry and Logger types +type FieldLogger interface { + WithField(key string, value interface{}) *Entry + WithFields(fields Fields) *Entry + WithError(err error) *Entry + + Debugf(format string, args ...interface{}) + Infof(format string, args ...interface{}) + Printf(format string, args ...interface{}) + Warnf(format string, args ...interface{}) + Warningf(format string, args ...interface{}) + Errorf(format string, args ...interface{}) + Fatalf(format string, args ...interface{}) + Panicf(format string, args ...interface{}) + + Debug(args ...interface{}) + Info(args ...interface{}) + Print(args ...interface{}) + Warn(args ...interface{}) + Warning(args ...interface{}) + Error(args ...interface{}) + Fatal(args ...interface{}) + Panic(args ...interface{}) + + Debugln(args ...interface{}) + Infoln(args ...interface{}) + Println(args ...interface{}) + Warnln(args ...interface{}) + Warningln(args ...interface{}) + Errorln(args ...interface{}) + Fatalln(args ...interface{}) + Panicln(args ...interface{}) +} diff --git a/vendor/github.com/Sirupsen/logrus/terminal_bsd.go b/vendor/github.com/Sirupsen/logrus/terminal_bsd.go new file mode 100644 index 0000000000..5b6212d24c --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/terminal_bsd.go @@ -0,0 +1,10 @@ +// +build darwin freebsd openbsd netbsd dragonfly +// +build !appengine,!js + +package logrus + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TIOCGETA + +type Termios unix.Termios diff --git a/vendor/github.com/Sirupsen/logrus/terminal_check_appengine.go b/vendor/github.com/Sirupsen/logrus/terminal_check_appengine.go new file mode 100644 index 0000000000..2403de9819 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/terminal_check_appengine.go @@ -0,0 +1,11 @@ +// +build appengine + +package logrus + +import ( + "io" +) + +func checkIfTerminal(w io.Writer) bool { + return true +} diff --git a/vendor/github.com/Sirupsen/logrus/terminal_check_js.go b/vendor/github.com/Sirupsen/logrus/terminal_check_js.go new file mode 100644 index 0000000000..0c209750a3 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/terminal_check_js.go @@ -0,0 +1,11 @@ +// +build js + +package logrus + +import ( + "io" +) + +func checkIfTerminal(w io.Writer) bool { + return false +} diff --git a/vendor/github.com/Sirupsen/logrus/terminal_check_notappengine.go b/vendor/github.com/Sirupsen/logrus/terminal_check_notappengine.go new file mode 100644 index 0000000000..87f0b8097f --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/terminal_check_notappengine.go @@ -0,0 +1,19 @@ +// +build !appengine,!js + +package logrus + +import ( + "io" + "os" + + "golang.org/x/crypto/ssh/terminal" +) + +func checkIfTerminal(w io.Writer) bool { + switch v := w.(type) { + case *os.File: + return terminal.IsTerminal(int(v.Fd())) + default: + return false + } +} diff --git a/vendor/github.com/Sirupsen/logrus/terminal_linux.go b/vendor/github.com/Sirupsen/logrus/terminal_linux.go new file mode 100644 index 0000000000..634e39b301 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/terminal_linux.go @@ -0,0 +1,14 @@ +// Based on ssh/terminal: +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine,!js + +package logrus + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TCGETS + +type Termios unix.Termios diff --git a/vendor/github.com/Sirupsen/logrus/text_formatter.go b/vendor/github.com/Sirupsen/logrus/text_formatter.go new file mode 100644 index 0000000000..beb628f3a6 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/text_formatter.go @@ -0,0 +1,213 @@ +package logrus + +import ( + "bytes" + "fmt" + "os" + "sort" + "strings" + "sync" + "time" +) + +const ( + nocolor = 0 + red = 31 + green = 32 + yellow = 33 + blue = 36 + gray = 37 +) + +var ( + baseTimestamp time.Time + emptyFieldMap FieldMap +) + +func init() { + baseTimestamp = time.Now() +} + +// TextFormatter formats logs into text +type TextFormatter struct { + // Set to true to bypass checking for a TTY before outputting colors. + ForceColors bool + + // Force disabling colors. + DisableColors bool + + // Override coloring based on CLICOLOR and CLICOLOR_FORCE. - https://bixense.com/clicolors/ + EnvironmentOverrideColors bool + + // Disable timestamp logging. useful when output is redirected to logging + // system that already adds timestamps. + DisableTimestamp bool + + // Enable logging the full timestamp when a TTY is attached instead of just + // the time passed since beginning of execution. + FullTimestamp bool + + // TimestampFormat to use for display when a full timestamp is printed + TimestampFormat string + + // The fields are sorted by default for a consistent output. For applications + // that log extremely frequently and don't use the JSON formatter this may not + // be desired. + DisableSorting bool + + // Disables the truncation of the level text to 4 characters. + DisableLevelTruncation bool + + // QuoteEmptyFields will wrap empty fields in quotes if true + QuoteEmptyFields bool + + // Whether the logger's out is to a terminal + isTerminal bool + + // FieldMap allows users to customize the names of keys for default fields. + // As an example: + // formatter := &TextFormatter{ + // FieldMap: FieldMap{ + // FieldKeyTime: "@timestamp", + // FieldKeyLevel: "@level", + // FieldKeyMsg: "@message"}} + FieldMap FieldMap + + sync.Once +} + +func (f *TextFormatter) init(entry *Entry) { + if entry.Logger != nil { + f.isTerminal = checkIfTerminal(entry.Logger.Out) + } +} + +func (f *TextFormatter) isColored() bool { + isColored := f.ForceColors || f.isTerminal + + if f.EnvironmentOverrideColors { + if force, ok := os.LookupEnv("CLICOLOR_FORCE"); ok && force != "0" { + isColored = true + } else if ok && force == "0" { + isColored = false + } else if os.Getenv("CLICOLOR") == "0" { + isColored = false + } + } + + return isColored && !f.DisableColors +} + +// Format renders a single log entry +func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { + prefixFieldClashes(entry.Data, f.FieldMap) + + keys := make([]string, 0, len(entry.Data)) + for k := range entry.Data { + keys = append(keys, k) + } + + if !f.DisableSorting { + sort.Strings(keys) + } + + var b *bytes.Buffer + if entry.Buffer != nil { + b = entry.Buffer + } else { + b = &bytes.Buffer{} + } + + f.Do(func() { f.init(entry) }) + + timestampFormat := f.TimestampFormat + if timestampFormat == "" { + timestampFormat = defaultTimestampFormat + } + if f.isColored() { + f.printColored(b, entry, keys, timestampFormat) + } else { + if !f.DisableTimestamp { + f.appendKeyValue(b, f.FieldMap.resolve(FieldKeyTime), entry.Time.Format(timestampFormat)) + } + f.appendKeyValue(b, f.FieldMap.resolve(FieldKeyLevel), entry.Level.String()) + if entry.Message != "" { + f.appendKeyValue(b, f.FieldMap.resolve(FieldKeyMsg), entry.Message) + } + for _, key := range keys { + f.appendKeyValue(b, key, entry.Data[key]) + } + } + + b.WriteByte('\n') + return b.Bytes(), nil +} + +func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) { + var levelColor int + switch entry.Level { + case DebugLevel: + levelColor = gray + case WarnLevel: + levelColor = yellow + case ErrorLevel, FatalLevel, PanicLevel: + levelColor = red + default: + levelColor = blue + } + + levelText := strings.ToUpper(entry.Level.String()) + if !f.DisableLevelTruncation { + levelText = levelText[0:4] + } + + if f.DisableTimestamp { + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m %-44s ", levelColor, levelText, entry.Message) + } else if !f.FullTimestamp { + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), entry.Message) + } else { + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message) + } + for _, k := range keys { + v := entry.Data[k] + fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k) + f.appendValue(b, v) + } +} + +func (f *TextFormatter) needsQuoting(text string) bool { + if f.QuoteEmptyFields && len(text) == 0 { + return true + } + for _, ch := range text { + if !((ch >= 'a' && ch <= 'z') || + (ch >= 'A' && ch <= 'Z') || + (ch >= '0' && ch <= '9') || + ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '@' || ch == '^' || ch == '+') { + return true + } + } + return false +} + +func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) { + if b.Len() > 0 { + b.WriteByte(' ') + } + b.WriteString(key) + b.WriteByte('=') + f.appendValue(b, value) +} + +func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) { + stringVal, ok := value.(string) + if !ok { + stringVal = fmt.Sprint(value) + } + + if !f.needsQuoting(stringVal) { + b.WriteString(stringVal) + } else { + b.WriteString(fmt.Sprintf("%q", stringVal)) + } +} diff --git a/vendor/github.com/Sirupsen/logrus/writer.go b/vendor/github.com/Sirupsen/logrus/writer.go new file mode 100644 index 0000000000..7bdebedc60 --- /dev/null +++ b/vendor/github.com/Sirupsen/logrus/writer.go @@ -0,0 +1,62 @@ +package logrus + +import ( + "bufio" + "io" + "runtime" +) + +func (logger *Logger) Writer() *io.PipeWriter { + return logger.WriterLevel(InfoLevel) +} + +func (logger *Logger) WriterLevel(level Level) *io.PipeWriter { + return NewEntry(logger).WriterLevel(level) +} + +func (entry *Entry) Writer() *io.PipeWriter { + return entry.WriterLevel(InfoLevel) +} + +func (entry *Entry) WriterLevel(level Level) *io.PipeWriter { + reader, writer := io.Pipe() + + var printFunc func(args ...interface{}) + + switch level { + case DebugLevel: + printFunc = entry.Debug + case InfoLevel: + printFunc = entry.Info + case WarnLevel: + printFunc = entry.Warn + case ErrorLevel: + printFunc = entry.Error + case FatalLevel: + printFunc = entry.Fatal + case PanicLevel: + printFunc = entry.Panic + default: + printFunc = entry.Print + } + + go entry.writerScanner(reader, printFunc) + runtime.SetFinalizer(writer, writerFinalizer) + + return writer +} + +func (entry *Entry) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) { + scanner := bufio.NewScanner(reader) + for scanner.Scan() { + printFunc(scanner.Text()) + } + if err := scanner.Err(); err != nil { + entry.Errorf("Error while reading from Writer: %s", err) + } + reader.Close() +} + +func writerFinalizer(writer *io.PipeWriter) { + writer.Close() +} diff --git a/vendor/github.com/inconshreveable/mousetrap/LICENSE b/vendor/github.com/inconshreveable/mousetrap/LICENSE new file mode 100644 index 0000000000..5f0d1fb6a7 --- /dev/null +++ b/vendor/github.com/inconshreveable/mousetrap/LICENSE @@ -0,0 +1,13 @@ +Copyright 2014 Alan Shreve + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/github.com/inconshreveable/mousetrap/README.md b/vendor/github.com/inconshreveable/mousetrap/README.md new file mode 100644 index 0000000000..7a950d1774 --- /dev/null +++ b/vendor/github.com/inconshreveable/mousetrap/README.md @@ -0,0 +1,23 @@ +# mousetrap + +mousetrap is a tiny library that answers a single question. + +On a Windows machine, was the process invoked by someone double clicking on +the executable file while browsing in explorer? + +### Motivation + +Windows developers unfamiliar with command line tools will often "double-click" +the executable for a tool. Because most CLI tools print the help and then exit +when invoked without arguments, this is often very frustrating for those users. + +mousetrap provides a way to detect these invocations so that you can provide +more helpful behavior and instructions on how to run the CLI tool. To see what +this looks like, both from an organizational and a technical perspective, see +https://inconshreveable.com/09-09-2014/sweat-the-small-stuff/ + +### The interface + +The library exposes a single interface: + + func StartedByExplorer() (bool) diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_others.go b/vendor/github.com/inconshreveable/mousetrap/trap_others.go new file mode 100644 index 0000000000..9d2d8a4bab --- /dev/null +++ b/vendor/github.com/inconshreveable/mousetrap/trap_others.go @@ -0,0 +1,15 @@ +// +build !windows + +package mousetrap + +// StartedByExplorer returns true if the program was invoked by the user +// double-clicking on the executable from explorer.exe +// +// It is conservative and returns false if any of the internal calls fail. +// It does not guarantee that the program was run from a terminal. It only can tell you +// whether it was launched from explorer.exe +// +// On non-Windows platforms, it always returns false. +func StartedByExplorer() bool { + return false +} diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_windows.go b/vendor/github.com/inconshreveable/mousetrap/trap_windows.go new file mode 100644 index 0000000000..336142a5e3 --- /dev/null +++ b/vendor/github.com/inconshreveable/mousetrap/trap_windows.go @@ -0,0 +1,98 @@ +// +build windows +// +build !go1.4 + +package mousetrap + +import ( + "fmt" + "os" + "syscall" + "unsafe" +) + +const ( + // defined by the Win32 API + th32cs_snapprocess uintptr = 0x2 +) + +var ( + kernel = syscall.MustLoadDLL("kernel32.dll") + CreateToolhelp32Snapshot = kernel.MustFindProc("CreateToolhelp32Snapshot") + Process32First = kernel.MustFindProc("Process32FirstW") + Process32Next = kernel.MustFindProc("Process32NextW") +) + +// ProcessEntry32 structure defined by the Win32 API +type processEntry32 struct { + dwSize uint32 + cntUsage uint32 + th32ProcessID uint32 + th32DefaultHeapID int + th32ModuleID uint32 + cntThreads uint32 + th32ParentProcessID uint32 + pcPriClassBase int32 + dwFlags uint32 + szExeFile [syscall.MAX_PATH]uint16 +} + +func getProcessEntry(pid int) (pe *processEntry32, err error) { + snapshot, _, e1 := CreateToolhelp32Snapshot.Call(th32cs_snapprocess, uintptr(0)) + if snapshot == uintptr(syscall.InvalidHandle) { + err = fmt.Errorf("CreateToolhelp32Snapshot: %v", e1) + return + } + defer syscall.CloseHandle(syscall.Handle(snapshot)) + + var processEntry processEntry32 + processEntry.dwSize = uint32(unsafe.Sizeof(processEntry)) + ok, _, e1 := Process32First.Call(snapshot, uintptr(unsafe.Pointer(&processEntry))) + if ok == 0 { + err = fmt.Errorf("Process32First: %v", e1) + return + } + + for { + if processEntry.th32ProcessID == uint32(pid) { + pe = &processEntry + return + } + + ok, _, e1 = Process32Next.Call(snapshot, uintptr(unsafe.Pointer(&processEntry))) + if ok == 0 { + err = fmt.Errorf("Process32Next: %v", e1) + return + } + } +} + +func getppid() (pid int, err error) { + pe, err := getProcessEntry(os.Getpid()) + if err != nil { + return + } + + pid = int(pe.th32ParentProcessID) + return +} + +// StartedByExplorer returns true if the program was invoked by the user double-clicking +// on the executable from explorer.exe +// +// It is conservative and returns false if any of the internal calls fail. +// It does not guarantee that the program was run from a terminal. It only can tell you +// whether it was launched from explorer.exe +func StartedByExplorer() bool { + ppid, err := getppid() + if err != nil { + return false + } + + pe, err := getProcessEntry(ppid) + if err != nil { + return false + } + + name := syscall.UTF16ToString(pe.szExeFile[:]) + return name == "explorer.exe" +} diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go b/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go new file mode 100644 index 0000000000..9a28e57c3c --- /dev/null +++ b/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go @@ -0,0 +1,46 @@ +// +build windows +// +build go1.4 + +package mousetrap + +import ( + "os" + "syscall" + "unsafe" +) + +func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) { + snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0) + if err != nil { + return nil, err + } + defer syscall.CloseHandle(snapshot) + var procEntry syscall.ProcessEntry32 + procEntry.Size = uint32(unsafe.Sizeof(procEntry)) + if err = syscall.Process32First(snapshot, &procEntry); err != nil { + return nil, err + } + for { + if procEntry.ProcessID == uint32(pid) { + return &procEntry, nil + } + err = syscall.Process32Next(snapshot, &procEntry) + if err != nil { + return nil, err + } + } +} + +// StartedByExplorer returns true if the program was invoked by the user double-clicking +// on the executable from explorer.exe +// +// It is conservative and returns false if any of the internal calls fail. +// It does not guarantee that the program was run from a terminal. It only can tell you +// whether it was launched from explorer.exe +func StartedByExplorer() bool { + pe, err := getProcessEntry(os.Getppid()) + if err != nil { + return false + } + return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:]) +} diff --git a/vendor/github.com/moul/http2curl/LICENSE b/vendor/github.com/moul/http2curl/LICENSE new file mode 100644 index 0000000000..492e2c629a --- /dev/null +++ b/vendor/github.com/moul/http2curl/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Manfred Touron + +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. + diff --git a/vendor/github.com/moul/http2curl/Makefile b/vendor/github.com/moul/http2curl/Makefile new file mode 100644 index 0000000000..7b1cd613ba --- /dev/null +++ b/vendor/github.com/moul/http2curl/Makefile @@ -0,0 +1,50 @@ +# Project-specific variables +CONVEY_PORT ?= 9042 + + +# Common variables +SOURCES := $(shell find . -type f -name "*.go") +COMMANDS := $(shell go list ./... | grep -v /vendor/ | grep /cmd/) +PACKAGES := $(shell go list ./... | grep -v /vendor/ | grep -v /cmd/) +GOENV ?= GO15VENDOREXPERIMENT=1 +GO ?= $(GOENV) go +GODEP ?= $(GOENV) godep +USER ?= $(shell whoami) + + +all: build + + +.PHONY: build +build: + echo "nothing to do" + + +.PHONY: test +test: + $(GO) get -t . + $(GO) test -v . + + +.PHONY: godep-save +godep-save: + $(GODEP) save $(PACKAGES) $(COMMANDS) + + +.PHONY: re +re: clean all + + +.PHONY: convey +convey: + $(GO) get github.com/smartystreets/goconvey + goconvey -cover -port=$(CONVEY_PORT) -workDir="$(realpath .)" -depth=1 + + +.PHONY: cover +cover: profile.out + + +profile.out: $(SOURCES) + rm -f $@ + $(GO) test -covermode=count -coverpkg=. -coverprofile=$@ . diff --git a/vendor/github.com/moul/http2curl/README.md b/vendor/github.com/moul/http2curl/README.md new file mode 100644 index 0000000000..beaf43dfab --- /dev/null +++ b/vendor/github.com/moul/http2curl/README.md @@ -0,0 +1,42 @@ +# http2curl +:triangular_ruler: Convert Golang's http.Request to CURL command line + +[![Build Status](https://travis-ci.org/moul/http2curl.svg?branch=master)](https://travis-ci.org/moul/http2curl) +[![GoDoc](https://godoc.org/github.com/moul/http2curl?status.svg)](https://godoc.org/github.com/moul/http2curl) +[![Coverage Status](https://coveralls.io/repos/moul/http2curl/badge.svg)](https://coveralls.io/github/moul/http2curl) + +To do the reverse, check out [mholt/curl-to-go](https://github.com/mholt/curl-to-go). + +## Example + +```go +import "http" +import "github.com/moul/http2curl" + +data := bytes.NewBufferString(`{"hello":"world","answer":42}`) +req, _ := http.NewRequest("PUT", "http://www.example.com/abc/def.ghi?jlk=mno&pqr=stu", data) +req.Header.Set("Content-Type", "application/json") + +command, _ := http2curl.GetCurlCommand(req) +fmt.Println(command) +// Output: curl -X PUT -d "{\"hello\":\"world\",\"answer\":42}" -H "Content-Type: application/json" http://www.example.com/abc/def.ghi?jlk=mno&pqr=stu +``` + +## Install + +```php +$ go get github.com/moul/http2curl +``` + +## Usages + +- https://github.com/parnurzeal/gorequest +- https://github.com/scaleway/scaleway-cli +- https://github.com/nmonterroso/cowsay-slackapp +- https://github.com/moul/as-a-service +- https://github.com/gavv/httpexpect +- https://github.com/smallnest/goreq + +## License + +MIT diff --git a/vendor/github.com/moul/http2curl/http2curl.go b/vendor/github.com/moul/http2curl/http2curl.go new file mode 100644 index 0000000000..1eb5be6054 --- /dev/null +++ b/vendor/github.com/moul/http2curl/http2curl.go @@ -0,0 +1,71 @@ +package http2curl + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "net/http" + "sort" + "strings" +) + +// CurlCommand contains exec.Command compatible slice + helpers +type CurlCommand struct { + slice []string +} + +// append appends a string to the CurlCommand +func (c *CurlCommand) append(newSlice ...string) { + c.slice = append(c.slice, newSlice...) +} + +// String returns a ready to copy/paste command +func (c *CurlCommand) String() string { + return strings.Join(c.slice, " ") +} + +// nopCloser is used to create a new io.ReadCloser for req.Body +type nopCloser struct { + io.Reader +} + +func bashEscape(str string) string { + return `'` + strings.Replace(str, `'`, `'\''`, -1) + `'` +} + +func (nopCloser) Close() error { return nil } + +// GetCurlCommand returns a CurlCommand corresponding to an http.Request +func GetCurlCommand(req *http.Request) (*CurlCommand, error) { + command := CurlCommand{} + + command.append("curl") + + command.append("-X", bashEscape(req.Method)) + + if req.Body != nil { + body, err := ioutil.ReadAll(req.Body) + if err != nil { + return nil, err + } + req.Body = nopCloser{bytes.NewBuffer(body)} + bodyEscaped := bashEscape(string(body)) + command.append("-d", bodyEscaped) + } + + var keys []string + + for k := range req.Header { + keys = append(keys, k) + } + sort.Strings(keys) + + for _, k := range keys { + command.append("-H", bashEscape(fmt.Sprintf("%s: %s", k, strings.Join(req.Header[k], " ")))) + } + + command.append(bashEscape(req.URL.String())) + + return &command, nil +} diff --git a/vendor/github.com/parnurzeal/gorequest/CHANGELOG b/vendor/github.com/parnurzeal/gorequest/CHANGELOG new file mode 100644 index 0000000000..83a211ad39 --- /dev/null +++ b/vendor/github.com/parnurzeal/gorequest/CHANGELOG @@ -0,0 +1,123 @@ +Changelog +========= + +v0.2.15 (2016-08-30) + + Features + * Allow float and boolean in Query()'s queryStruct @davyzhang + * Support Map in Query() @yangmls + * Support Map in Send() @longlongh4 + * Document RedirectPolicy @codegoalie + * Enable Debug mode by ENV variable @heytitle + * Add Retry() @xild + Bug/Fixes + * Allow bodies with all methods @pkopac + * Change std "errors" pkg to "github.com/pkg/errors" @pkopac + +v0.2.14 (2016-08-30) + + Features + * Support multipart @fraenky8 + * Support OPTIONS request @coderhaoxin + * Add EndStruct method @franciscocpg + * Add AsCurlCommand @jaytaylor + * Add CustomMethod @WaveCutz + * Add MakeRequest @quangbuule + Bug/Fixes + * Disable keep alive by default + + +v0.2.13 (2015-11-21) + + Features + * Add DisableTransportSwap to stop gorequest from modifying Transport settings. + Note that this will effect many functions that modify gorequest's + tranport. (So, use with caution.) (Bug #47, PR #59 by @piotrmiskiewicz) + + +v0.2.12 (2015-11-21) + + Features + * Add SetCurlCommand for printing comparable CURL command of the request + (PR #60 by @QuentinPerez) + +v0.2.11 (2015-10-24) + + Bug/Fixes + * Add support to Slice data structure (Bug #40, #42) + * Refactor sendStruct to be public function SendStruct + +v0.2.10 (2015-10-24) + + Bug/Fixes + * Fix incorrect text output in tests (PR #52 by @QuentinPerez) + * Fix Panic and runtime error properly (PR #53 by @QuentinPerez) + * Add support for "text/plain" and "application/xml" (PR #51 by + @smallnest) + * Content-Type header is also equivalent with Type function to identify + supported Gorequest's Target Type + +v0.2.9 (2015-08-16) + + Bug/Fixes + * ParseQuery accepts ; as a synonym for &. thus Gorequest Query won't + accept ; as in a query string. We add additional Param to solve this (PR + #43 by @6david9) + * AddCookies for bulk adding cookies (PR #46 by @pencil001) + +v0.2.8 (2015-08-10) + + Bug/Fixes + * Added SetDebug and SetLogger for debug mode (PR #28 by @dafang) + * Ensure the response Body is reusable (PR #37 by alaingilbert) + +v0.2.7 (2015-07-11) + + Bug/Fixes + * Incorrectly reset "Authentication" header (Hot fix by @na-ga PR #38 & Issue #39) + +v0.2.6 (2015-07-10) + + Features + * Added EndBytes (PR #30 by @jaytaylor) + +v0.2.5 (2015-07-01) + + Features + * Added Basic Auth support (pull request #24 by @dickeyxxx) + + Bug/Fixes + * Fix #31 incorrect number conversion (PR #34 by @killix) + +v0.2.4 (2015-04-13) + + Features + * Query() now supports Struct as same as Send() (pull request #25 by @figlief) + +v0.2.3 (2015-02-08) + + Features + * Added Patch HTTP Method + + Bug/Fixes + * Refactored testing code + +v0.2.2 (2015-01-03) + + Features + * Added TLSClientConfig for better control over tls + * Added AddCookie func to set "Cookie" field in request (pull request #17 by @austinov) - Issue #7 + * Added CookieJar (pull request #15 by @kemadz) + +v0.2.1 (2014-07-06) + + Features + * Implemented timeout test + + Bugs/Fixes + * Improved timeout feature by control over both dial + read/write timeout compared to previously controlling only dial connection timeout. + +v0.2.0 (2014-06-13) - Send is now supporting Struct type as a parameter + +v0.1.0 (2014-04-14) - Finished release with enough rich functions to do get, post, json and redirectpolicy + diff --git a/vendor/github.com/parnurzeal/gorequest/CONTRIBUTING.md b/vendor/github.com/parnurzeal/gorequest/CONTRIBUTING.md new file mode 100644 index 0000000000..71d1954953 --- /dev/null +++ b/vendor/github.com/parnurzeal/gorequest/CONTRIBUTING.md @@ -0,0 +1,73 @@ +# Contributing to GoRequest + +Thanks for taking the time to contribute!! + +GoRequest welcomes any kind of contributions including documentation, bug reports, +issues, feature requests, feature implementations, pull requests, helping to manage and answer issues, etc. + +### Code Guidelines + +To make the contribution process as seamless as possible, we ask for the following: + +* Go ahead and fork the project and make your changes. We encourage pull requests to allow for review and discussion of code changes. +* When you’re ready to create a pull request, be sure to: + * Have test cases for the new code. + * Follow [GoDoc](https://blog.golang.org/godoc-documenting-go-code) guideline and always add documentation for new function/variable definitions. + * Run `go fmt`. + * Additonally, add documentation to README.md if you are adding new features or changing functionality. + * Squash your commits into a single commit. `git rebase -i`. It’s okay to force update your pull request with `git push -f`. + * Make sure `go test ./...` passes, and `go build` completes. + * Follow the **Git Commit Message Guidelines** below. + +### Writing Commit Message + +Follow this [blog article](http://chris.beams.io/posts/git-commit/). It is a good resource for learning how to write good commit messages, +the most important part being that each commit message should have a title/subject in imperative mood starting with a capital letter and no trailing period: +*"Return error when sending incorrect JSON format"*, **NOT** *"returning some error."* +Also, if your commit references one or more GitHub issues, always end your commit message body with *See #1234* or *Fixes #1234*. +Replace *1234* with the GitHub issue ID. The last example will close the issue when the commit is merged into *master*. + +### Sending a Pull Request + +Due to the way Go handles package imports, the best approach for working on a +fork is to use Git Remotes. You can follow the instructions below: + +1. Get the latest sources: + + ``` + go get -u -t github.com/parnurzeal/gorequest/... + ``` + +1. Change to the GoRequest source directory: + + ``` + cd $GOPATH/src/github.com/parnurzeal/gorequest + ``` + +1. Create a new branch for your changes (the branch name is arbitrary): + + ``` + git checkout -b issue_1234 + ``` + +1. After making your changes, commit them to your new branch: + + ``` + git commit -a -v + ``` + +1. Fork GoRequest in Github. + +1. Add your fork as a new remote (the remote name, "fork" in this example, is arbitrary): + + ``` + git remote add fork git://github.com/USERNAME/gorequest.git + ``` + +1. Push the changes to your new remote: + + ``` + git push --set-upstream fork issue_1234 + ``` + +1. You're now ready to submit a PR based upon the new branch in your forked repository. diff --git a/vendor/github.com/parnurzeal/gorequest/LICENSE b/vendor/github.com/parnurzeal/gorequest/LICENSE new file mode 100644 index 0000000000..d2e3b6ddfe --- /dev/null +++ b/vendor/github.com/parnurzeal/gorequest/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Theeraphol Wattanavekin + +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. diff --git a/vendor/github.com/parnurzeal/gorequest/README.md b/vendor/github.com/parnurzeal/gorequest/README.md new file mode 100644 index 0000000000..d5119e87b7 --- /dev/null +++ b/vendor/github.com/parnurzeal/gorequest/README.md @@ -0,0 +1,328 @@ +GoRequest +========= + +GoRequest -- Simplified HTTP client ( inspired by famous SuperAgent lib in Node.js ) + +![GopherGoRequest](https://raw.githubusercontent.com/parnurzeal/gorequest/gh-pages/images/Gopher_GoRequest_400x300.jpg) + +#### "Shooting Requests like a Machine Gun" - Gopher + +Sending request would never been fun and easier than this. It comes with lots of feature: + +* Get/Post/Put/Head/Delete/Patch/Options +* Set - simple header setting +* JSON - made it simple with JSON string as a parameter +* Multipart-Support - send data and files as multipart request +* Proxy - sending request via proxy +* Timeout - setting timeout for a request +* TLSClientConfig - taking control over tls where at least you can disable security check for https +* RedirectPolicy +* Cookie - setting cookies for your request +* CookieJar - automatic in-memory cookiejar +* BasicAuth - setting basic authentication header +* more to come.. + +## Installation + +```bash +$ go get github.com/parnurzeal/gorequest +``` + +## Documentation +See [Go Doc](http://godoc.org/github.com/parnurzeal/gorequest) or [Go Walker](http://gowalker.org/github.com/parnurzeal/gorequest) for usage and details. + +## Status + +[![Drone Build Status](https://drone.io/github.com/jmcvetta/restclient/status.png)](https://drone.io/github.com/parnurzeal/gorequest/latest) +[![Travis Build Status](https://travis-ci.org/parnurzeal/gorequest.svg?branch=master)](https://travis-ci.org/parnurzeal/gorequest) + +## Why should you use GoRequest? + +GoRequest makes thing much more simple for you, making http client more awesome and fun like SuperAgent + golang style usage. + +This is what you normally do for a simple GET without GoRequest: + +```go +resp, err := http.Get("http://example.com/") +``` + +With GoRequest: + +```go +request := gorequest.New() +resp, body, errs := request.Get("http://example.com/").End() +``` + +Or below if you don't want to reuse it for other requests. + +```go +resp, body, errs := gorequest.New().Get("http://example.com/").End() +``` + +How about getting control over HTTP client headers, redirect policy, and etc. Things is getting more complicated in golang. You need to create a Client, setting header in different command, ... to do just only one __GET__ + +```go +client := &http.Client{ + CheckRedirect: redirectPolicyFunc, +} + +req, err := http.NewRequest("GET", "http://example.com", nil) + +req.Header.Add("If-None-Match", `W/"wyzzy"`) +resp, err := client.Do(req) +``` + +Why making things ugly while you can just do as follows: + +```go +request := gorequest.New() +resp, body, errs := request.Get("http://example.com"). + RedirectPolicy(redirectPolicyFunc). + Set("If-None-Match", `W/"wyzzy"`). + End() +``` + +__DELETE__, __HEAD__, __POST__, __PUT__, __PATCH__ are now supported and can be used the same way as __GET__: + +```go +request := gorequest.New() +resp, body, errs := request.Post("http://example.com").End() +// PUT -> request.Put("http://example.com").End() +// DELETE -> request.Delete("http://example.com").End() +// HEAD -> request.Head("http://example.com").End() +// ANYTHING -> request.CustomMethod("TRACE", "http://example.com").End() +``` + +### JSON + +For a __JSON POST__ with standard libraries, you might need to marshal map data structure to json format, setting header to 'application/json' (and other headers if you need to) and declare http.Client. So, you code become longer and hard to maintain: + +```go +m := map[string]interface{}{ + "name": "backy", + "species": "dog", +} +mJson, _ := json.Marshal(m) +contentReader := bytes.NewReader(mJson) +req, _ := http.NewRequest("POST", "http://example.com", contentReader) +req.Header.Set("Content-Type", "application/json") +req.Header.Set("Notes","GoRequest is coming!") +client := &http.Client{} +resp, _ := client.Do(req) +``` + +Compared to our GoRequest version, JSON is for sure a default. So, it turns out to be just one simple line!: + +```go +request := gorequest.New() +resp, body, errs := request.Post("http://example.com"). + Set("Notes","gorequst is coming!"). + Send(`{"name":"backy", "species":"dog"}`). + End() +``` + +Moreover, it also supports struct type. So, you can have a fun __Mix & Match__ sending the different data types for your request: + +```go +type BrowserVersionSupport struct { + Chrome string + Firefox string +} +ver := BrowserVersionSupport{ Chrome: "37.0.2041.6", Firefox: "30.0" } +request := gorequest.New() +resp, body, errs := request.Post("http://version.com/update"). + Send(ver). + Send(`{"Safari":"5.1.10"}`). + End() +``` + +Not only for Send() but Query() is also supported. Just give it a try! :) + +## Callback + +Moreover, GoRequest also supports callback function. This gives you much more flexibility on using it. You can use it any way to match your own style! +Let's see a bit of callback example: + +```go +func printStatus(resp gorequest.Response, body string, errs []error){ + fmt.Println(resp.Status) +} +gorequest.New().Get("http://example.com").End(printStatus) +``` + +## Multipart/Form-Data + +You can specify the content-type of the request to type `multipart` to send all data as `multipart/form-data`. This feature also allows you to send (multiple) files! Check the examples below! + +```go +gorequest.New().Post("http://example.com/"). + Type("multipart"). + Send(`{"query1":"test"}`). + End() +``` + +The `SendFile` function accepts `strings` as path to a file, `[]byte` slice or even a `os.File`! You can also combine them to send multiple files with either custom name and/or custom fieldname: + +```go + f, _ := filepath.Abs("./file2.txt") +bytesOfFile, _ := ioutil.ReadFile(f) + +gorequest.New().Post("http://example.com/"). + Type("multipart"). + SendFile("./file1.txt"). + SendFile(bytesOfFile, "file2.txt", "my_file_fieldname"). + End() +``` + +Check the docs for `SendFile` to get more information about the types of arguments. + +## Proxy + +In the case when you are behind proxy, GoRequest can handle it easily with Proxy func: + +```go +request := gorequest.New().Proxy("http://proxy:999") +resp, body, errs := request.Get("http://example-proxy.com").End() +// To reuse same client with no_proxy, use empty string: +resp, body, errs = request.Proxy("").Get("http://example-no-proxy.com").End() +``` + +## Basic Authentication + +To add a basic authentication header: + +```go +request := gorequest.New().SetBasicAuth("username", "password") +resp, body, errs := request.Get("http://example-proxy.com").End() +``` + +## Timeout + +Timeout can be set in any time duration using time package: + +```go +request := gorequest.New().Timeout(2*time.Millisecond) +resp, body, errs:= request.Get("http://example.com").End() +``` + +Timeout func defines both dial + read/write timeout to the specified time parameter. + +## EndBytes + +Thanks to @jaytaylor, we now have EndBytes to use when you want the body as bytes. + +The callbacks work the same way as with `End`, except that a byte array is used instead of a string. + +```go +resp, bodyBytes, errs := gorequest.New().Get("http://example.com/").EndBytes() +``` + +## EndStruct + +We now have EndStruct to use when you want the body as struct. + +The callbacks work the same way as with `End`, except that a struct is used instead of a string. + +Supposing the URL **http://example.com/** returns the body `{"hey":"you"}` + +```go +heyYou struct { + Hey string `json:"hey"` +} + +var heyYou heyYou + +resp, _, errs := gorequest.New().Get("http://example.com/").EndStruct(&heyYou) +``` + +## Retry + +Supposing you need retry 3 times, with 5 seconds between each attempt when gets a BadRequest or a InternalServerError + +```go +request := gorequest.New() +resp, body, errs := request.Get("http://example.com/"). + Retry(3, 5 * time.seconds, http.StatusBadRequest, http.StatusInternalServerError). + End() +``` + +## Handling Redirects + +Redirects can be handled with RedirectPolicy which behaves similarly to +net/http Client's [CheckRedirect +function](https://golang.org/pkg/net/http#Client). Simply specify a function +which takes the Request about to be made and a slice of previous Requests in +order of oldest first. When this function returns an error, the Request is not +made. + +For example to redirect only to https endpoints: + +```go +request := gorequest.New() +resp, body, errs := request.Get("http://example.com/"). + RedirectPolicy(func(req Request, via []*Request) error { + if req.URL.Scheme != "https" { + return http.ErrUseLastResponse + } + }). + End() +``` + +## Debug + +For debugging, GoRequest leverages `httputil` to dump details of every request/response. (Thanks to @dafang) + +You can just use `SetDebug` or environment variable `GOREQUEST_DEBUG=0|1` to enable/disable debug mode and `SetLogger` to set your own choice of logger. + +Thanks to @QuentinPerez, we can see even how gorequest is compared to CURL by using `SetCurlCommand`. + +## Noted +As the underlying gorequest is based on http.Client in most use cases, gorequest.New() should be called once and reuse gorequest as much as possible. + +## Contributing to GoRequest: + +If you find any improvement or issue you want to fix, feel free to send me a pull request with testing. + +Thanks to all contributors thus far: + + +| Contributors | +|---------------------------------------| +| https://github.com/alaingilbert | +| https://github.com/austinov | +| https://github.com/coderhaoxin | +| https://github.com/codegoalie | +| https://github.com/dafang | +| https://github.com/davyzhang | +| https://github.com/dickeyxxx | +| https://github.com/figlief | +| https://github.com/fraenky8 | +| https://github.com/franciscocpg | +| https://github.com/heytitle | +| https://github.com/hownowstephen | +| https://github.com/kemadz | +| https://github.com/killix | +| https://github.com/jaytaylor | +| https://github.com/na-ga | +| https://github.com/piotrmiskiewicz | +| https://github.com/pencil001 | +| https://github.com/pkopac | +| https://github.com/quangbuule | +| https://github.com/QuentinPerez | +| https://github.com/smallnest | +| https://github.com/WaveCutz | +| https://github.com/xild | +| https://github.com/yangmls | +| https://github.com/6david9 | + + +Also, co-maintainer is needed here. If anyone is interested, please email me (parnurzeal at gmail.com) + +## Credits + +* Renee French - the creator of Gopher mascot +* [Wisi Mongkhonsrisawat](https://www.facebook.com/puairw) for providing an awesome GoRequest's Gopher image :) + +## License + +GoRequest is MIT License. diff --git a/vendor/github.com/parnurzeal/gorequest/gorequest.go b/vendor/github.com/parnurzeal/gorequest/gorequest.go new file mode 100644 index 0000000000..ea1a55c17d --- /dev/null +++ b/vendor/github.com/parnurzeal/gorequest/gorequest.go @@ -0,0 +1,1238 @@ +// Package gorequest inspired by Nodejs SuperAgent provides easy-way to write http client +package gorequest + +import ( + "bytes" + "crypto/tls" + "encoding/json" + "io/ioutil" + "log" + "net" + "net/http" + "net/http/cookiejar" + "net/http/httputil" + "net/url" + "os" + "reflect" + "strconv" + "strings" + "time" + + "github.com/pkg/errors" + + "mime/multipart" + + "net/textproto" + + "fmt" + + "path/filepath" + + "github.com/moul/http2curl" + "golang.org/x/net/publicsuffix" +) + +type Request *http.Request +type Response *http.Response + +// HTTP methods we support +const ( + POST = "POST" + GET = "GET" + HEAD = "HEAD" + PUT = "PUT" + DELETE = "DELETE" + PATCH = "PATCH" + OPTIONS = "OPTIONS" +) + +// A SuperAgent is a object storing all request data for client. +type SuperAgent struct { + Url string + Method string + Header map[string]string + TargetType string + ForceType string + Data map[string]interface{} + SliceData []interface{} + FormData url.Values + QueryData url.Values + FileData []File + BounceToRawString bool + RawString string + Client *http.Client + Transport *http.Transport + Cookies []*http.Cookie + Errors []error + BasicAuth struct{ Username, Password string } + Debug bool + CurlCommand bool + logger *log.Logger + Retryable struct { + RetryableStatus []int + RetryerTime time.Duration + RetryerCount int + Attempt int + Enable bool + } +} + +var DisableTransportSwap = false + +// Used to create a new SuperAgent object. +func New() *SuperAgent { + cookiejarOptions := cookiejar.Options{ + PublicSuffixList: publicsuffix.List, + } + jar, _ := cookiejar.New(&cookiejarOptions) + + debug := os.Getenv("GOREQUEST_DEBUG") == "1" + + s := &SuperAgent{ + TargetType: "json", + Data: make(map[string]interface{}), + Header: make(map[string]string), + RawString: "", + SliceData: []interface{}{}, + FormData: url.Values{}, + QueryData: url.Values{}, + FileData: make([]File, 0), + BounceToRawString: false, + Client: &http.Client{Jar: jar}, + Transport: &http.Transport{}, + Cookies: make([]*http.Cookie, 0), + Errors: nil, + BasicAuth: struct{ Username, Password string }{}, + Debug: debug, + CurlCommand: false, + logger: log.New(os.Stderr, "[gorequest]", log.LstdFlags), + } + // disable keep alives by default, see this issue https://github.com/parnurzeal/gorequest/issues/75 + s.Transport.DisableKeepAlives = true + return s +} + +// Enable the debug mode which logs request/response detail +func (s *SuperAgent) SetDebug(enable bool) *SuperAgent { + s.Debug = enable + return s +} + +// Enable the curlcommand mode which display a CURL command line +func (s *SuperAgent) SetCurlCommand(enable bool) *SuperAgent { + s.CurlCommand = enable + return s +} + +func (s *SuperAgent) SetLogger(logger *log.Logger) *SuperAgent { + s.logger = logger + return s +} + +// Clear SuperAgent data for another new request. +func (s *SuperAgent) ClearSuperAgent() { + s.Url = "" + s.Method = "" + s.Header = make(map[string]string) + s.Data = make(map[string]interface{}) + s.SliceData = []interface{}{} + s.FormData = url.Values{} + s.QueryData = url.Values{} + s.FileData = make([]File, 0) + s.BounceToRawString = false + s.RawString = "" + s.ForceType = "" + s.TargetType = "json" + s.Cookies = make([]*http.Cookie, 0) + s.Errors = nil +} + +// Just a wrapper to initialize SuperAgent instance by method string +func (s *SuperAgent) CustomMethod(method, targetUrl string) *SuperAgent { + switch method { + case POST: + return s.Post(targetUrl) + case GET: + return s.Get(targetUrl) + case HEAD: + return s.Head(targetUrl) + case PUT: + return s.Put(targetUrl) + case DELETE: + return s.Delete(targetUrl) + case PATCH: + return s.Patch(targetUrl) + case OPTIONS: + return s.Options(targetUrl) + default: + s.ClearSuperAgent() + s.Method = method + s.Url = targetUrl + s.Errors = nil + return s + } +} + +func (s *SuperAgent) Get(targetUrl string) *SuperAgent { + s.ClearSuperAgent() + s.Method = GET + s.Url = targetUrl + s.Errors = nil + return s +} + +func (s *SuperAgent) Post(targetUrl string) *SuperAgent { + s.ClearSuperAgent() + s.Method = POST + s.Url = targetUrl + s.Errors = nil + return s +} + +func (s *SuperAgent) Head(targetUrl string) *SuperAgent { + s.ClearSuperAgent() + s.Method = HEAD + s.Url = targetUrl + s.Errors = nil + return s +} + +func (s *SuperAgent) Put(targetUrl string) *SuperAgent { + s.ClearSuperAgent() + s.Method = PUT + s.Url = targetUrl + s.Errors = nil + return s +} + +func (s *SuperAgent) Delete(targetUrl string) *SuperAgent { + s.ClearSuperAgent() + s.Method = DELETE + s.Url = targetUrl + s.Errors = nil + return s +} + +func (s *SuperAgent) Patch(targetUrl string) *SuperAgent { + s.ClearSuperAgent() + s.Method = PATCH + s.Url = targetUrl + s.Errors = nil + return s +} + +func (s *SuperAgent) Options(targetUrl string) *SuperAgent { + s.ClearSuperAgent() + s.Method = OPTIONS + s.Url = targetUrl + s.Errors = nil + return s +} + +// Set is used for setting header fields. +// Example. To set `Accept` as `application/json` +// +// gorequest.New(). +// Post("/gamelist"). +// Set("Accept", "application/json"). +// End() +func (s *SuperAgent) Set(param string, value string) *SuperAgent { + s.Header[param] = value + return s +} + +// Retryable is used for setting a Retryer policy +// Example. To set Retryer policy with 5 seconds between each attempt. +// 3 max attempt. +// And StatusBadRequest and StatusInternalServerError as RetryableStatus + +// gorequest.New(). +// Post("/gamelist"). +// Retry(3, 5 * time.seconds, http.StatusBadRequest, http.StatusInternalServerError). +// End() +func (s *SuperAgent) Retry(retryerCount int, retryerTime time.Duration, statusCode ...int) *SuperAgent { + for _, code := range statusCode { + statusText := http.StatusText(code) + if len(statusText) == 0 { + s.Errors = append(s.Errors, errors.New("StatusCode '"+strconv.Itoa(code)+"' doesn't exist in http package")) + } + } + + s.Retryable = struct { + RetryableStatus []int + RetryerTime time.Duration + RetryerCount int + Attempt int + Enable bool + }{ + statusCode, + retryerTime, + retryerCount, + 0, + true, + } + return s +} + +// SetBasicAuth sets the basic authentication header +// Example. To set the header for username "myuser" and password "mypass" +// +// gorequest.New() +// Post("/gamelist"). +// SetBasicAuth("myuser", "mypass"). +// End() +func (s *SuperAgent) SetBasicAuth(username string, password string) *SuperAgent { + s.BasicAuth = struct{ Username, Password string }{username, password} + return s +} + +// AddCookie adds a cookie to the request. The behavior is the same as AddCookie on Request from net/http +func (s *SuperAgent) AddCookie(c *http.Cookie) *SuperAgent { + s.Cookies = append(s.Cookies, c) + return s +} + +// AddCookies is a convenient method to add multiple cookies +func (s *SuperAgent) AddCookies(cookies []*http.Cookie) *SuperAgent { + s.Cookies = append(s.Cookies, cookies...) + return s +} + +var Types = map[string]string{ + "html": "text/html", + "json": "application/json", + "xml": "application/xml", + "text": "text/plain", + "urlencoded": "application/x-www-form-urlencoded", + "form": "application/x-www-form-urlencoded", + "form-data": "application/x-www-form-urlencoded", + "multipart": "multipart/form-data", +} + +// Type is a convenience function to specify the data type to send. +// For example, to send data as `application/x-www-form-urlencoded` : +// +// gorequest.New(). +// Post("/recipe"). +// Type("form"). +// Send(`{ "name": "egg benedict", "category": "brunch" }`). +// End() +// +// This will POST the body "name=egg benedict&category=brunch" to url /recipe +// +// GoRequest supports +// +// "text/html" uses "html" +// "application/json" uses "json" +// "application/xml" uses "xml" +// "text/plain" uses "text" +// "application/x-www-form-urlencoded" uses "urlencoded", "form" or "form-data" +// +func (s *SuperAgent) Type(typeStr string) *SuperAgent { + if _, ok := Types[typeStr]; ok { + s.ForceType = typeStr + } else { + s.Errors = append(s.Errors, errors.New("Type func: incorrect type \""+typeStr+"\"")) + } + return s +} + +// Query function accepts either json string or strings which will form a query-string in url of GET method or body of POST method. +// For example, making "/search?query=bicycle&size=50x50&weight=20kg" using GET method: +// +// gorequest.New(). +// Get("/search"). +// Query(`{ query: 'bicycle' }`). +// Query(`{ size: '50x50' }`). +// Query(`{ weight: '20kg' }`). +// End() +// +// Or you can put multiple json values: +// +// gorequest.New(). +// Get("/search"). +// Query(`{ query: 'bicycle', size: '50x50', weight: '20kg' }`). +// End() +// +// Strings are also acceptable: +// +// gorequest.New(). +// Get("/search"). +// Query("query=bicycle&size=50x50"). +// Query("weight=20kg"). +// End() +// +// Or even Mixed! :) +// +// gorequest.New(). +// Get("/search"). +// Query("query=bicycle"). +// Query(`{ size: '50x50', weight:'20kg' }`). +// End() +// +func (s *SuperAgent) Query(content interface{}) *SuperAgent { + switch v := reflect.ValueOf(content); v.Kind() { + case reflect.String: + s.queryString(v.String()) + case reflect.Struct: + s.queryStruct(v.Interface()) + case reflect.Map: + s.queryMap(v.Interface()) + default: + } + return s +} + +func (s *SuperAgent) queryStruct(content interface{}) *SuperAgent { + if marshalContent, err := json.Marshal(content); err != nil { + s.Errors = append(s.Errors, err) + } else { + var val map[string]interface{} + if err := json.Unmarshal(marshalContent, &val); err != nil { + s.Errors = append(s.Errors, err) + } else { + for k, v := range val { + k = strings.ToLower(k) + var queryVal string + switch t := v.(type) { + case string: + queryVal = t + case float64: + queryVal = strconv.FormatFloat(t, 'f', -1, 64) + case time.Time: + queryVal = t.Format(time.RFC3339) + default: + j, err := json.Marshal(v) + if err != nil { + continue + } + queryVal = string(j) + } + s.QueryData.Add(k, queryVal) + } + } + } + return s +} + +func (s *SuperAgent) queryString(content string) *SuperAgent { + var val map[string]string + if err := json.Unmarshal([]byte(content), &val); err == nil { + for k, v := range val { + s.QueryData.Add(k, v) + } + } else { + if queryData, err := url.ParseQuery(content); err == nil { + for k, queryValues := range queryData { + for _, queryValue := range queryValues { + s.QueryData.Add(k, string(queryValue)) + } + } + } else { + s.Errors = append(s.Errors, err) + } + // TODO: need to check correct format of 'field=val&field=val&...' + } + return s +} + +func (s *SuperAgent) queryMap(content interface{}) *SuperAgent { + return s.queryStruct(content) +} + +// As Go conventions accepts ; as a synonym for &. (https://github.com/golang/go/issues/2210) +// Thus, Query won't accept ; in a querystring if we provide something like fields=f1;f2;f3 +// This Param is then created as an alternative method to solve this. +func (s *SuperAgent) Param(key string, value string) *SuperAgent { + s.QueryData.Add(key, value) + return s +} + +func (s *SuperAgent) Timeout(timeout time.Duration) *SuperAgent { + s.Transport.Dial = func(network, addr string) (net.Conn, error) { + conn, err := net.DialTimeout(network, addr, timeout) + if err != nil { + s.Errors = append(s.Errors, err) + return nil, err + } + conn.SetDeadline(time.Now().Add(timeout)) + return conn, nil + } + return s +} + +// Set TLSClientConfig for underling Transport. +// One example is you can use it to disable security check (https): +// +// gorequest.New().TLSClientConfig(&tls.Config{ InsecureSkipVerify: true}). +// Get("https://disable-security-check.com"). +// End() +// +func (s *SuperAgent) TLSClientConfig(config *tls.Config) *SuperAgent { + s.Transport.TLSClientConfig = config + return s +} + +// Proxy function accepts a proxy url string to setup proxy url for any request. +// It provides a convenience way to setup proxy which have advantages over usual old ways. +// One example is you might try to set `http_proxy` environment. This means you are setting proxy up for all the requests. +// You will not be able to send different request with different proxy unless you change your `http_proxy` environment again. +// Another example is using Golang proxy setting. This is normal prefer way to do but too verbase compared to GoRequest's Proxy: +// +// gorequest.New().Proxy("http://myproxy:9999"). +// Post("http://www.google.com"). +// End() +// +// To set no_proxy, just put empty string to Proxy func: +// +// gorequest.New().Proxy(""). +// Post("http://www.google.com"). +// End() +// +func (s *SuperAgent) Proxy(proxyUrl string) *SuperAgent { + parsedProxyUrl, err := url.Parse(proxyUrl) + if err != nil { + s.Errors = append(s.Errors, err) + } else if proxyUrl == "" { + s.Transport.Proxy = nil + } else { + s.Transport.Proxy = http.ProxyURL(parsedProxyUrl) + } + return s +} + +// RedirectPolicy accepts a function to define how to handle redirects. If the +// policy function returns an error, the next Request is not made and the previous +// request is returned. +// +// The policy function's arguments are the Request about to be made and the +// past requests in order of oldest first. +func (s *SuperAgent) RedirectPolicy(policy func(req Request, via []Request) error) *SuperAgent { + s.Client.CheckRedirect = func(r *http.Request, v []*http.Request) error { + vv := make([]Request, len(v)) + for i, r := range v { + vv[i] = Request(r) + } + return policy(Request(r), vv) + } + return s +} + +// Send function accepts either json string or query strings which is usually used to assign data to POST or PUT method. +// Without specifying any type, if you give Send with json data, you are doing requesting in json format: +// +// gorequest.New(). +// Post("/search"). +// Send(`{ query: 'sushi' }`). +// End() +// +// While if you use at least one of querystring, GoRequest understands and automatically set the Content-Type to `application/x-www-form-urlencoded` +// +// gorequest.New(). +// Post("/search"). +// Send("query=tonkatsu"). +// End() +// +// So, if you want to strictly send json format, you need to use Type func to set it as `json` (Please see more details in Type function). +// You can also do multiple chain of Send: +// +// gorequest.New(). +// Post("/search"). +// Send("query=bicycle&size=50x50"). +// Send(`{ wheel: '4'}`). +// End() +// +// From v0.2.0, Send function provide another convenience way to work with Struct type. You can mix and match it with json and query string: +// +// type BrowserVersionSupport struct { +// Chrome string +// Firefox string +// } +// ver := BrowserVersionSupport{ Chrome: "37.0.2041.6", Firefox: "30.0" } +// gorequest.New(). +// Post("/update_version"). +// Send(ver). +// Send(`{"Safari":"5.1.10"}`). +// End() +// +// If you have set Type to text or Content-Type to text/plain, content will be sent as raw string in body instead of form +// +// gorequest.New(). +// Post("/greet"). +// Type("text"). +// Send("hello world"). +// End() +// +func (s *SuperAgent) Send(content interface{}) *SuperAgent { + // TODO: add normal text mode or other mode to Send func + switch v := reflect.ValueOf(content); v.Kind() { + case reflect.String: + s.SendString(v.String()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: // includes rune + s.SendString(strconv.FormatInt(v.Int(), 10)) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: // includes byte + s.SendString(strconv.FormatUint(v.Uint(), 10)) + case reflect.Float64: + s.SendString(strconv.FormatFloat(v.Float(), 'f', -1, 64)) + case reflect.Float32: + s.SendString(strconv.FormatFloat(v.Float(), 'f', -1, 32)) + case reflect.Bool: + s.SendString(strconv.FormatBool(v.Bool())) + case reflect.Struct: + s.SendStruct(v.Interface()) + case reflect.Slice: + s.SendSlice(makeSliceOfReflectValue(v)) + case reflect.Array: + s.SendSlice(makeSliceOfReflectValue(v)) + case reflect.Ptr: + s.Send(v.Elem().Interface()) + case reflect.Map: + s.SendMap(v.Interface()) + default: + // TODO: leave default for handling other types in the future, such as complex numbers, (nested) maps, etc + return s + } + return s +} + +func makeSliceOfReflectValue(v reflect.Value) (slice []interface{}) { + + kind := v.Kind() + if kind != reflect.Slice && kind != reflect.Array { + return slice + } + + slice = make([]interface{}, v.Len()) + for i := 0; i < v.Len(); i++ { + slice[i] = v.Index(i).Interface() + } + + return slice +} + +// SendSlice (similar to SendString) returns SuperAgent's itself for any next chain and takes content []interface{} as a parameter. +// Its duty is to append slice of interface{} into s.SliceData ([]interface{}) which later changes into json array in the End() func. +func (s *SuperAgent) SendSlice(content []interface{}) *SuperAgent { + s.SliceData = append(s.SliceData, content...) + return s +} + +func (s *SuperAgent) SendMap(content interface{}) *SuperAgent { + return s.SendStruct(content) +} + +// SendStruct (similar to SendString) returns SuperAgent's itself for any next chain and takes content interface{} as a parameter. +// Its duty is to transfrom interface{} (implicitly always a struct) into s.Data (map[string]interface{}) which later changes into appropriate format such as json, form, text, etc. in the End() func. +func (s *SuperAgent) SendStruct(content interface{}) *SuperAgent { + if marshalContent, err := json.Marshal(content); err != nil { + s.Errors = append(s.Errors, err) + } else { + var val map[string]interface{} + d := json.NewDecoder(bytes.NewBuffer(marshalContent)) + d.UseNumber() + if err := d.Decode(&val); err != nil { + s.Errors = append(s.Errors, err) + } else { + for k, v := range val { + s.Data[k] = v + } + } + } + return s +} + +// SendString returns SuperAgent's itself for any next chain and takes content string as a parameter. +// Its duty is to transform String into s.Data (map[string]interface{}) which later changes into appropriate format such as json, form, text, etc. in the End func. +// Send implicitly uses SendString and you should use Send instead of this. +func (s *SuperAgent) SendString(content string) *SuperAgent { + if !s.BounceToRawString { + var val interface{} + d := json.NewDecoder(strings.NewReader(content)) + d.UseNumber() + if err := d.Decode(&val); err == nil { + switch v := reflect.ValueOf(val); v.Kind() { + case reflect.Map: + for k, v := range val.(map[string]interface{}) { + s.Data[k] = v + } + // add to SliceData + case reflect.Slice: + s.SendSlice(val.([]interface{})) + // bounce to rawstring if it is arrayjson, or others + default: + s.BounceToRawString = true + } + } else if formData, err := url.ParseQuery(content); err == nil { + for k, formValues := range formData { + for _, formValue := range formValues { + // make it array if already have key + if val, ok := s.Data[k]; ok { + var strArray []string + strArray = append(strArray, string(formValue)) + // check if previous data is one string or array + switch oldValue := val.(type) { + case []string: + strArray = append(strArray, oldValue...) + case string: + strArray = append(strArray, oldValue) + } + s.Data[k] = strArray + } else { + // make it just string if does not already have same key + s.Data[k] = formValue + } + } + } + s.TargetType = "form" + } else { + s.BounceToRawString = true + } + } + // Dump all contents to RawString in case in the end user doesn't want json or form. + s.RawString += content + return s +} + +type File struct { + Filename string + Fieldname string + Data []byte +} + +// SendFile function works only with type "multipart". The function accepts one mandatory and up to two optional arguments. The mandatory (first) argument is the file. +// The function accepts a path to a file as string: +// +// gorequest.New(). +// Post("http://example.com"). +// Type("multipart"). +// SendFile("./example_file.ext"). +// End() +// +// File can also be a []byte slice of a already file read by eg. ioutil.ReadFile: +// +// b, _ := ioutil.ReadFile("./example_file.ext") +// gorequest.New(). +// Post("http://example.com"). +// Type("multipart"). +// SendFile(b). +// End() +// +// Furthermore file can also be a os.File: +// +// f, _ := os.Open("./example_file.ext") +// gorequest.New(). +// Post("http://example.com"). +// Type("multipart"). +// SendFile(f). +// End() +// +// The first optional argument (second argument overall) is the filename, which will be automatically determined when file is a string (path) or a os.File. +// When file is a []byte slice, filename defaults to "filename". In all cases the automatically determined filename can be overwritten: +// +// b, _ := ioutil.ReadFile("./example_file.ext") +// gorequest.New(). +// Post("http://example.com"). +// Type("multipart"). +// SendFile(b, "my_custom_filename"). +// End() +// +// The second optional argument (third argument overall) is the fieldname in the multipart/form-data request. It defaults to fileNUMBER (eg. file1), where number is ascending and starts counting at 1. +// So if you send multiple files, the fieldnames will be file1, file2, ... unless it is overwritten. If fieldname is set to "file" it will be automatically set to fileNUMBER, where number is the greatest exsiting number+1. +// +// b, _ := ioutil.ReadFile("./example_file.ext") +// gorequest.New(). +// Post("http://example.com"). +// Type("multipart"). +// SendFile(b, "", "my_custom_fieldname"). // filename left blank, will become "example_file.ext" +// End() +// +func (s *SuperAgent) SendFile(file interface{}, args ...string) *SuperAgent { + + filename := "" + fieldname := "file" + + if len(args) >= 1 && len(args[0]) > 0 { + filename = strings.TrimSpace(args[0]) + } + if len(args) >= 2 && len(args[1]) > 0 { + fieldname = strings.TrimSpace(args[1]) + } + if fieldname == "file" || fieldname == "" { + fieldname = "file" + strconv.Itoa(len(s.FileData)+1) + } + + switch v := reflect.ValueOf(file); v.Kind() { + case reflect.String: + pathToFile, err := filepath.Abs(v.String()) + if err != nil { + s.Errors = append(s.Errors, err) + return s + } + if filename == "" { + filename = filepath.Base(pathToFile) + } + data, err := ioutil.ReadFile(v.String()) + if err != nil { + s.Errors = append(s.Errors, err) + return s + } + s.FileData = append(s.FileData, File{ + Filename: filename, + Fieldname: fieldname, + Data: data, + }) + case reflect.Slice: + slice := makeSliceOfReflectValue(v) + if filename == "" { + filename = "filename" + } + f := File{ + Filename: filename, + Fieldname: fieldname, + Data: make([]byte, len(slice)), + } + for i := range slice { + f.Data[i] = slice[i].(byte) + } + s.FileData = append(s.FileData, f) + case reflect.Ptr: + if len(args) == 1 { + return s.SendFile(v.Elem().Interface(), args[0]) + } + if len(args) >= 2 { + return s.SendFile(v.Elem().Interface(), args[0], args[1]) + } + return s.SendFile(v.Elem().Interface()) + default: + if v.Type() == reflect.TypeOf(os.File{}) { + osfile := v.Interface().(os.File) + if filename == "" { + filename = filepath.Base(osfile.Name()) + } + data, err := ioutil.ReadFile(osfile.Name()) + if err != nil { + s.Errors = append(s.Errors, err) + return s + } + s.FileData = append(s.FileData, File{ + Filename: filename, + Fieldname: fieldname, + Data: data, + }) + return s + } + + s.Errors = append(s.Errors, errors.New("SendFile currently only supports either a string (path/to/file), a slice of bytes (file content itself), or a os.File!")) + } + + return s +} + +func changeMapToURLValues(data map[string]interface{}) url.Values { + var newUrlValues = url.Values{} + for k, v := range data { + switch val := v.(type) { + case string: + newUrlValues.Add(k, val) + case bool: + newUrlValues.Add(k, strconv.FormatBool(val)) + // if a number, change to string + // json.Number used to protect against a wrong (for GoRequest) default conversion + // which always converts number to float64. + // This type is caused by using Decoder.UseNumber() + case json.Number: + newUrlValues.Add(k, string(val)) + case int: + newUrlValues.Add(k, strconv.FormatInt(int64(val), 10)) + // TODO add all other int-Types (int8, int16, ...) + case float64: + newUrlValues.Add(k, strconv.FormatFloat(float64(val), 'f', -1, 64)) + case float32: + newUrlValues.Add(k, strconv.FormatFloat(float64(val), 'f', -1, 64)) + // following slices are mostly needed for tests + case []string: + for _, element := range val { + newUrlValues.Add(k, element) + } + case []int: + for _, element := range val { + newUrlValues.Add(k, strconv.FormatInt(int64(element), 10)) + } + case []bool: + for _, element := range val { + newUrlValues.Add(k, strconv.FormatBool(element)) + } + case []float64: + for _, element := range val { + newUrlValues.Add(k, strconv.FormatFloat(float64(element), 'f', -1, 64)) + } + case []float32: + for _, element := range val { + newUrlValues.Add(k, strconv.FormatFloat(float64(element), 'f', -1, 64)) + } + // these slices are used in practice like sending a struct + case []interface{}: + + if len(val) <= 0 { + continue + } + + switch val[0].(type) { + case string: + for _, element := range val { + newUrlValues.Add(k, element.(string)) + } + case bool: + for _, element := range val { + newUrlValues.Add(k, strconv.FormatBool(element.(bool))) + } + case json.Number: + for _, element := range val { + newUrlValues.Add(k, string(element.(json.Number))) + } + } + default: + // TODO add ptr, arrays, ... + } + } + return newUrlValues +} + +// End is the most important function that you need to call when ending the chain. The request won't proceed without calling it. +// End function returns Response which matchs the structure of Response type in Golang's http package (but without Body data). The body data itself returns as a string in a 2nd return value. +// Lastly but worth noticing, error array (NOTE: not just single error value) is returned as a 3rd value and nil otherwise. +// +// For example: +// +// resp, body, errs := gorequest.New().Get("http://www.google.com").End() +// if (errs != nil) { +// fmt.Println(errs) +// } +// fmt.Println(resp, body) +// +// Moreover, End function also supports callback which you can put as a parameter. +// This extends the flexibility and makes GoRequest fun and clean! You can use GoRequest in whatever style you love! +// +// For example: +// +// func printBody(resp gorequest.Response, body string, errs []error){ +// fmt.Println(resp.Status) +// } +// gorequest.New().Get("http://www..google.com").End(printBody) +// +func (s *SuperAgent) End(callback ...func(response Response, body string, errs []error)) (Response, string, []error) { + var bytesCallback []func(response Response, body []byte, errs []error) + if len(callback) > 0 { + bytesCallback = []func(response Response, body []byte, errs []error){ + func(response Response, body []byte, errs []error) { + callback[0](response, string(body), errs) + }, + } + } + + resp, body, errs := s.EndBytes(bytesCallback...) + bodyString := string(body) + + return resp, bodyString, errs +} + +// EndBytes should be used when you want the body as bytes. The callbacks work the same way as with `End`, except that a byte array is used instead of a string. +func (s *SuperAgent) EndBytes(callback ...func(response Response, body []byte, errs []error)) (Response, []byte, []error) { + var ( + errs []error + resp Response + body []byte + ) + + for { + resp, body, errs = s.getResponseBytes() + if errs != nil { + return nil, nil, errs + } + if s.isRetryableRequest(resp) { + resp.Header.Set("Retry-Count", strconv.Itoa(s.Retryable.Attempt)) + break + } + } + + respCallback := *resp + if len(callback) != 0 { + callback[0](&respCallback, body, s.Errors) + } + return resp, body, nil +} + +func (s *SuperAgent) isRetryableRequest(resp Response) bool { + if s.Retryable.Enable && s.Retryable.Attempt < s.Retryable.RetryerCount && contains(resp.StatusCode, s.Retryable.RetryableStatus) { + time.Sleep(s.Retryable.RetryerTime) + s.Retryable.Attempt++ + return false + } + return true +} + +func contains(respStatus int, statuses []int) bool { + for _, status := range statuses { + if status == respStatus { + return true + } + } + return false +} + +// EndStruct should be used when you want the body as a struct. The callbacks work the same way as with `End`, except that a struct is used instead of a string. +func (s *SuperAgent) EndStruct(v interface{}, callback ...func(response Response, v interface{}, body []byte, errs []error)) (Response, []byte, []error) { + resp, body, errs := s.EndBytes() + if errs != nil { + return nil, body, errs + } + err := json.Unmarshal(body, &v) + if err != nil { + s.Errors = append(s.Errors, err) + return resp, body, s.Errors + } + respCallback := *resp + if len(callback) != 0 { + callback[0](&respCallback, v, body, s.Errors) + } + return resp, body, nil +} + +func (s *SuperAgent) getResponseBytes() (Response, []byte, []error) { + var ( + req *http.Request + err error + resp Response + ) + // check whether there is an error. if yes, return all errors + if len(s.Errors) != 0 { + return nil, nil, s.Errors + } + // check if there is forced type + switch s.ForceType { + case "json", "form", "xml", "text", "multipart": + s.TargetType = s.ForceType + // If forcetype is not set, check whether user set Content-Type header. + // If yes, also bounce to the correct supported TargetType automatically. + default: + for k, v := range Types { + if s.Header["Content-Type"] == v { + s.TargetType = k + } + } + } + + // if slice and map get mixed, let's bounce to rawstring + if len(s.Data) != 0 && len(s.SliceData) != 0 { + s.BounceToRawString = true + } + + // Make Request + req, err = s.MakeRequest() + if err != nil { + s.Errors = append(s.Errors, err) + return nil, nil, s.Errors + } + + // Set Transport + if !DisableTransportSwap { + s.Client.Transport = s.Transport + } + + // Log details of this request + if s.Debug { + dump, err := httputil.DumpRequest(req, true) + s.logger.SetPrefix("[http] ") + if err != nil { + s.logger.Println("Error:", err) + } else { + s.logger.Printf("HTTP Request: %s", string(dump)) + } + } + + // Display CURL command line + if s.CurlCommand { + curl, err := http2curl.GetCurlCommand(req) + s.logger.SetPrefix("[curl] ") + if err != nil { + s.logger.Println("Error:", err) + } else { + s.logger.Printf("CURL command line: %s", curl) + } + } + + // Send request + resp, err = s.Client.Do(req) + if err != nil { + s.Errors = append(s.Errors, err) + return nil, nil, s.Errors + } + defer resp.Body.Close() + + // Log details of this response + if s.Debug { + dump, err := httputil.DumpResponse(resp, true) + if nil != err { + s.logger.Println("Error:", err) + } else { + s.logger.Printf("HTTP Response: %s", string(dump)) + } + } + + body, _ := ioutil.ReadAll(resp.Body) + // Reset resp.Body so it can be use again + resp.Body = ioutil.NopCloser(bytes.NewBuffer(body)) + + return resp, body, nil +} + +func (s *SuperAgent) MakeRequest() (*http.Request, error) { + var ( + req *http.Request + err error + ) + + if s.Method == "" { + return nil, errors.New("No method specified") + } + + if s.TargetType == "json" { + // If-case to give support to json array. we check if + // 1) Map only: send it as json map from s.Data + // 2) Array or Mix of map & array or others: send it as rawstring from s.RawString + var contentJson []byte + if s.BounceToRawString { + contentJson = []byte(s.RawString) + } else if len(s.Data) != 0 { + contentJson, _ = json.Marshal(s.Data) + } else if len(s.SliceData) != 0 { + contentJson, _ = json.Marshal(s.SliceData) + } + contentReader := bytes.NewReader(contentJson) + req, err = http.NewRequest(s.Method, s.Url, contentReader) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/json") + } else if s.TargetType == "form" || s.TargetType == "form-data" || s.TargetType == "urlencoded" { + var contentForm []byte + if s.BounceToRawString || len(s.SliceData) != 0 { + contentForm = []byte(s.RawString) + } else { + formData := changeMapToURLValues(s.Data) + contentForm = []byte(formData.Encode()) + } + contentReader := bytes.NewReader(contentForm) + req, err = http.NewRequest(s.Method, s.Url, contentReader) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + } else if s.TargetType == "text" { + req, err = http.NewRequest(s.Method, s.Url, strings.NewReader(s.RawString)) + req.Header.Set("Content-Type", "text/plain") + } else if s.TargetType == "xml" { + req, err = http.NewRequest(s.Method, s.Url, strings.NewReader(s.RawString)) + req.Header.Set("Content-Type", "application/xml") + } else if s.TargetType == "multipart" { + + var buf bytes.Buffer + mw := multipart.NewWriter(&buf) + + if s.BounceToRawString { + fieldName, ok := s.Header["data_fieldname"] + if !ok { + fieldName = "data" + } + fw, _ := mw.CreateFormField(fieldName) + fw.Write([]byte(s.RawString)) + } + + if len(s.Data) != 0 { + formData := changeMapToURLValues(s.Data) + for key, values := range formData { + for _, value := range values { + fw, _ := mw.CreateFormField(key) + fw.Write([]byte(value)) + } + } + } + + if len(s.SliceData) != 0 { + fieldName, ok := s.Header["json_fieldname"] + if !ok { + fieldName = "data" + } + // copied from CreateFormField() in mime/multipart/writer.go + h := make(textproto.MIMEHeader) + fieldName = strings.Replace(strings.Replace(fieldName, "\\", "\\\\", -1), `"`, "\\\"", -1) + h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"`, fieldName)) + h.Set("Content-Type", "application/json") + fw, _ := mw.CreatePart(h) + contentJson, err := json.Marshal(s.SliceData) + if err != nil { + return nil, err + } + fw.Write(contentJson) + } + + // add the files + if len(s.FileData) != 0 { + for _, file := range s.FileData { + fw, _ := mw.CreateFormFile(file.Fieldname, file.Filename) + fw.Write(file.Data) + } + } + + // close before call to FormDataContentType ! otherwise its not valid multipart + mw.Close() + + req, err = http.NewRequest(s.Method, s.Url, &buf) + req.Header.Set("Content-Type", mw.FormDataContentType()) + } else { + // let's return an error instead of an nil pointer exception here + return nil, errors.New("TargetType '" + s.TargetType + "' could not be determined") + } + + for k, v := range s.Header { + req.Header.Set(k, v) + // Setting the host header is a special case, see this issue: https://github.com/golang/go/issues/7682 + if strings.EqualFold(k, "host") { + req.Host = v + } + } + // Add all querystring from Query func + q := req.URL.Query() + for k, v := range s.QueryData { + for _, vv := range v { + q.Add(k, vv) + } + } + req.URL.RawQuery = q.Encode() + + // Add basic auth + if s.BasicAuth != struct{ Username, Password string }{} { + req.SetBasicAuth(s.BasicAuth.Username, s.BasicAuth.Password) + } + + // Add cookies + for _, cookie := range s.Cookies { + req.AddCookie(cookie) + } + + return req, nil +} + +// AsCurlCommand returns a string representing the runnable `curl' command +// version of the request. +func (s *SuperAgent) AsCurlCommand() (string, error) { + req, err := s.MakeRequest() + if err != nil { + return "", err + } + cmd, err := http2curl.GetCurlCommand(req) + if err != nil { + return "", err + } + return cmd.String(), nil +} diff --git a/vendor/github.com/pkg/errors/LICENSE b/vendor/github.com/pkg/errors/LICENSE new file mode 100644 index 0000000000..835ba3e755 --- /dev/null +++ b/vendor/github.com/pkg/errors/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2015, Dave Cheney +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. + +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. diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md new file mode 100644 index 0000000000..6483ba2afb --- /dev/null +++ b/vendor/github.com/pkg/errors/README.md @@ -0,0 +1,52 @@ +# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge) + +Package errors provides simple error handling primitives. + +`go get github.com/pkg/errors` + +The traditional error handling idiom in Go is roughly akin to +```go +if err != nil { + return err +} +``` +which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. + +## Adding context to an error + +The errors.Wrap function returns a new error that adds context to the original error. For example +```go +_, err := ioutil.ReadAll(r) +if err != nil { + return errors.Wrap(err, "read failed") +} +``` +## Retrieving the cause of an error + +Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. +```go +type causer interface { + Cause() error +} +``` +`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: +```go +switch err := errors.Cause(err).(type) { +case *MyError: + // handle specifically +default: + // unknown error +} +``` + +[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). + +## Contributing + +We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. + +Before proposing a change, please discuss your change by raising an issue. + +## License + +BSD-2-Clause diff --git a/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml new file mode 100644 index 0000000000..a932eade02 --- /dev/null +++ b/vendor/github.com/pkg/errors/appveyor.yml @@ -0,0 +1,32 @@ +version: build-{build}.{branch} + +clone_folder: C:\gopath\src\github.com\pkg\errors +shallow_clone: true # for startup speed + +environment: + GOPATH: C:\gopath + +platform: + - x64 + +# http://www.appveyor.com/docs/installed-software +install: + # some helpful output for debugging builds + - go version + - go env + # pre-installed MinGW at C:\MinGW is 32bit only + # but MSYS2 at C:\msys64 has mingw64 + - set PATH=C:\msys64\mingw64\bin;%PATH% + - gcc --version + - g++ --version + +build_script: + - go install -v ./... + +test_script: + - set PATH=C:\gopath\bin;%PATH% + - go test -v ./... + +#artifacts: +# - path: '%GOPATH%\bin\*.exe' +deploy: off diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go new file mode 100644 index 0000000000..842ee80456 --- /dev/null +++ b/vendor/github.com/pkg/errors/errors.go @@ -0,0 +1,269 @@ +// Package errors provides simple error handling primitives. +// +// The traditional error handling idiom in Go is roughly akin to +// +// if err != nil { +// return err +// } +// +// which applied recursively up the call stack results in error reports +// without context or debugging information. The errors package allows +// programmers to add context to the failure path in their code in a way +// that does not destroy the original value of the error. +// +// Adding context to an error +// +// The errors.Wrap function returns a new error that adds context to the +// original error by recording a stack trace at the point Wrap is called, +// and the supplied message. For example +// +// _, err := ioutil.ReadAll(r) +// if err != nil { +// return errors.Wrap(err, "read failed") +// } +// +// If additional control is required the errors.WithStack and errors.WithMessage +// functions destructure errors.Wrap into its component operations of annotating +// an error with a stack trace and an a message, respectively. +// +// Retrieving the cause of an error +// +// Using errors.Wrap constructs a stack of errors, adding context to the +// preceding error. Depending on the nature of the error it may be necessary +// to reverse the operation of errors.Wrap to retrieve the original error +// for inspection. Any error value which implements this interface +// +// type causer interface { +// Cause() error +// } +// +// can be inspected by errors.Cause. errors.Cause will recursively retrieve +// the topmost error which does not implement causer, which is assumed to be +// the original cause. For example: +// +// switch err := errors.Cause(err).(type) { +// case *MyError: +// // handle specifically +// default: +// // unknown error +// } +// +// causer interface is not exported by this package, but is considered a part +// of stable public API. +// +// Formatted printing of errors +// +// All error values returned from this package implement fmt.Formatter and can +// be formatted by the fmt package. The following verbs are supported +// +// %s print the error. If the error has a Cause it will be +// printed recursively +// %v see %s +// %+v extended format. Each Frame of the error's StackTrace will +// be printed in detail. +// +// Retrieving the stack trace of an error or wrapper +// +// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are +// invoked. This information can be retrieved with the following interface. +// +// type stackTracer interface { +// StackTrace() errors.StackTrace +// } +// +// Where errors.StackTrace is defined as +// +// type StackTrace []Frame +// +// The Frame type represents a call site in the stack trace. Frame supports +// the fmt.Formatter interface that can be used for printing information about +// the stack trace of this error. For example: +// +// if err, ok := err.(stackTracer); ok { +// for _, f := range err.StackTrace() { +// fmt.Printf("%+s:%d", f) +// } +// } +// +// stackTracer interface is not exported by this package, but is considered a part +// of stable public API. +// +// See the documentation for Frame.Format for more details. +package errors + +import ( + "fmt" + "io" +) + +// New returns an error with the supplied message. +// New also records the stack trace at the point it was called. +func New(message string) error { + return &fundamental{ + msg: message, + stack: callers(), + } +} + +// Errorf formats according to a format specifier and returns the string +// as a value that satisfies error. +// Errorf also records the stack trace at the point it was called. +func Errorf(format string, args ...interface{}) error { + return &fundamental{ + msg: fmt.Sprintf(format, args...), + stack: callers(), + } +} + +// fundamental is an error that has a message and a stack, but no caller. +type fundamental struct { + msg string + *stack +} + +func (f *fundamental) Error() string { return f.msg } + +func (f *fundamental) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + io.WriteString(s, f.msg) + f.stack.Format(s, verb) + return + } + fallthrough + case 's': + io.WriteString(s, f.msg) + case 'q': + fmt.Fprintf(s, "%q", f.msg) + } +} + +// WithStack annotates err with a stack trace at the point WithStack was called. +// If err is nil, WithStack returns nil. +func WithStack(err error) error { + if err == nil { + return nil + } + return &withStack{ + err, + callers(), + } +} + +type withStack struct { + error + *stack +} + +func (w *withStack) Cause() error { return w.error } + +func (w *withStack) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v", w.Cause()) + w.stack.Format(s, verb) + return + } + fallthrough + case 's': + io.WriteString(s, w.Error()) + case 'q': + fmt.Fprintf(s, "%q", w.Error()) + } +} + +// Wrap returns an error annotating err with a stack trace +// at the point Wrap is called, and the supplied message. +// If err is nil, Wrap returns nil. +func Wrap(err error, message string) error { + if err == nil { + return nil + } + err = &withMessage{ + cause: err, + msg: message, + } + return &withStack{ + err, + callers(), + } +} + +// Wrapf returns an error annotating err with a stack trace +// at the point Wrapf is call, and the format specifier. +// If err is nil, Wrapf returns nil. +func Wrapf(err error, format string, args ...interface{}) error { + if err == nil { + return nil + } + err = &withMessage{ + cause: err, + msg: fmt.Sprintf(format, args...), + } + return &withStack{ + err, + callers(), + } +} + +// WithMessage annotates err with a new message. +// If err is nil, WithMessage returns nil. +func WithMessage(err error, message string) error { + if err == nil { + return nil + } + return &withMessage{ + cause: err, + msg: message, + } +} + +type withMessage struct { + cause error + msg string +} + +func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } +func (w *withMessage) Cause() error { return w.cause } + +func (w *withMessage) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v\n", w.Cause()) + io.WriteString(s, w.msg) + return + } + fallthrough + case 's', 'q': + io.WriteString(s, w.Error()) + } +} + +// Cause returns the underlying cause of the error, if possible. +// An error value has a cause if it implements the following +// interface: +// +// type causer interface { +// Cause() error +// } +// +// If the error does not implement Cause, the original error will +// be returned. If the error is nil, nil will be returned without further +// investigation. +func Cause(err error) error { + type causer interface { + Cause() error + } + + for err != nil { + cause, ok := err.(causer) + if !ok { + break + } + err = cause.Cause() + } + return err +} diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go new file mode 100644 index 0000000000..2874a048cf --- /dev/null +++ b/vendor/github.com/pkg/errors/stack.go @@ -0,0 +1,147 @@ +package errors + +import ( + "fmt" + "io" + "path" + "runtime" + "strings" +) + +// Frame represents a program counter inside a stack frame. +type Frame uintptr + +// pc returns the program counter for this frame; +// multiple frames may have the same PC value. +func (f Frame) pc() uintptr { return uintptr(f) - 1 } + +// file returns the full path to the file that contains the +// function for this Frame's pc. +func (f Frame) file() string { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return "unknown" + } + file, _ := fn.FileLine(f.pc()) + return file +} + +// line returns the line number of source code of the +// function for this Frame's pc. +func (f Frame) line() int { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return 0 + } + _, line := fn.FileLine(f.pc()) + return line +} + +// Format formats the frame according to the fmt.Formatter interface. +// +// %s source file +// %d source line +// %n function name +// %v equivalent to %s:%d +// +// Format accepts flags that alter the printing of some verbs, as follows: +// +// %+s function name and path of source file relative to the compile time +// GOPATH separated by \n\t (\n\t) +// %+v equivalent to %+s:%d +func (f Frame) Format(s fmt.State, verb rune) { + switch verb { + case 's': + switch { + case s.Flag('+'): + pc := f.pc() + fn := runtime.FuncForPC(pc) + if fn == nil { + io.WriteString(s, "unknown") + } else { + file, _ := fn.FileLine(pc) + fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file) + } + default: + io.WriteString(s, path.Base(f.file())) + } + case 'd': + fmt.Fprintf(s, "%d", f.line()) + case 'n': + name := runtime.FuncForPC(f.pc()).Name() + io.WriteString(s, funcname(name)) + case 'v': + f.Format(s, 's') + io.WriteString(s, ":") + f.Format(s, 'd') + } +} + +// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). +type StackTrace []Frame + +// Format formats the stack of Frames according to the fmt.Formatter interface. +// +// %s lists source files for each Frame in the stack +// %v lists the source file and line number for each Frame in the stack +// +// Format accepts flags that alter the printing of some verbs, as follows: +// +// %+v Prints filename, function, and line number for each Frame in the stack. +func (st StackTrace) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + switch { + case s.Flag('+'): + for _, f := range st { + fmt.Fprintf(s, "\n%+v", f) + } + case s.Flag('#'): + fmt.Fprintf(s, "%#v", []Frame(st)) + default: + fmt.Fprintf(s, "%v", []Frame(st)) + } + case 's': + fmt.Fprintf(s, "%s", []Frame(st)) + } +} + +// stack represents a stack of program counters. +type stack []uintptr + +func (s *stack) Format(st fmt.State, verb rune) { + switch verb { + case 'v': + switch { + case st.Flag('+'): + for _, pc := range *s { + f := Frame(pc) + fmt.Fprintf(st, "\n%+v", f) + } + } + } +} + +func (s *stack) StackTrace() StackTrace { + f := make([]Frame, len(*s)) + for i := 0; i < len(f); i++ { + f[i] = Frame((*s)[i]) + } + return f +} + +func callers() *stack { + const depth = 32 + var pcs [depth]uintptr + n := runtime.Callers(3, pcs[:]) + var st stack = pcs[0:n] + return &st +} + +// funcname removes the path prefix component of a function's name reported by func.Name(). +func funcname(name string) string { + i := strings.LastIndex(name, "/") + name = name[i+1:] + i = strings.Index(name, ".") + return name[i+1:] +} diff --git a/vendor/github.com/satori/go.uuid/LICENSE b/vendor/github.com/satori/go.uuid/LICENSE new file mode 100644 index 0000000000..926d549870 --- /dev/null +++ b/vendor/github.com/satori/go.uuid/LICENSE @@ -0,0 +1,20 @@ +Copyright (C) 2013-2018 by Maxim Bublis + +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. diff --git a/vendor/github.com/satori/go.uuid/README.md b/vendor/github.com/satori/go.uuid/README.md new file mode 100644 index 0000000000..7b1a722dff --- /dev/null +++ b/vendor/github.com/satori/go.uuid/README.md @@ -0,0 +1,65 @@ +# UUID package for Go language + +[![Build Status](https://travis-ci.org/satori/go.uuid.png?branch=master)](https://travis-ci.org/satori/go.uuid) +[![Coverage Status](https://coveralls.io/repos/github/satori/go.uuid/badge.svg?branch=master)](https://coveralls.io/github/satori/go.uuid) +[![GoDoc](http://godoc.org/github.com/satori/go.uuid?status.png)](http://godoc.org/github.com/satori/go.uuid) + +This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs. + +With 100% test coverage and benchmarks out of box. + +Supported versions: +* Version 1, based on timestamp and MAC address (RFC 4122) +* Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1) +* Version 3, based on MD5 hashing (RFC 4122) +* Version 4, based on random numbers (RFC 4122) +* Version 5, based on SHA-1 hashing (RFC 4122) + +## Installation + +Use the `go` command: + + $ go get github.com/satori/go.uuid + +## Requirements + +UUID package requires Go >= 1.2. + +## Example + +```go +package main + +import ( + "fmt" + "github.com/satori/go.uuid" +) + +func main() { + // Creating UUID Version 4 + u1 := uuid.NewV4() + fmt.Printf("UUIDv4: %s\n", u1) + + // Parsing UUID from string input + u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") + if err != nil { + fmt.Printf("Something gone wrong: %s", err) + } + fmt.Printf("Successfully parsed: %s", u2) +} +``` + +## Documentation + +[Documentation](http://godoc.org/github.com/satori/go.uuid) is hosted at GoDoc project. + +## Links +* [RFC 4122](http://tools.ietf.org/html/rfc4122) +* [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01) + +## Copyright + +Copyright (C) 2013-2018 by Maxim Bublis . + +UUID package released under MIT License. +See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details. diff --git a/vendor/github.com/satori/go.uuid/codec.go b/vendor/github.com/satori/go.uuid/codec.go new file mode 100644 index 0000000000..656892c53e --- /dev/null +++ b/vendor/github.com/satori/go.uuid/codec.go @@ -0,0 +1,206 @@ +// Copyright (C) 2013-2018 by Maxim Bublis +// +// 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. + +package uuid + +import ( + "bytes" + "encoding/hex" + "fmt" +) + +// FromBytes returns UUID converted from raw byte slice input. +// It will return error if the slice isn't 16 bytes long. +func FromBytes(input []byte) (u UUID, err error) { + err = u.UnmarshalBinary(input) + return +} + +// FromBytesOrNil returns UUID converted from raw byte slice input. +// Same behavior as FromBytes, but returns a Nil UUID on error. +func FromBytesOrNil(input []byte) UUID { + uuid, err := FromBytes(input) + if err != nil { + return Nil + } + return uuid +} + +// FromString returns UUID parsed from string input. +// Input is expected in a form accepted by UnmarshalText. +func FromString(input string) (u UUID, err error) { + err = u.UnmarshalText([]byte(input)) + return +} + +// FromStringOrNil returns UUID parsed from string input. +// Same behavior as FromString, but returns a Nil UUID on error. +func FromStringOrNil(input string) UUID { + uuid, err := FromString(input) + if err != nil { + return Nil + } + return uuid +} + +// MarshalText implements the encoding.TextMarshaler interface. +// The encoding is the same as returned by String. +func (u UUID) MarshalText() (text []byte, err error) { + text = []byte(u.String()) + return +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// Following formats are supported: +// "6ba7b810-9dad-11d1-80b4-00c04fd430c8", +// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", +// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" +// "6ba7b8109dad11d180b400c04fd430c8" +// ABNF for supported UUID text representation follows: +// uuid := canonical | hashlike | braced | urn +// plain := canonical | hashlike +// canonical := 4hexoct '-' 2hexoct '-' 2hexoct '-' 6hexoct +// hashlike := 12hexoct +// braced := '{' plain '}' +// urn := URN ':' UUID-NID ':' plain +// URN := 'urn' +// UUID-NID := 'uuid' +// 12hexoct := 6hexoct 6hexoct +// 6hexoct := 4hexoct 2hexoct +// 4hexoct := 2hexoct 2hexoct +// 2hexoct := hexoct hexoct +// hexoct := hexdig hexdig +// hexdig := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | +// 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | +// 'A' | 'B' | 'C' | 'D' | 'E' | 'F' +func (u *UUID) UnmarshalText(text []byte) (err error) { + switch len(text) { + case 32: + return u.decodeHashLike(text) + case 36: + return u.decodeCanonical(text) + case 38: + return u.decodeBraced(text) + case 41: + fallthrough + case 45: + return u.decodeURN(text) + default: + return fmt.Errorf("uuid: incorrect UUID length: %s", text) + } +} + +// decodeCanonical decodes UUID string in format +// "6ba7b810-9dad-11d1-80b4-00c04fd430c8". +func (u *UUID) decodeCanonical(t []byte) (err error) { + if t[8] != '-' || t[13] != '-' || t[18] != '-' || t[23] != '-' { + return fmt.Errorf("uuid: incorrect UUID format %s", t) + } + + src := t[:] + dst := u[:] + + for i, byteGroup := range byteGroups { + if i > 0 { + src = src[1:] // skip dash + } + _, err = hex.Decode(dst[:byteGroup/2], src[:byteGroup]) + if err != nil { + return + } + src = src[byteGroup:] + dst = dst[byteGroup/2:] + } + + return +} + +// decodeHashLike decodes UUID string in format +// "6ba7b8109dad11d180b400c04fd430c8". +func (u *UUID) decodeHashLike(t []byte) (err error) { + src := t[:] + dst := u[:] + + if _, err = hex.Decode(dst, src); err != nil { + return err + } + return +} + +// decodeBraced decodes UUID string in format +// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" or in format +// "{6ba7b8109dad11d180b400c04fd430c8}". +func (u *UUID) decodeBraced(t []byte) (err error) { + l := len(t) + + if t[0] != '{' || t[l-1] != '}' { + return fmt.Errorf("uuid: incorrect UUID format %s", t) + } + + return u.decodePlain(t[1 : l-1]) +} + +// decodeURN decodes UUID string in format +// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in format +// "urn:uuid:6ba7b8109dad11d180b400c04fd430c8". +func (u *UUID) decodeURN(t []byte) (err error) { + total := len(t) + + urn_uuid_prefix := t[:9] + + if !bytes.Equal(urn_uuid_prefix, urnPrefix) { + return fmt.Errorf("uuid: incorrect UUID format: %s", t) + } + + return u.decodePlain(t[9:total]) +} + +// decodePlain decodes UUID string in canonical format +// "6ba7b810-9dad-11d1-80b4-00c04fd430c8" or in hash-like format +// "6ba7b8109dad11d180b400c04fd430c8". +func (u *UUID) decodePlain(t []byte) (err error) { + switch len(t) { + case 32: + return u.decodeHashLike(t) + case 36: + return u.decodeCanonical(t) + default: + return fmt.Errorf("uuid: incorrrect UUID length: %s", t) + } +} + +// MarshalBinary implements the encoding.BinaryMarshaler interface. +func (u UUID) MarshalBinary() (data []byte, err error) { + data = u.Bytes() + return +} + +// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. +// It will return error if the slice isn't 16 bytes long. +func (u *UUID) UnmarshalBinary(data []byte) (err error) { + if len(data) != Size { + err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data)) + return + } + copy(u[:], data) + + return +} diff --git a/vendor/github.com/satori/go.uuid/generator.go b/vendor/github.com/satori/go.uuid/generator.go new file mode 100644 index 0000000000..3f2f1da2dc --- /dev/null +++ b/vendor/github.com/satori/go.uuid/generator.go @@ -0,0 +1,239 @@ +// Copyright (C) 2013-2018 by Maxim Bublis +// +// 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. + +package uuid + +import ( + "crypto/md5" + "crypto/rand" + "crypto/sha1" + "encoding/binary" + "hash" + "net" + "os" + "sync" + "time" +) + +// Difference in 100-nanosecond intervals between +// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970). +const epochStart = 122192928000000000 + +var ( + global = newDefaultGenerator() + + epochFunc = unixTimeFunc + posixUID = uint32(os.Getuid()) + posixGID = uint32(os.Getgid()) +) + +// NewV1 returns UUID based on current timestamp and MAC address. +func NewV1() UUID { + return global.NewV1() +} + +// NewV2 returns DCE Security UUID based on POSIX UID/GID. +func NewV2(domain byte) UUID { + return global.NewV2(domain) +} + +// NewV3 returns UUID based on MD5 hash of namespace UUID and name. +func NewV3(ns UUID, name string) UUID { + return global.NewV3(ns, name) +} + +// NewV4 returns random generated UUID. +func NewV4() UUID { + return global.NewV4() +} + +// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name. +func NewV5(ns UUID, name string) UUID { + return global.NewV5(ns, name) +} + +// Generator provides interface for generating UUIDs. +type Generator interface { + NewV1() UUID + NewV2(domain byte) UUID + NewV3(ns UUID, name string) UUID + NewV4() UUID + NewV5(ns UUID, name string) UUID +} + +// Default generator implementation. +type generator struct { + storageOnce sync.Once + storageMutex sync.Mutex + + lastTime uint64 + clockSequence uint16 + hardwareAddr [6]byte +} + +func newDefaultGenerator() Generator { + return &generator{} +} + +// NewV1 returns UUID based on current timestamp and MAC address. +func (g *generator) NewV1() UUID { + u := UUID{} + + timeNow, clockSeq, hardwareAddr := g.getStorage() + + binary.BigEndian.PutUint32(u[0:], uint32(timeNow)) + binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) + binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) + binary.BigEndian.PutUint16(u[8:], clockSeq) + + copy(u[10:], hardwareAddr) + + u.SetVersion(V1) + u.SetVariant(VariantRFC4122) + + return u +} + +// NewV2 returns DCE Security UUID based on POSIX UID/GID. +func (g *generator) NewV2(domain byte) UUID { + u := UUID{} + + timeNow, clockSeq, hardwareAddr := g.getStorage() + + switch domain { + case DomainPerson: + binary.BigEndian.PutUint32(u[0:], posixUID) + case DomainGroup: + binary.BigEndian.PutUint32(u[0:], posixGID) + } + + binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) + binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) + binary.BigEndian.PutUint16(u[8:], clockSeq) + u[9] = domain + + copy(u[10:], hardwareAddr) + + u.SetVersion(V2) + u.SetVariant(VariantRFC4122) + + return u +} + +// NewV3 returns UUID based on MD5 hash of namespace UUID and name. +func (g *generator) NewV3(ns UUID, name string) UUID { + u := newFromHash(md5.New(), ns, name) + u.SetVersion(V3) + u.SetVariant(VariantRFC4122) + + return u +} + +// NewV4 returns random generated UUID. +func (g *generator) NewV4() UUID { + u := UUID{} + g.safeRandom(u[:]) + u.SetVersion(V4) + u.SetVariant(VariantRFC4122) + + return u +} + +// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name. +func (g *generator) NewV5(ns UUID, name string) UUID { + u := newFromHash(sha1.New(), ns, name) + u.SetVersion(V5) + u.SetVariant(VariantRFC4122) + + return u +} + +func (g *generator) initStorage() { + g.initClockSequence() + g.initHardwareAddr() +} + +func (g *generator) initClockSequence() { + buf := make([]byte, 2) + g.safeRandom(buf) + g.clockSequence = binary.BigEndian.Uint16(buf) +} + +func (g *generator) initHardwareAddr() { + interfaces, err := net.Interfaces() + if err == nil { + for _, iface := range interfaces { + if len(iface.HardwareAddr) >= 6 { + copy(g.hardwareAddr[:], iface.HardwareAddr) + return + } + } + } + + // Initialize hardwareAddr randomly in case + // of real network interfaces absence + g.safeRandom(g.hardwareAddr[:]) + + // Set multicast bit as recommended in RFC 4122 + g.hardwareAddr[0] |= 0x01 +} + +func (g *generator) safeRandom(dest []byte) { + if _, err := rand.Read(dest); err != nil { + panic(err) + } +} + +// Returns UUID v1/v2 storage state. +// Returns epoch timestamp, clock sequence, and hardware address. +func (g *generator) getStorage() (uint64, uint16, []byte) { + g.storageOnce.Do(g.initStorage) + + g.storageMutex.Lock() + defer g.storageMutex.Unlock() + + timeNow := epochFunc() + // Clock changed backwards since last UUID generation. + // Should increase clock sequence. + if timeNow <= g.lastTime { + g.clockSequence++ + } + g.lastTime = timeNow + + return timeNow, g.clockSequence, g.hardwareAddr[:] +} + +// Returns difference in 100-nanosecond intervals between +// UUID epoch (October 15, 1582) and current time. +// This is default epoch calculation function. +func unixTimeFunc() uint64 { + return epochStart + uint64(time.Now().UnixNano()/100) +} + +// Returns UUID based on hashing of namespace UUID and name. +func newFromHash(h hash.Hash, ns UUID, name string) UUID { + u := UUID{} + h.Write(ns[:]) + h.Write([]byte(name)) + copy(u[:], h.Sum(nil)) + + return u +} diff --git a/vendor/github.com/satori/go.uuid/sql.go b/vendor/github.com/satori/go.uuid/sql.go new file mode 100644 index 0000000000..56759d3905 --- /dev/null +++ b/vendor/github.com/satori/go.uuid/sql.go @@ -0,0 +1,78 @@ +// Copyright (C) 2013-2018 by Maxim Bublis +// +// 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. + +package uuid + +import ( + "database/sql/driver" + "fmt" +) + +// Value implements the driver.Valuer interface. +func (u UUID) Value() (driver.Value, error) { + return u.String(), nil +} + +// Scan implements the sql.Scanner interface. +// A 16-byte slice is handled by UnmarshalBinary, while +// a longer byte slice or a string is handled by UnmarshalText. +func (u *UUID) Scan(src interface{}) error { + switch src := src.(type) { + case []byte: + if len(src) == Size { + return u.UnmarshalBinary(src) + } + return u.UnmarshalText(src) + + case string: + return u.UnmarshalText([]byte(src)) + } + + return fmt.Errorf("uuid: cannot convert %T to UUID", src) +} + +// NullUUID can be used with the standard sql package to represent a +// UUID value that can be NULL in the database +type NullUUID struct { + UUID UUID + Valid bool +} + +// Value implements the driver.Valuer interface. +func (u NullUUID) Value() (driver.Value, error) { + if !u.Valid { + return nil, nil + } + // Delegate to UUID Value function + return u.UUID.Value() +} + +// Scan implements the sql.Scanner interface. +func (u *NullUUID) Scan(src interface{}) error { + if src == nil { + u.UUID, u.Valid = Nil, false + return nil + } + + // Delegate to UUID Scan function + u.Valid = true + return u.UUID.Scan(src) +} diff --git a/vendor/github.com/satori/go.uuid/uuid.go b/vendor/github.com/satori/go.uuid/uuid.go new file mode 100644 index 0000000000..a2b8e2ca2a --- /dev/null +++ b/vendor/github.com/satori/go.uuid/uuid.go @@ -0,0 +1,161 @@ +// Copyright (C) 2013-2018 by Maxim Bublis +// +// 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. + +// Package uuid provides implementation of Universally Unique Identifier (UUID). +// Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and +// version 2 (as specified in DCE 1.1). +package uuid + +import ( + "bytes" + "encoding/hex" +) + +// Size of a UUID in bytes. +const Size = 16 + +// UUID representation compliant with specification +// described in RFC 4122. +type UUID [Size]byte + +// UUID versions +const ( + _ byte = iota + V1 + V2 + V3 + V4 + V5 +) + +// UUID layout variants. +const ( + VariantNCS byte = iota + VariantRFC4122 + VariantMicrosoft + VariantFuture +) + +// UUID DCE domains. +const ( + DomainPerson = iota + DomainGroup + DomainOrg +) + +// String parse helpers. +var ( + urnPrefix = []byte("urn:uuid:") + byteGroups = []int{8, 4, 4, 4, 12} +) + +// Nil is special form of UUID that is specified to have all +// 128 bits set to zero. +var Nil = UUID{} + +// Predefined namespace UUIDs. +var ( + NamespaceDNS = Must(FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")) + NamespaceURL = Must(FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8")) + NamespaceOID = Must(FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8")) + NamespaceX500 = Must(FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8")) +) + +// Equal returns true if u1 and u2 equals, otherwise returns false. +func Equal(u1 UUID, u2 UUID) bool { + return bytes.Equal(u1[:], u2[:]) +} + +// Version returns algorithm version used to generate UUID. +func (u UUID) Version() byte { + return u[6] >> 4 +} + +// Variant returns UUID layout variant. +func (u UUID) Variant() byte { + switch { + case (u[8] >> 7) == 0x00: + return VariantNCS + case (u[8] >> 6) == 0x02: + return VariantRFC4122 + case (u[8] >> 5) == 0x06: + return VariantMicrosoft + case (u[8] >> 5) == 0x07: + fallthrough + default: + return VariantFuture + } +} + +// Bytes returns bytes slice representation of UUID. +func (u UUID) Bytes() []byte { + return u[:] +} + +// Returns canonical string representation of UUID: +// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. +func (u UUID) String() string { + buf := make([]byte, 36) + + hex.Encode(buf[0:8], u[0:4]) + buf[8] = '-' + hex.Encode(buf[9:13], u[4:6]) + buf[13] = '-' + hex.Encode(buf[14:18], u[6:8]) + buf[18] = '-' + hex.Encode(buf[19:23], u[8:10]) + buf[23] = '-' + hex.Encode(buf[24:], u[10:]) + + return string(buf) +} + +// SetVersion sets version bits. +func (u *UUID) SetVersion(v byte) { + u[6] = (u[6] & 0x0f) | (v << 4) +} + +// SetVariant sets variant bits. +func (u *UUID) SetVariant(v byte) { + switch v { + case VariantNCS: + u[8] = (u[8]&(0xff>>1) | (0x00 << 7)) + case VariantRFC4122: + u[8] = (u[8]&(0xff>>2) | (0x02 << 6)) + case VariantMicrosoft: + u[8] = (u[8]&(0xff>>3) | (0x06 << 5)) + case VariantFuture: + fallthrough + default: + u[8] = (u[8]&(0xff>>3) | (0x07 << 5)) + } +} + +// Must is a helper that wraps a call to a function returning (UUID, error) +// and panics if the error is non-nil. It is intended for use in variable +// initializations such as +// var packageUUID = uuid.Must(uuid.FromString("123e4567-e89b-12d3-a456-426655440000")); +func Must(u UUID, err error) UUID { + if err != nil { + panic(err) + } + return u +} diff --git a/vendor/github.com/spf13/cobra/LICENSE.txt b/vendor/github.com/spf13/cobra/LICENSE.txt new file mode 100644 index 0000000000..298f0e2665 --- /dev/null +++ b/vendor/github.com/spf13/cobra/LICENSE.txt @@ -0,0 +1,174 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md new file mode 100644 index 0000000000..da256087d3 --- /dev/null +++ b/vendor/github.com/spf13/cobra/README.md @@ -0,0 +1,734 @@ +![cobra logo](https://cloud.githubusercontent.com/assets/173412/10886352/ad566232-814f-11e5-9cd0-aa101788c117.png) + +Cobra is both a library for creating powerful modern CLI applications as well as a program to generate applications and command files. + +Many of the most widely used Go projects are built using Cobra including: + +* [Kubernetes](http://kubernetes.io/) +* [Hugo](http://gohugo.io) +* [rkt](https://github.com/coreos/rkt) +* [etcd](https://github.com/coreos/etcd) +* [Moby (former Docker)](https://github.com/moby/moby) +* [Docker (distribution)](https://github.com/docker/distribution) +* [OpenShift](https://www.openshift.com/) +* [Delve](https://github.com/derekparker/delve) +* [GopherJS](http://www.gopherjs.org/) +* [CockroachDB](http://www.cockroachlabs.com/) +* [Bleve](http://www.blevesearch.com/) +* [ProjectAtomic (enterprise)](http://www.projectatomic.io/) +* [GiantSwarm's swarm](https://github.com/giantswarm/cli) +* [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack) +* [rclone](http://rclone.org/) +* [nehm](https://github.com/bogem/nehm) +* [Pouch](https://github.com/alibaba/pouch) + +[![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra) +[![CircleCI status](https://circleci.com/gh/spf13/cobra.png?circle-token=:circle-token "CircleCI status")](https://circleci.com/gh/spf13/cobra) +[![GoDoc](https://godoc.org/github.com/spf13/cobra?status.svg)](https://godoc.org/github.com/spf13/cobra) + +# Table of Contents + +- [Overview](#overview) +- [Concepts](#concepts) + * [Commands](#commands) + * [Flags](#flags) +- [Installing](#installing) +- [Getting Started](#getting-started) + * [Using the Cobra Generator](#using-the-cobra-generator) + * [Using the Cobra Library](#using-the-cobra-library) + * [Working with Flags](#working-with-flags) + * [Positional and Custom Arguments](#positional-and-custom-arguments) + * [Example](#example) + * [Help Command](#help-command) + * [Usage Message](#usage-message) + * [PreRun and PostRun Hooks](#prerun-and-postrun-hooks) + * [Suggestions when "unknown command" happens](#suggestions-when-unknown-command-happens) + * [Generating documentation for your command](#generating-documentation-for-your-command) + * [Generating bash completions](#generating-bash-completions) +- [Contributing](#contributing) +- [License](#license) + +# Overview + +Cobra is a library providing a simple interface to create powerful modern CLI +interfaces similar to git & go tools. + +Cobra is also an application that will generate your application scaffolding to rapidly +develop a Cobra-based application. + +Cobra provides: +* Easy subcommand-based CLIs: `app server`, `app fetch`, etc. +* Fully POSIX-compliant flags (including short & long versions) +* Nested subcommands +* Global, local and cascading flags +* Easy generation of applications & commands with `cobra init appname` & `cobra add cmdname` +* Intelligent suggestions (`app srver`... did you mean `app server`?) +* Automatic help generation for commands and flags +* Automatic help flag recognition of `-h`, `--help`, etc. +* Automatically generated bash autocomplete for your application +* Automatically generated man pages for your application +* Command aliases so you can change things without breaking them +* The flexibility to define your own help, usage, etc. +* Optional tight integration with [viper](http://github.com/spf13/viper) for 12-factor apps + +# Concepts + +Cobra is built on a structure of commands, arguments & flags. + +**Commands** represent actions, **Args** are things and **Flags** are modifiers for those actions. + +The best applications will read like sentences when used. Users will know how +to use the application because they will natively understand how to use it. + +The pattern to follow is +`APPNAME VERB NOUN --ADJECTIVE.` + or +`APPNAME COMMAND ARG --FLAG` + +A few good real world examples may better illustrate this point. + +In the following example, 'server' is a command, and 'port' is a flag: + + hugo server --port=1313 + +In this command we are telling Git to clone the url bare. + + git clone URL --bare + +## Commands + +Command is the central point of the application. Each interaction that +the application supports will be contained in a Command. A command can +have children commands and optionally run an action. + +In the example above, 'server' is the command. + +[More about cobra.Command](https://godoc.org/github.com/spf13/cobra#Command) + +## Flags + +A flag is a way to modify the behavior of a command. Cobra supports +fully POSIX-compliant flags as well as the Go [flag package](https://golang.org/pkg/flag/). +A Cobra command can define flags that persist through to children commands +and flags that are only available to that command. + +In the example above, 'port' is the flag. + +Flag functionality is provided by the [pflag +library](https://github.com/spf13/pflag), a fork of the flag standard library +which maintains the same interface while adding POSIX compliance. + +# Installing +Using Cobra is easy. First, use `go get` to install the latest version +of the library. This command will install the `cobra` generator executable +along with the library and its dependencies: + + go get -u github.com/spf13/cobra/cobra + +Next, include Cobra in your application: + +```go +import "github.com/spf13/cobra" +``` + +# Getting Started + +While you are welcome to provide your own organization, typically a Cobra-based +application will follow the following organizational structure: + +``` + ▾ appName/ + ▾ cmd/ + add.go + your.go + commands.go + here.go + main.go +``` + +In a Cobra app, typically the main.go file is very bare. It serves one purpose: initializing Cobra. + +```go +package main + +import ( + + "{pathToYourApp}/cmd" +) + +func main() { + cmd.Execute() +} +``` + +## Using the Cobra Generator + +Cobra provides its own program that will create your application and add any +commands you want. It's the easiest way to incorporate Cobra into your application. + +[Here](https://github.com/spf13/cobra/blob/master/cobra/README.md) you can find more information about it. + +## Using the Cobra Library + +To manually implement Cobra you need to create a bare main.go file and a rootCmd file. +You will optionally provide additional commands as you see fit. + +### Create rootCmd + +Cobra doesn't require any special constructors. Simply create your commands. + +Ideally you place this in app/cmd/root.go: + +```go +var rootCmd = &cobra.Command{ + Use: "hugo", + Short: "Hugo is a very fast static site generator", + Long: `A Fast and Flexible Static Site Generator built with + love by spf13 and friends in Go. + Complete documentation is available at http://hugo.spf13.com`, + Run: func(cmd *cobra.Command, args []string) { + // Do Stuff Here + }, +} + +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} +``` + +You will additionally define flags and handle configuration in your init() function. + +For example cmd/root.go: + +```go +import ( + "fmt" + "os" + + homedir "github.com/mitchellh/go-homedir" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func init() { + cobra.OnInitialize(initConfig) + rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") + rootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/") + rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution") + rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)") + rootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration") + viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")) + viper.BindPFlag("projectbase", rootCmd.PersistentFlags().Lookup("projectbase")) + viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper")) + viper.SetDefault("author", "NAME HERE ") + viper.SetDefault("license", "apache") +} + +func initConfig() { + // Don't forget to read config either from cfgFile or from home directory! + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + // Find home directory. + home, err := homedir.Dir() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // Search config in home directory with name ".cobra" (without extension). + viper.AddConfigPath(home) + viper.SetConfigName(".cobra") + } + + if err := viper.ReadInConfig(); err != nil { + fmt.Println("Can't read config:", err) + os.Exit(1) + } +} +``` + +### Create your main.go + +With the root command you need to have your main function execute it. +Execute should be run on the root for clarity, though it can be called on any command. + +In a Cobra app, typically the main.go file is very bare. It serves, one purpose, to initialize Cobra. + +```go +package main + +import ( + "fmt" + "os" + + "{pathToYourApp}/cmd" +) + +func main() { + cmd.Execute() +} +``` + +### Create additional commands + +Additional commands can be defined and typically are each given their own file +inside of the cmd/ directory. + +If you wanted to create a version command you would create cmd/version.go and +populate it with the following: + +```go +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(versionCmd) +} + +var versionCmd = &cobra.Command{ + Use: "version", + Short: "Print the version number of Hugo", + Long: `All software has versions. This is Hugo's`, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Hugo Static Site Generator v0.9 -- HEAD") + }, +} +``` + +## Working with Flags + +Flags provide modifiers to control how the action command operates. + +### Assign flags to a command + +Since the flags are defined and used in different locations, we need to +define a variable outside with the correct scope to assign the flag to +work with. + +```go +var Verbose bool +var Source string +``` + +There are two different approaches to assign a flag. + +### Persistent Flags + +A flag can be 'persistent' meaning that this flag will be available to the +command it's assigned to as well as every command under that command. For +global flags, assign a flag as a persistent flag on the root. + +```go +rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output") +``` + +### Local Flags + +A flag can also be assigned locally which will only apply to that specific command. + +```go +rootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from") +``` + +### Local Flag on Parent Commands + +By default Cobra only parses local flags on the target command, any local flags on +parent commands are ignored. By enabling `Command.TraverseChildren` Cobra will +parse local flags on each command before executing the target command. + +```go +command := cobra.Command{ + Use: "print [OPTIONS] [COMMANDS]", + TraverseChildren: true, +} +``` + +### Bind Flags with Config + +You can also bind your flags with [viper](https://github.com/spf13/viper): +```go +var author string + +func init() { + rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution") + viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")) +} +``` + +In this example the persistent flag `author` is bound with `viper`. +**Note**, that the variable `author` will not be set to the value from config, +when the `--author` flag is not provided by user. + +More in [viper documentation](https://github.com/spf13/viper#working-with-flags). + +### Required flags + +Flags are optional by default. If instead you wish your command to report an error +when a flag has not been set, mark it as required: +```go +rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)") +rootCmd.MarkFlagRequired("region") +``` + +## Positional and Custom Arguments + +Validation of positional arguments can be specified using the `Args` field +of `Command`. + +The following validators are built in: + +- `NoArgs` - the command will report an error if there are any positional args. +- `ArbitraryArgs` - the command will accept any args. +- `OnlyValidArgs` - the command will report an error if there are any positional args that are not in the `ValidArgs` field of `Command`. +- `MinimumNArgs(int)` - the command will report an error if there are not at least N positional args. +- `MaximumNArgs(int)` - the command will report an error if there are more than N positional args. +- `ExactArgs(int)` - the command will report an error if there are not exactly N positional args. +- `RangeArgs(min, max)` - the command will report an error if the number of args is not between the minimum and maximum number of expected args. + +An example of setting the custom validator: + +```go +var cmd = &cobra.Command{ + Short: "hello", + Args: func(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return errors.New("requires at least one arg") + } + if myapp.IsValidColor(args[0]) { + return nil + } + return fmt.Errorf("invalid color specified: %s", args[0]) + }, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Hello, World!") + }, +} +``` + +## Example + +In the example below, we have defined three commands. Two are at the top level +and one (cmdTimes) is a child of one of the top commands. In this case the root +is not executable meaning that a subcommand is required. This is accomplished +by not providing a 'Run' for the 'rootCmd'. + +We have only defined one flag for a single command. + +More documentation about flags is available at https://github.com/spf13/pflag + +```go +package main + +import ( + "fmt" + "strings" + + "github.com/spf13/cobra" +) + +func main() { + var echoTimes int + + var cmdPrint = &cobra.Command{ + Use: "print [string to print]", + Short: "Print anything to the screen", + Long: `print is for printing anything back to the screen. +For many years people have printed back to the screen.`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Print: " + strings.Join(args, " ")) + }, + } + + var cmdEcho = &cobra.Command{ + Use: "echo [string to echo]", + Short: "Echo anything to the screen", + Long: `echo is for echoing anything back. +Echo works a lot like print, except it has a child command.`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("Print: " + strings.Join(args, " ")) + }, + } + + var cmdTimes = &cobra.Command{ + Use: "times [# times] [string to echo]", + Short: "Echo anything to the screen more times", + Long: `echo things multiple times back to the user by providing +a count and a string.`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + for i := 0; i < echoTimes; i++ { + fmt.Println("Echo: " + strings.Join(args, " ")) + } + }, + } + + cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input") + + var rootCmd = &cobra.Command{Use: "app"} + rootCmd.AddCommand(cmdPrint, cmdEcho) + cmdEcho.AddCommand(cmdTimes) + rootCmd.Execute() +} +``` + +For a more complete example of a larger application, please checkout [Hugo](http://gohugo.io/). + +## Help Command + +Cobra automatically adds a help command to your application when you have subcommands. +This will be called when a user runs 'app help'. Additionally, help will also +support all other commands as input. Say, for instance, you have a command called +'create' without any additional configuration; Cobra will work when 'app help +create' is called. Every command will automatically have the '--help' flag added. + +### Example + +The following output is automatically generated by Cobra. Nothing beyond the +command and flag definitions are needed. + + $ cobra help + + Cobra is a CLI library for Go that empowers applications. + This application is a tool to generate the needed files + to quickly create a Cobra application. + + Usage: + cobra [command] + + Available Commands: + add Add a command to a Cobra Application + help Help about any command + init Initialize a Cobra Application + + Flags: + -a, --author string author name for copyright attribution (default "YOUR NAME") + --config string config file (default is $HOME/.cobra.yaml) + -h, --help help for cobra + -l, --license string name of license for the project + --viper use Viper for configuration (default true) + + Use "cobra [command] --help" for more information about a command. + + +Help is just a command like any other. There is no special logic or behavior +around it. In fact, you can provide your own if you want. + +### Defining your own help + +You can provide your own Help command or your own template for the default command to use +with following functions: + +```go +cmd.SetHelpCommand(cmd *Command) +cmd.SetHelpFunc(f func(*Command, []string)) +cmd.SetHelpTemplate(s string) +``` + +The latter two will also apply to any children commands. + +## Usage Message + +When the user provides an invalid flag or invalid command, Cobra responds by +showing the user the 'usage'. + +### Example +You may recognize this from the help above. That's because the default help +embeds the usage as part of its output. + + $ cobra --invalid + Error: unknown flag: --invalid + Usage: + cobra [command] + + Available Commands: + add Add a command to a Cobra Application + help Help about any command + init Initialize a Cobra Application + + Flags: + -a, --author string author name for copyright attribution (default "YOUR NAME") + --config string config file (default is $HOME/.cobra.yaml) + -h, --help help for cobra + -l, --license string name of license for the project + --viper use Viper for configuration (default true) + + Use "cobra [command] --help" for more information about a command. + +### Defining your own usage +You can provide your own usage function or template for Cobra to use. +Like help, the function and template are overridable through public methods: + +```go +cmd.SetUsageFunc(f func(*Command) error) +cmd.SetUsageTemplate(s string) +``` + +## Version Flag + +Cobra adds a top-level '--version' flag if the Version field is set on the root command. +Running an application with the '--version' flag will print the version to stdout using +the version template. The template can be customized using the +`cmd.SetVersionTemplate(s string)` function. + +## PreRun and PostRun Hooks + +It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order: + +- `PersistentPreRun` +- `PreRun` +- `Run` +- `PostRun` +- `PersistentPostRun` + +An example of two commands which use all of these features is below. When the subcommand is executed, it will run the root command's `PersistentPreRun` but not the root command's `PersistentPostRun`: + +```go +package main + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func main() { + + var rootCmd = &cobra.Command{ + Use: "root [sub]", + Short: "My root command", + PersistentPreRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args) + }, + PreRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PreRun with args: %v\n", args) + }, + Run: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd Run with args: %v\n", args) + }, + PostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PostRun with args: %v\n", args) + }, + PersistentPostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args) + }, + } + + var subCmd = &cobra.Command{ + Use: "sub [no options!]", + Short: "My subcommand", + PreRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd PreRun with args: %v\n", args) + }, + Run: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd Run with args: %v\n", args) + }, + PostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd PostRun with args: %v\n", args) + }, + PersistentPostRun: func(cmd *cobra.Command, args []string) { + fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args) + }, + } + + rootCmd.AddCommand(subCmd) + + rootCmd.SetArgs([]string{""}) + rootCmd.Execute() + fmt.Println() + rootCmd.SetArgs([]string{"sub", "arg1", "arg2"}) + rootCmd.Execute() +} +``` + +Output: +``` +Inside rootCmd PersistentPreRun with args: [] +Inside rootCmd PreRun with args: [] +Inside rootCmd Run with args: [] +Inside rootCmd PostRun with args: [] +Inside rootCmd PersistentPostRun with args: [] + +Inside rootCmd PersistentPreRun with args: [arg1 arg2] +Inside subCmd PreRun with args: [arg1 arg2] +Inside subCmd Run with args: [arg1 arg2] +Inside subCmd PostRun with args: [arg1 arg2] +Inside subCmd PersistentPostRun with args: [arg1 arg2] +``` + +## Suggestions when "unknown command" happens + +Cobra will print automatic suggestions when "unknown command" errors happen. This allows Cobra to behave similarly to the `git` command when a typo happens. For example: + +``` +$ hugo srever +Error: unknown command "srever" for "hugo" + +Did you mean this? + server + +Run 'hugo --help' for usage. +``` + +Suggestions are automatic based on every subcommand registered and use an implementation of [Levenshtein distance](http://en.wikipedia.org/wiki/Levenshtein_distance). Every registered command that matches a minimum distance of 2 (ignoring case) will be displayed as a suggestion. + +If you need to disable suggestions or tweak the string distance in your command, use: + +```go +command.DisableSuggestions = true +``` + +or + +```go +command.SuggestionsMinimumDistance = 1 +``` + +You can also explicitly set names for which a given command will be suggested using the `SuggestFor` attribute. This allows suggestions for strings that are not close in terms of string distance, but makes sense in your set of commands and for some which you don't want aliases. Example: + +``` +$ kubectl remove +Error: unknown command "remove" for "kubectl" + +Did you mean this? + delete + +Run 'kubectl help' for usage. +``` + +## Generating documentation for your command + +Cobra can generate documentation based on subcommands, flags, etc. in the following formats: + +- [Markdown](doc/md_docs.md) +- [ReStructured Text](doc/rest_docs.md) +- [Man Page](doc/man_docs.md) + +## Generating bash completions + +Cobra can generate a bash-completion file. If you add more information to your command, these completions can be amazingly powerful and flexible. Read more about it in [Bash Completions](bash_completions.md). + +# Contributing + +1. Fork it +2. Download your fork to your PC (`git clone https://github.com/your_username/cobra && cd cobra`) +3. Create your feature branch (`git checkout -b my-new-feature`) +4. Make changes and add them (`git add .`) +5. Commit your changes (`git commit -m 'Add some feature'`) +6. Push to the branch (`git push origin my-new-feature`) +7. Create new pull request + +# License + +Cobra is released under the Apache 2.0 license. See [LICENSE.txt](https://github.com/spf13/cobra/blob/master/LICENSE.txt) diff --git a/vendor/github.com/spf13/cobra/args.go b/vendor/github.com/spf13/cobra/args.go new file mode 100644 index 0000000000..a5d8a9273e --- /dev/null +++ b/vendor/github.com/spf13/cobra/args.go @@ -0,0 +1,89 @@ +package cobra + +import ( + "fmt" +) + +type PositionalArgs func(cmd *Command, args []string) error + +// Legacy arg validation has the following behaviour: +// - root commands with no subcommands can take arbitrary arguments +// - root commands with subcommands will do subcommand validity checking +// - subcommands will always accept arbitrary arguments +func legacyArgs(cmd *Command, args []string) error { + // no subcommand, always take args + if !cmd.HasSubCommands() { + return nil + } + + // root command with subcommands, do subcommand checking. + if !cmd.HasParent() && len(args) > 0 { + return fmt.Errorf("unknown command %q for %q%s", args[0], cmd.CommandPath(), cmd.findSuggestions(args[0])) + } + return nil +} + +// NoArgs returns an error if any args are included. +func NoArgs(cmd *Command, args []string) error { + if len(args) > 0 { + return fmt.Errorf("unknown command %q for %q", args[0], cmd.CommandPath()) + } + return nil +} + +// OnlyValidArgs returns an error if any args are not in the list of ValidArgs. +func OnlyValidArgs(cmd *Command, args []string) error { + if len(cmd.ValidArgs) > 0 { + for _, v := range args { + if !stringInSlice(v, cmd.ValidArgs) { + return fmt.Errorf("invalid argument %q for %q%s", v, cmd.CommandPath(), cmd.findSuggestions(args[0])) + } + } + } + return nil +} + +// ArbitraryArgs never returns an error. +func ArbitraryArgs(cmd *Command, args []string) error { + return nil +} + +// MinimumNArgs returns an error if there is not at least N args. +func MinimumNArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) < n { + return fmt.Errorf("requires at least %d arg(s), only received %d", n, len(args)) + } + return nil + } +} + +// MaximumNArgs returns an error if there are more than N args. +func MaximumNArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) > n { + return fmt.Errorf("accepts at most %d arg(s), received %d", n, len(args)) + } + return nil + } +} + +// ExactArgs returns an error if there are not exactly n args. +func ExactArgs(n int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) != n { + return fmt.Errorf("accepts %d arg(s), received %d", n, len(args)) + } + return nil + } +} + +// RangeArgs returns an error if the number of args is not within the expected range. +func RangeArgs(min int, max int) PositionalArgs { + return func(cmd *Command, args []string) error { + if len(args) < min || len(args) > max { + return fmt.Errorf("accepts between %d and %d arg(s), received %d", min, max, len(args)) + } + return nil + } +} diff --git a/vendor/github.com/spf13/cobra/bash_completions.go b/vendor/github.com/spf13/cobra/bash_completions.go new file mode 100644 index 0000000000..63274d96f5 --- /dev/null +++ b/vendor/github.com/spf13/cobra/bash_completions.go @@ -0,0 +1,590 @@ +package cobra + +import ( + "bytes" + "fmt" + "io" + "os" + "sort" + "strings" + + "github.com/spf13/pflag" +) + +// Annotations for Bash completion. +const ( + BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extensions" + BashCompCustom = "cobra_annotation_bash_completion_custom" + BashCompOneRequiredFlag = "cobra_annotation_bash_completion_one_required_flag" + BashCompSubdirsInDir = "cobra_annotation_bash_completion_subdirs_in_dir" +) + +func writePreamble(buf *bytes.Buffer, name string) { + buf.WriteString(fmt.Sprintf("# bash completion for %-36s -*- shell-script -*-\n", name)) + buf.WriteString(fmt.Sprintf(` +__%[1]s_debug() +{ + if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then + echo "$*" >> "${BASH_COMP_DEBUG_FILE}" + fi +} + +# Homebrew on Macs have version 1.3 of bash-completion which doesn't include +# _init_completion. This is a very minimal version of that function. +__%[1]s_init_completion() +{ + COMPREPLY=() + _get_comp_words_by_ref "$@" cur prev words cword +} + +__%[1]s_index_of_word() +{ + local w word=$1 + shift + index=0 + for w in "$@"; do + [[ $w = "$word" ]] && return + index=$((index+1)) + done + index=-1 +} + +__%[1]s_contains_word() +{ + local w word=$1; shift + for w in "$@"; do + [[ $w = "$word" ]] && return + done + return 1 +} + +__%[1]s_handle_reply() +{ + __%[1]s_debug "${FUNCNAME[0]}" + case $cur in + -*) + if [[ $(type -t compopt) = "builtin" ]]; then + compopt -o nospace + fi + local allflags + if [ ${#must_have_one_flag[@]} -ne 0 ]; then + allflags=("${must_have_one_flag[@]}") + else + allflags=("${flags[*]} ${two_word_flags[*]}") + fi + COMPREPLY=( $(compgen -W "${allflags[*]}" -- "$cur") ) + if [[ $(type -t compopt) = "builtin" ]]; then + [[ "${COMPREPLY[0]}" == *= ]] || compopt +o nospace + fi + + # complete after --flag=abc + if [[ $cur == *=* ]]; then + if [[ $(type -t compopt) = "builtin" ]]; then + compopt +o nospace + fi + + local index flag + flag="${cur%%=*}" + __%[1]s_index_of_word "${flag}" "${flags_with_completion[@]}" + COMPREPLY=() + if [[ ${index} -ge 0 ]]; then + PREFIX="" + cur="${cur#*=}" + ${flags_completion[${index}]} + if [ -n "${ZSH_VERSION}" ]; then + # zsh completion needs --flag= prefix + eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )" + fi + fi + fi + return 0; + ;; + esac + + # check if we are handling a flag with special work handling + local index + __%[1]s_index_of_word "${prev}" "${flags_with_completion[@]}" + if [[ ${index} -ge 0 ]]; then + ${flags_completion[${index}]} + return + fi + + # we are parsing a flag and don't have a special handler, no completion + if [[ ${cur} != "${words[cword]}" ]]; then + return + fi + + local completions + completions=("${commands[@]}") + if [[ ${#must_have_one_noun[@]} -ne 0 ]]; then + completions=("${must_have_one_noun[@]}") + fi + if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then + completions+=("${must_have_one_flag[@]}") + fi + COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") ) + + if [[ ${#COMPREPLY[@]} -eq 0 && ${#noun_aliases[@]} -gt 0 && ${#must_have_one_noun[@]} -ne 0 ]]; then + COMPREPLY=( $(compgen -W "${noun_aliases[*]}" -- "$cur") ) + fi + + if [[ ${#COMPREPLY[@]} -eq 0 ]]; then + if declare -F __%[1]s_custom_func >/dev/null; then + # try command name qualified custom func + __%[1]s_custom_func + else + # otherwise fall back to unqualified for compatibility + declare -F ___custom_func >/dev/null && __custom_func + fi + fi + + # available in bash-completion >= 2, not always present on macOS + if declare -F __ltrim_colon_completions >/dev/null; then + __ltrim_colon_completions "$cur" + fi + + # If there is only 1 completion and it is a flag with an = it will be completed + # but we don't want a space after the = + if [[ "${#COMPREPLY[@]}" -eq "1" ]] && [[ $(type -t compopt) = "builtin" ]] && [[ "${COMPREPLY[0]}" == --*= ]]; then + compopt -o nospace + fi +} + +# The arguments should be in the form "ext1|ext2|extn" +__%[1]s_handle_filename_extension_flag() +{ + local ext="$1" + _filedir "@(${ext})" +} + +__%[1]s_handle_subdirs_in_dir_flag() +{ + local dir="$1" + pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 +} + +__%[1]s_handle_flag() +{ + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + + # if a command required a flag, and we found it, unset must_have_one_flag() + local flagname=${words[c]} + local flagvalue + # if the word contained an = + if [[ ${words[c]} == *"="* ]]; then + flagvalue=${flagname#*=} # take in as flagvalue after the = + flagname=${flagname%%=*} # strip everything after the = + flagname="${flagname}=" # but put the = back + fi + __%[1]s_debug "${FUNCNAME[0]}: looking for ${flagname}" + if __%[1]s_contains_word "${flagname}" "${must_have_one_flag[@]}"; then + must_have_one_flag=() + fi + + # if you set a flag which only applies to this command, don't show subcommands + if __%[1]s_contains_word "${flagname}" "${local_nonpersistent_flags[@]}"; then + commands=() + fi + + # keep flag value with flagname as flaghash + # flaghash variable is an associative array which is only supported in bash > 3. + if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then + if [ -n "${flagvalue}" ] ; then + flaghash[${flagname}]=${flagvalue} + elif [ -n "${words[ $((c+1)) ]}" ] ; then + flaghash[${flagname}]=${words[ $((c+1)) ]} + else + flaghash[${flagname}]="true" # pad "true" for bool flag + fi + fi + + # skip the argument to a two word flag + if __%[1]s_contains_word "${words[c]}" "${two_word_flags[@]}"; then + c=$((c+1)) + # if we are looking for a flags value, don't show commands + if [[ $c -eq $cword ]]; then + commands=() + fi + fi + + c=$((c+1)) + +} + +__%[1]s_handle_noun() +{ + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + + if __%[1]s_contains_word "${words[c]}" "${must_have_one_noun[@]}"; then + must_have_one_noun=() + elif __%[1]s_contains_word "${words[c]}" "${noun_aliases[@]}"; then + must_have_one_noun=() + fi + + nouns+=("${words[c]}") + c=$((c+1)) +} + +__%[1]s_handle_command() +{ + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + + local next_command + if [[ -n ${last_command} ]]; then + next_command="_${last_command}_${words[c]//:/__}" + else + if [[ $c -eq 0 ]]; then + next_command="_%[1]s_root_command" + else + next_command="_${words[c]//:/__}" + fi + fi + c=$((c+1)) + __%[1]s_debug "${FUNCNAME[0]}: looking for ${next_command}" + declare -F "$next_command" >/dev/null && $next_command +} + +__%[1]s_handle_word() +{ + if [[ $c -ge $cword ]]; then + __%[1]s_handle_reply + return + fi + __%[1]s_debug "${FUNCNAME[0]}: c is $c words[c] is ${words[c]}" + if [[ "${words[c]}" == -* ]]; then + __%[1]s_handle_flag + elif __%[1]s_contains_word "${words[c]}" "${commands[@]}"; then + __%[1]s_handle_command + elif [[ $c -eq 0 ]]; then + __%[1]s_handle_command + elif __%[1]s_contains_word "${words[c]}" "${command_aliases[@]}"; then + # aliashash variable is an associative array which is only supported in bash > 3. + if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then + words[c]=${aliashash[${words[c]}]} + __%[1]s_handle_command + else + __%[1]s_handle_noun + fi + else + __%[1]s_handle_noun + fi + __%[1]s_handle_word +} + +`, name)) +} + +func writePostscript(buf *bytes.Buffer, name string) { + name = strings.Replace(name, ":", "__", -1) + buf.WriteString(fmt.Sprintf("__start_%s()\n", name)) + buf.WriteString(fmt.Sprintf(`{ + local cur prev words cword + declare -A flaghash 2>/dev/null || : + declare -A aliashash 2>/dev/null || : + if declare -F _init_completion >/dev/null 2>&1; then + _init_completion -s || return + else + __%[1]s_init_completion -n "=" || return + fi + + local c=0 + local flags=() + local two_word_flags=() + local local_nonpersistent_flags=() + local flags_with_completion=() + local flags_completion=() + local commands=("%[1]s") + local must_have_one_flag=() + local must_have_one_noun=() + local last_command + local nouns=() + + __%[1]s_handle_word +} + +`, name)) + buf.WriteString(fmt.Sprintf(`if [[ $(type -t compopt) = "builtin" ]]; then + complete -o default -F __start_%s %s +else + complete -o default -o nospace -F __start_%s %s +fi + +`, name, name, name, name)) + buf.WriteString("# ex: ts=4 sw=4 et filetype=sh\n") +} + +func writeCommands(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" commands=()\n") + for _, c := range cmd.Commands() { + if !c.IsAvailableCommand() || c == cmd.helpCommand { + continue + } + buf.WriteString(fmt.Sprintf(" commands+=(%q)\n", c.Name())) + writeCmdAliases(buf, c) + } + buf.WriteString("\n") +} + +func writeFlagHandler(buf *bytes.Buffer, name string, annotations map[string][]string, cmd *Command) { + for key, value := range annotations { + switch key { + case BashCompFilenameExt: + buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + + var ext string + if len(value) > 0 { + ext = fmt.Sprintf("__%s_handle_filename_extension_flag ", cmd.Root().Name()) + strings.Join(value, "|") + } else { + ext = "_filedir" + } + buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext)) + case BashCompCustom: + buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + if len(value) > 0 { + handlers := strings.Join(value, "; ") + buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", handlers)) + } else { + buf.WriteString(" flags_completion+=(:)\n") + } + case BashCompSubdirsInDir: + buf.WriteString(fmt.Sprintf(" flags_with_completion+=(%q)\n", name)) + + var ext string + if len(value) == 1 { + ext = fmt.Sprintf("__%s_handle_subdirs_in_dir_flag ", cmd.Root().Name()) + value[0] + } else { + ext = "_filedir -d" + } + buf.WriteString(fmt.Sprintf(" flags_completion+=(%q)\n", ext)) + } + } +} + +func writeShortFlag(buf *bytes.Buffer, flag *pflag.Flag, cmd *Command) { + name := flag.Shorthand + format := " " + if len(flag.NoOptDefVal) == 0 { + format += "two_word_" + } + format += "flags+=(\"-%s\")\n" + buf.WriteString(fmt.Sprintf(format, name)) + writeFlagHandler(buf, "-"+name, flag.Annotations, cmd) +} + +func writeFlag(buf *bytes.Buffer, flag *pflag.Flag, cmd *Command) { + name := flag.Name + format := " flags+=(\"--%s" + if len(flag.NoOptDefVal) == 0 { + format += "=" + } + format += "\")\n" + buf.WriteString(fmt.Sprintf(format, name)) + writeFlagHandler(buf, "--"+name, flag.Annotations, cmd) +} + +func writeLocalNonPersistentFlag(buf *bytes.Buffer, flag *pflag.Flag) { + name := flag.Name + format := " local_nonpersistent_flags+=(\"--%s" + if len(flag.NoOptDefVal) == 0 { + format += "=" + } + format += "\")\n" + buf.WriteString(fmt.Sprintf(format, name)) +} + +func writeFlags(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(` flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + +`) + localNonPersistentFlags := cmd.LocalNonPersistentFlags() + cmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) { + if nonCompletableFlag(flag) { + return + } + writeFlag(buf, flag, cmd) + if len(flag.Shorthand) > 0 { + writeShortFlag(buf, flag, cmd) + } + if localNonPersistentFlags.Lookup(flag.Name) != nil { + writeLocalNonPersistentFlag(buf, flag) + } + }) + cmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) { + if nonCompletableFlag(flag) { + return + } + writeFlag(buf, flag, cmd) + if len(flag.Shorthand) > 0 { + writeShortFlag(buf, flag, cmd) + } + }) + + buf.WriteString("\n") +} + +func writeRequiredFlag(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" must_have_one_flag=()\n") + flags := cmd.NonInheritedFlags() + flags.VisitAll(func(flag *pflag.Flag) { + if nonCompletableFlag(flag) { + return + } + for key := range flag.Annotations { + switch key { + case BashCompOneRequiredFlag: + format := " must_have_one_flag+=(\"--%s" + if flag.Value.Type() != "bool" { + format += "=" + } + format += "\")\n" + buf.WriteString(fmt.Sprintf(format, flag.Name)) + + if len(flag.Shorthand) > 0 { + buf.WriteString(fmt.Sprintf(" must_have_one_flag+=(\"-%s\")\n", flag.Shorthand)) + } + } + } + }) +} + +func writeRequiredNouns(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" must_have_one_noun=()\n") + sort.Sort(sort.StringSlice(cmd.ValidArgs)) + for _, value := range cmd.ValidArgs { + buf.WriteString(fmt.Sprintf(" must_have_one_noun+=(%q)\n", value)) + } +} + +func writeCmdAliases(buf *bytes.Buffer, cmd *Command) { + if len(cmd.Aliases) == 0 { + return + } + + sort.Sort(sort.StringSlice(cmd.Aliases)) + + buf.WriteString(fmt.Sprint(` if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then`, "\n")) + for _, value := range cmd.Aliases { + buf.WriteString(fmt.Sprintf(" command_aliases+=(%q)\n", value)) + buf.WriteString(fmt.Sprintf(" aliashash[%q]=%q\n", value, cmd.Name())) + } + buf.WriteString(` fi`) + buf.WriteString("\n") +} +func writeArgAliases(buf *bytes.Buffer, cmd *Command) { + buf.WriteString(" noun_aliases=()\n") + sort.Sort(sort.StringSlice(cmd.ArgAliases)) + for _, value := range cmd.ArgAliases { + buf.WriteString(fmt.Sprintf(" noun_aliases+=(%q)\n", value)) + } +} + +func gen(buf *bytes.Buffer, cmd *Command) { + for _, c := range cmd.Commands() { + if !c.IsAvailableCommand() || c == cmd.helpCommand { + continue + } + gen(buf, c) + } + commandName := cmd.CommandPath() + commandName = strings.Replace(commandName, " ", "_", -1) + commandName = strings.Replace(commandName, ":", "__", -1) + + if cmd.Root() == cmd { + buf.WriteString(fmt.Sprintf("_%s_root_command()\n{\n", commandName)) + } else { + buf.WriteString(fmt.Sprintf("_%s()\n{\n", commandName)) + } + + buf.WriteString(fmt.Sprintf(" last_command=%q\n", commandName)) + buf.WriteString("\n") + buf.WriteString(" command_aliases=()\n") + buf.WriteString("\n") + + writeCommands(buf, cmd) + writeFlags(buf, cmd) + writeRequiredFlag(buf, cmd) + writeRequiredNouns(buf, cmd) + writeArgAliases(buf, cmd) + buf.WriteString("}\n\n") +} + +// GenBashCompletion generates bash completion file and writes to the passed writer. +func (c *Command) GenBashCompletion(w io.Writer) error { + buf := new(bytes.Buffer) + writePreamble(buf, c.Name()) + if len(c.BashCompletionFunction) > 0 { + buf.WriteString(c.BashCompletionFunction + "\n") + } + gen(buf, c) + writePostscript(buf, c.Name()) + + _, err := buf.WriteTo(w) + return err +} + +func nonCompletableFlag(flag *pflag.Flag) bool { + return flag.Hidden || len(flag.Deprecated) > 0 +} + +// GenBashCompletionFile generates bash completion file. +func (c *Command) GenBashCompletionFile(filename string) error { + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() + + return c.GenBashCompletion(outFile) +} + +// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag if it exists, +// and causes your command to report an error if invoked without the flag. +func (c *Command) MarkFlagRequired(name string) error { + return MarkFlagRequired(c.Flags(), name) +} + +// MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag if it exists, +// and causes your command to report an error if invoked without the flag. +func (c *Command) MarkPersistentFlagRequired(name string) error { + return MarkFlagRequired(c.PersistentFlags(), name) +} + +// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag if it exists, +// and causes your command to report an error if invoked without the flag. +func MarkFlagRequired(flags *pflag.FlagSet, name string) error { + return flags.SetAnnotation(name, BashCompOneRequiredFlag, []string{"true"}) +} + +// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag, if it exists. +// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. +func (c *Command) MarkFlagFilename(name string, extensions ...string) error { + return MarkFlagFilename(c.Flags(), name, extensions...) +} + +// MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists. +// Generated bash autocompletion will call the bash function f for the flag. +func (c *Command) MarkFlagCustom(name string, f string) error { + return MarkFlagCustom(c.Flags(), name, f) +} + +// MarkPersistentFlagFilename adds the BashCompFilenameExt annotation to the named persistent flag, if it exists. +// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. +func (c *Command) MarkPersistentFlagFilename(name string, extensions ...string) error { + return MarkFlagFilename(c.PersistentFlags(), name, extensions...) +} + +// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag in the flag set, if it exists. +// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. +func MarkFlagFilename(flags *pflag.FlagSet, name string, extensions ...string) error { + return flags.SetAnnotation(name, BashCompFilenameExt, extensions) +} + +// MarkFlagCustom adds the BashCompCustom annotation to the named flag in the flag set, if it exists. +// Generated bash autocompletion will call the bash function f for the flag. +func MarkFlagCustom(flags *pflag.FlagSet, name string, f string) error { + return flags.SetAnnotation(name, BashCompCustom, []string{f}) +} diff --git a/vendor/github.com/spf13/cobra/bash_completions.md b/vendor/github.com/spf13/cobra/bash_completions.md new file mode 100644 index 0000000000..3bd32e0ce8 --- /dev/null +++ b/vendor/github.com/spf13/cobra/bash_completions.md @@ -0,0 +1,256 @@ +# Generating Bash Completions For Your Own cobra.Command + +If you are using the generator you can create a completion command by running + +```bash +cobra add completion +``` + +Update the help text show how to install the bash_completion Linux show here [Kubectl docs show mac options](https://kubernetes.io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletion) + +Writing the shell script to stdout allows the most flexible use. + +```go +// completionCmd represents the completion command +var completionCmd = &cobra.Command{ + Use: "completion", + Short: "Generates bash completion scripts", + Long: `To load completion run + +. <(bitbucket completion) + +To configure your bash shell to load completions for each session add to your bashrc + +# ~/.bashrc or ~/.profile +. <(bitbucket completion) +`, + Run: func(cmd *cobra.Command, args []string) { + rootCmd.GenBashCompletion(os.Stdout); + }, +} +``` + +**Note:** The cobra generator may include messages printed to stdout for example if the config file is loaded, this will break the auto complete script + + +## Example from kubectl + +Generating bash completions from a cobra command is incredibly easy. An actual program which does so for the kubernetes kubectl binary is as follows: + +```go +package main + +import ( + "io/ioutil" + "os" + + "k8s.io/kubernetes/pkg/kubectl/cmd" + "k8s.io/kubernetes/pkg/kubectl/cmd/util" +) + +func main() { + kubectl := cmd.NewKubectlCommand(util.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) + kubectl.GenBashCompletionFile("out.sh") +} +``` + +`out.sh` will get you completions of subcommands and flags. Copy it to `/etc/bash_completion.d/` as described [here](https://debian-administration.org/article/316/An_introduction_to_bash_completion_part_1) and reset your terminal to use autocompletion. If you make additional annotations to your code, you can get even more intelligent and flexible behavior. + +## Creating your own custom functions + +Some more actual code that works in kubernetes: + +```bash +const ( + bash_completion_func = `__kubectl_parse_get() +{ + local kubectl_output out + if kubectl_output=$(kubectl get --no-headers "$1" 2>/dev/null); then + out=($(echo "${kubectl_output}" | awk '{print $1}')) + COMPREPLY=( $( compgen -W "${out[*]}" -- "$cur" ) ) + fi +} + +__kubectl_get_resource() +{ + if [[ ${#nouns[@]} -eq 0 ]]; then + return 1 + fi + __kubectl_parse_get ${nouns[${#nouns[@]} -1]} + if [[ $? -eq 0 ]]; then + return 0 + fi +} + +__kubectl_custom_func() { + case ${last_command} in + kubectl_get | kubectl_describe | kubectl_delete | kubectl_stop) + __kubectl_get_resource + return + ;; + *) + ;; + esac +} +`) +``` + +And then I set that in my command definition: + +```go +cmds := &cobra.Command{ + Use: "kubectl", + Short: "kubectl controls the Kubernetes cluster manager", + Long: `kubectl controls the Kubernetes cluster manager. + +Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`, + Run: runHelp, + BashCompletionFunction: bash_completion_func, +} +``` + +The `BashCompletionFunction` option is really only valid/useful on the root command. Doing the above will cause `___kubectl_custom_func()` (`___custom_func()`) to be called when the built in processor was unable to find a solution. In the case of kubernetes a valid command might look something like `kubectl get pod [mypod]`. If you type `kubectl get pod [tab][tab]` the `__kubectl_customc_func()` will run because the cobra.Command only understood "kubectl" and "get." `__kubectl_custom_func()` will see that the cobra.Command is "kubectl_get" and will thus call another helper `__kubectl_get_resource()`. `__kubectl_get_resource` will look at the 'nouns' collected. In our example the only noun will be `pod`. So it will call `__kubectl_parse_get pod`. `__kubectl_parse_get` will actually call out to kubernetes and get any pods. It will then set `COMPREPLY` to valid pods! + +## Have the completions code complete your 'nouns' + +In the above example "pod" was assumed to already be typed. But if you want `kubectl get [tab][tab]` to show a list of valid "nouns" you have to set them. Simplified code from `kubectl get` looks like: + +```go +validArgs []string = { "pod", "node", "service", "replicationcontroller" } + +cmd := &cobra.Command{ + Use: "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)", + Short: "Display one or many resources", + Long: get_long, + Example: get_example, + Run: func(cmd *cobra.Command, args []string) { + err := RunGet(f, out, cmd, args) + util.CheckErr(err) + }, + ValidArgs: validArgs, +} +``` + +Notice we put the "ValidArgs" on the "get" subcommand. Doing so will give results like + +```bash +# kubectl get [tab][tab] +node pod replicationcontroller service +``` + +## Plural form and shortcuts for nouns + +If your nouns have a number of aliases, you can define them alongside `ValidArgs` using `ArgAliases`: + +```go +argAliases []string = { "pods", "nodes", "services", "svc", "replicationcontrollers", "rc" } + +cmd := &cobra.Command{ + ... + ValidArgs: validArgs, + ArgAliases: argAliases +} +``` + +The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by +the completion algorithm if entered manually, e.g. in: + +```bash +# kubectl get rc [tab][tab] +backend frontend database +``` + +Note that without declaring `rc` as an alias, the completion algorithm would show the list of nouns +in this example again instead of the replication controllers. + +## Mark flags as required + +Most of the time completions will only show subcommands. But if a flag is required to make a subcommand work, you probably want it to show up when the user types [tab][tab]. Marking a flag as 'Required' is incredibly easy. + +```go +cmd.MarkFlagRequired("pod") +cmd.MarkFlagRequired("container") +``` + +and you'll get something like + +```bash +# kubectl exec [tab][tab][tab] +-c --container= -p --pod= +``` + +# Specify valid filename extensions for flags that take a filename + +In this example we use --filename= and expect to get a json or yaml file as the argument. To make this easier we annotate the --filename flag with valid filename extensions. + +```go + annotations := []string{"json", "yaml", "yml"} + annotation := make(map[string][]string) + annotation[cobra.BashCompFilenameExt] = annotations + + flag := &pflag.Flag{ + Name: "filename", + Shorthand: "f", + Usage: usage, + Value: value, + DefValue: value.String(), + Annotations: annotation, + } + cmd.Flags().AddFlag(flag) +``` + +Now when you run a command with this filename flag you'll get something like + +```bash +# kubectl create -f +test/ example/ rpmbuild/ +hello.yml test.json +``` + +So while there are many other files in the CWD it only shows me subdirs and those with valid extensions. + +# Specify custom flag completion + +Similar to the filename completion and filtering using cobra.BashCompFilenameExt, you can specify +a custom flag completion function with cobra.BashCompCustom: + +```go + annotation := make(map[string][]string) + annotation[cobra.BashCompCustom] = []string{"__kubectl_get_namespaces"} + + flag := &pflag.Flag{ + Name: "namespace", + Usage: usage, + Annotations: annotation, + } + cmd.Flags().AddFlag(flag) +``` + +In addition add the `__handle_namespace_flag` implementation in the `BashCompletionFunction` +value, e.g.: + +```bash +__kubectl_get_namespaces() +{ + local template + template="{{ range .items }}{{ .metadata.name }} {{ end }}" + local kubectl_out + if kubectl_out=$(kubectl get -o template --template="${template}" namespace 2>/dev/null); then + COMPREPLY=( $( compgen -W "${kubectl_out}[*]" -- "$cur" ) ) + fi +} +``` +# Using bash aliases for commands + +You can also configure the `bash aliases` for the commands and they will also support completions. + +```bash +alias aliasname=origcommand +complete -o default -F __start_origcommand aliasname + +# and now when you run `aliasname` completion will make +# suggestions as it did for `origcommand`. + +$) aliasname +completion firstcommand secondcommand +``` diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go new file mode 100644 index 0000000000..57bd65ba61 --- /dev/null +++ b/vendor/github.com/spf13/cobra/cobra.go @@ -0,0 +1,200 @@ +// Copyright © 2013 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Commands similar to git, go tools and other modern CLI tools +// inspired by go, go-Commander, gh and subcommand + +package cobra + +import ( + "fmt" + "io" + "reflect" + "strconv" + "strings" + "text/template" + "unicode" +) + +var templateFuncs = template.FuncMap{ + "trim": strings.TrimSpace, + "trimRightSpace": trimRightSpace, + "trimTrailingWhitespaces": trimRightSpace, + "appendIfNotPresent": appendIfNotPresent, + "rpad": rpad, + "gt": Gt, + "eq": Eq, +} + +var initializers []func(*Command) + +// EnablePrefixMatching allows to set automatic prefix matching. Automatic prefix matching can be a dangerous thing +// to automatically enable in CLI tools. +// Set this to true to enable it. +var EnablePrefixMatching = false + +// EnableCommandSorting controls sorting of the slice of commands, which is turned on by default. +// To disable sorting, set it to false. +var EnableCommandSorting = true + +// MousetrapHelpText enables an information splash screen on Windows +// if the CLI is started from explorer.exe. +// To disable the mousetrap, just set this variable to blank string (""). +// Works only on Microsoft Windows. +var MousetrapHelpText string = `This is a command line tool. + +You need to open cmd.exe and run it from there. +` + +// AddTemplateFunc adds a template function that's available to Usage and Help +// template generation. +func AddTemplateFunc(name string, tmplFunc interface{}) { + templateFuncs[name] = tmplFunc +} + +// AddTemplateFuncs adds multiple template functions that are available to Usage and +// Help template generation. +func AddTemplateFuncs(tmplFuncs template.FuncMap) { + for k, v := range tmplFuncs { + templateFuncs[k] = v + } +} + +// OnInitialize sets the passed functions to be run when each command's +// Execute method is called. +func OnInitialize(y ...func(cmd *Command)) { + initializers = append(initializers, y...) +} + +// FIXME Gt is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. + +// Gt takes two types and checks whether the first type is greater than the second. In case of types Arrays, Chans, +// Maps and Slices, Gt will compare their lengths. Ints are compared directly while strings are first parsed as +// ints and then compared. +func Gt(a interface{}, b interface{}) bool { + var left, right int64 + av := reflect.ValueOf(a) + + switch av.Kind() { + case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: + left = int64(av.Len()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + left = av.Int() + case reflect.String: + left, _ = strconv.ParseInt(av.String(), 10, 64) + } + + bv := reflect.ValueOf(b) + + switch bv.Kind() { + case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: + right = int64(bv.Len()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + right = bv.Int() + case reflect.String: + right, _ = strconv.ParseInt(bv.String(), 10, 64) + } + + return left > right +} + +// FIXME Eq is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. + +// Eq takes two types and checks whether they are equal. Supported types are int and string. Unsupported types will panic. +func Eq(a interface{}, b interface{}) bool { + av := reflect.ValueOf(a) + bv := reflect.ValueOf(b) + + switch av.Kind() { + case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: + panic("Eq called on unsupported type") + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return av.Int() == bv.Int() + case reflect.String: + return av.String() == bv.String() + } + return false +} + +func trimRightSpace(s string) string { + return strings.TrimRightFunc(s, unicode.IsSpace) +} + +// FIXME appendIfNotPresent is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra. + +// appendIfNotPresent will append stringToAppend to the end of s, but only if it's not yet present in s. +func appendIfNotPresent(s, stringToAppend string) string { + if strings.Contains(s, stringToAppend) { + return s + } + return s + " " + stringToAppend +} + +// rpad adds padding to the right of a string. +func rpad(s string, padding int) string { + template := fmt.Sprintf("%%-%ds", padding) + return fmt.Sprintf(template, s) +} + +// tmpl executes the given template text on data, writing the result to w. +func tmpl(w io.Writer, text string, data interface{}) error { + t := template.New("top") + t.Funcs(templateFuncs) + template.Must(t.Parse(text)) + return t.Execute(w, data) +} + +// ld compares two strings and returns the levenshtein distance between them. +func ld(s, t string, ignoreCase bool) int { + if ignoreCase { + s = strings.ToLower(s) + t = strings.ToLower(t) + } + d := make([][]int, len(s)+1) + for i := range d { + d[i] = make([]int, len(t)+1) + } + for i := range d { + d[i][0] = i + } + for j := range d[0] { + d[0][j] = j + } + for j := 1; j <= len(t); j++ { + for i := 1; i <= len(s); i++ { + if s[i-1] == t[j-1] { + d[i][j] = d[i-1][j-1] + } else { + min := d[i-1][j] + if d[i][j-1] < min { + min = d[i][j-1] + } + if d[i-1][j-1] < min { + min = d[i-1][j-1] + } + d[i][j] = min + 1 + } + } + + } + return d[len(s)][len(t)] +} + +func stringInSlice(a string, list []string) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +} diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go new file mode 100644 index 0000000000..80d1d3b778 --- /dev/null +++ b/vendor/github.com/spf13/cobra/command.go @@ -0,0 +1,1517 @@ +// Copyright © 2013 Steve Francia . +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package cobra is a commander providing a simple interface to create powerful modern CLI interfaces. +// In addition to providing an interface, Cobra simultaneously provides a controller to organize your application code. +package cobra + +import ( + "bytes" + "fmt" + "io" + "os" + "path/filepath" + "sort" + "strings" + + flag "github.com/spf13/pflag" +) + +// FParseErrWhitelist configures Flag parse errors to be ignored +type FParseErrWhitelist flag.ParseErrorsWhitelist + +// Command is just that, a command for your application. +// E.g. 'go run ...' - 'run' is the command. Cobra requires +// you to define the usage and description as part of your command +// definition to ensure usability. +type Command struct { + // Use is the one-line usage message. + Use string + + // Aliases is an array of aliases that can be used instead of the first word in Use. + Aliases []string + + // SuggestFor is an array of command names for which this command will be suggested - + // similar to aliases but only suggests. + SuggestFor []string + + // Short is the short description shown in the 'help' output. + Short string + + // Long is the long message shown in the 'help ' output. + Long string + + // Example is examples of how to use the command. + Example string + + // ValidArgs is list of all valid non-flag arguments that are accepted in bash completions + ValidArgs []string + + // Expected arguments + Args PositionalArgs + + // ArgAliases is List of aliases for ValidArgs. + // These are not suggested to the user in the bash completion, + // but accepted if entered manually. + ArgAliases []string + + // BashCompletionFunction is custom functions used by the bash autocompletion generator. + BashCompletionFunction string + + // Deprecated defines, if this command is deprecated and should print this string when used. + Deprecated string + + // Hidden defines, if this command is hidden and should NOT show up in the list of available commands. + Hidden bool + + // Annotations are key/value pairs that can be used by applications to identify or + // group commands. + Annotations map[string]string + + // Version defines the version for this command. If this value is non-empty and the command does not + // define a "version" flag, a "version" boolean flag will be added to the command and, if specified, + // will print content of the "Version" variable. + Version string + + // The *Run functions are executed in the following order: + // * PersistentPreRun() + // * PreRun() + // * Run() + // * PostRun() + // * PersistentPostRun() + // All functions get the same args, the arguments after the command name. + // + // PersistentPreRun: children of this command will inherit and execute. + PersistentPreRun func(cmd *Command, args []string) + // PersistentPreRunE: PersistentPreRun but returns an error. + PersistentPreRunE func(cmd *Command, args []string) error + // PreRun: children of this command will not inherit. + PreRun func(cmd *Command, args []string) + // PreRunE: PreRun but returns an error. + PreRunE func(cmd *Command, args []string) error + // Run: Typically the actual work function. Most commands will only implement this. + Run func(cmd *Command, args []string) + // RunE: Run but returns an error. + RunE func(cmd *Command, args []string) error + // PostRun: run after the Run command. + PostRun func(cmd *Command, args []string) + // PostRunE: PostRun but returns an error. + PostRunE func(cmd *Command, args []string) error + // PersistentPostRun: children of this command will inherit and execute after PostRun. + PersistentPostRun func(cmd *Command, args []string) + // PersistentPostRunE: PersistentPostRun but returns an error. + PersistentPostRunE func(cmd *Command, args []string) error + + // SilenceErrors is an option to quiet errors down stream. + SilenceErrors bool + + // SilenceUsage is an option to silence usage when an error occurs. + SilenceUsage bool + + // DisableFlagParsing disables the flag parsing. + // If this is true all flags will be passed to the command as arguments. + DisableFlagParsing bool + + // DisableAutoGenTag defines, if gen tag ("Auto generated by spf13/cobra...") + // will be printed by generating docs for this command. + DisableAutoGenTag bool + + // DisableFlagsInUseLine will disable the addition of [flags] to the usage + // line of a command when printing help or generating docs + DisableFlagsInUseLine bool + + // DisableSuggestions disables the suggestions based on Levenshtein distance + // that go along with 'unknown command' messages. + DisableSuggestions bool + // SuggestionsMinimumDistance defines minimum levenshtein distance to display suggestions. + // Must be > 0. + SuggestionsMinimumDistance int + + // TraverseChildren parses flags on all parents before executing child command. + TraverseChildren bool + + //FParseErrWhitelist flag parse errors to be ignored + FParseErrWhitelist FParseErrWhitelist + + // commands is the list of commands supported by this program. + commands []*Command + // parent is a parent command for this command. + parent *Command + // Max lengths of commands' string lengths for use in padding. + commandsMaxUseLen int + commandsMaxCommandPathLen int + commandsMaxNameLen int + // commandsAreSorted defines, if command slice are sorted or not. + commandsAreSorted bool + // commandCalledAs is the name or alias value used to call this command. + commandCalledAs struct { + name string + called bool + } + + // args is actual args parsed from flags. + args []string + // flagErrorBuf contains all error messages from pflag. + flagErrorBuf *bytes.Buffer + // flags is full set of flags. + flags *flag.FlagSet + // pflags contains persistent flags. + pflags *flag.FlagSet + // lflags contains local flags. + lflags *flag.FlagSet + // iflags contains inherited flags. + iflags *flag.FlagSet + // parentsPflags is all persistent flags of cmd's parents. + parentsPflags *flag.FlagSet + // globNormFunc is the global normalization function + // that we can use on every pflag set and children commands + globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName + + // output is an output writer defined by user. + output io.Writer + // usageFunc is usage func defined by user. + usageFunc func(*Command) error + // usageTemplate is usage template defined by user. + usageTemplate string + // flagErrorFunc is func defined by user and it's called when the parsing of + // flags returns an error. + flagErrorFunc func(*Command, error) error + // helpTemplate is help template defined by user. + helpTemplate string + // helpFunc is help func defined by user. + helpFunc func(*Command, []string) + // helpCommand is command with usage 'help'. If it's not defined by user, + // cobra uses default help command. + helpCommand *Command + // versionTemplate is the version template defined by user. + versionTemplate string +} + +// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden +// particularly useful when testing. +func (c *Command) SetArgs(a []string) { + c.args = a +} + +// SetOutput sets the destination for usage and error messages. +// If output is nil, os.Stderr is used. +func (c *Command) SetOutput(output io.Writer) { + c.output = output +} + +// SetUsageFunc sets usage function. Usage can be defined by application. +func (c *Command) SetUsageFunc(f func(*Command) error) { + c.usageFunc = f +} + +// SetUsageTemplate sets usage template. Can be defined by Application. +func (c *Command) SetUsageTemplate(s string) { + c.usageTemplate = s +} + +// SetFlagErrorFunc sets a function to generate an error when flag parsing +// fails. +func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) { + c.flagErrorFunc = f +} + +// SetHelpFunc sets help function. Can be defined by Application. +func (c *Command) SetHelpFunc(f func(*Command, []string)) { + c.helpFunc = f +} + +// SetHelpCommand sets help command. +func (c *Command) SetHelpCommand(cmd *Command) { + c.helpCommand = cmd +} + +// SetHelpTemplate sets help template to be used. Application can use it to set custom template. +func (c *Command) SetHelpTemplate(s string) { + c.helpTemplate = s +} + +// SetVersionTemplate sets version template to be used. Application can use it to set custom template. +func (c *Command) SetVersionTemplate(s string) { + c.versionTemplate = s +} + +// SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands. +// The user should not have a cyclic dependency on commands. +func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) { + c.Flags().SetNormalizeFunc(n) + c.PersistentFlags().SetNormalizeFunc(n) + c.globNormFunc = n + + for _, command := range c.commands { + command.SetGlobalNormalizationFunc(n) + } +} + +// OutOrStdout returns output to stdout. +func (c *Command) OutOrStdout() io.Writer { + return c.getOut(os.Stdout) +} + +// OutOrStderr returns output to stderr +func (c *Command) OutOrStderr() io.Writer { + return c.getOut(os.Stderr) +} + +func (c *Command) getOut(def io.Writer) io.Writer { + if c.output != nil { + return c.output + } + if c.HasParent() { + return c.parent.getOut(def) + } + return def +} + +// UsageFunc returns either the function set by SetUsageFunc for this command +// or a parent, or it returns a default usage function. +func (c *Command) UsageFunc() (f func(*Command) error) { + if c.usageFunc != nil { + return c.usageFunc + } + if c.HasParent() { + return c.Parent().UsageFunc() + } + return func(c *Command) error { + c.mergePersistentFlags() + err := tmpl(c.OutOrStderr(), c.UsageTemplate(), c) + if err != nil { + c.Println(err) + } + return err + } +} + +// Usage puts out the usage for the command. +// Used when a user provides invalid input. +// Can be defined by user by overriding UsageFunc. +func (c *Command) Usage() error { + return c.UsageFunc()(c) +} + +// HelpFunc returns either the function set by SetHelpFunc for this command +// or a parent, or it returns a function with default help behavior. +func (c *Command) HelpFunc() func(*Command, []string) { + if c.helpFunc != nil { + return c.helpFunc + } + if c.HasParent() { + return c.Parent().HelpFunc() + } + return func(c *Command, a []string) { + c.mergePersistentFlags() + err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c) + if err != nil { + c.Println(err) + } + } +} + +// Help puts out the help for the command. +// Used when a user calls help [command]. +// Can be defined by user by overriding HelpFunc. +func (c *Command) Help() error { + c.HelpFunc()(c, []string{}) + return nil +} + +// UsageString return usage string. +func (c *Command) UsageString() string { + tmpOutput := c.output + bb := new(bytes.Buffer) + c.SetOutput(bb) + c.Usage() + c.output = tmpOutput + return bb.String() +} + +// FlagErrorFunc returns either the function set by SetFlagErrorFunc for this +// command or a parent, or it returns a function which returns the original +// error. +func (c *Command) FlagErrorFunc() (f func(*Command, error) error) { + if c.flagErrorFunc != nil { + return c.flagErrorFunc + } + + if c.HasParent() { + return c.parent.FlagErrorFunc() + } + return func(c *Command, err error) error { + return err + } +} + +var minUsagePadding = 25 + +// UsagePadding return padding for the usage. +func (c *Command) UsagePadding() int { + if c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen { + return minUsagePadding + } + return c.parent.commandsMaxUseLen +} + +var minCommandPathPadding = 11 + +// CommandPathPadding return padding for the command path. +func (c *Command) CommandPathPadding() int { + if c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen { + return minCommandPathPadding + } + return c.parent.commandsMaxCommandPathLen +} + +var minNamePadding = 11 + +// NamePadding returns padding for the name. +func (c *Command) NamePadding() int { + if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen { + return minNamePadding + } + return c.parent.commandsMaxNameLen +} + +// UsageTemplate returns usage template for the command. +func (c *Command) UsageTemplate() string { + if c.usageTemplate != "" { + return c.usageTemplate + } + + if c.HasParent() { + return c.parent.UsageTemplate() + } + return `Usage:{{if .Runnable}} + {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}} + {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}} + +Aliases: + {{.NameAndAliases}}{{end}}{{if .HasExample}} + +Examples: +{{.Example}}{{end}}{{if .HasAvailableSubCommands}} + +Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}} + +Flags: +{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}} + +Global Flags: +{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}} + +Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}} + {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}} + +Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}} +` +} + +// HelpTemplate return help template for the command. +func (c *Command) HelpTemplate() string { + if c.helpTemplate != "" { + return c.helpTemplate + } + + if c.HasParent() { + return c.parent.HelpTemplate() + } + return `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}} + +{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}` +} + +// VersionTemplate return version template for the command. +func (c *Command) VersionTemplate() string { + if c.versionTemplate != "" { + return c.versionTemplate + } + + if c.HasParent() { + return c.parent.VersionTemplate() + } + return `{{with .Name}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}} +` +} + +func hasNoOptDefVal(name string, fs *flag.FlagSet) bool { + flag := fs.Lookup(name) + if flag == nil { + return false + } + return flag.NoOptDefVal != "" +} + +func shortHasNoOptDefVal(name string, fs *flag.FlagSet) bool { + if len(name) == 0 { + return false + } + + flag := fs.ShorthandLookup(name[:1]) + if flag == nil { + return false + } + return flag.NoOptDefVal != "" +} + +func stripFlags(args []string, c *Command) []string { + if len(args) == 0 { + return args + } + c.mergePersistentFlags() + + commands := []string{} + flags := c.Flags() + +Loop: + for len(args) > 0 { + s := args[0] + args = args[1:] + switch { + case s == "--": + // "--" terminates the flags + break Loop + case strings.HasPrefix(s, "--") && !strings.Contains(s, "=") && !hasNoOptDefVal(s[2:], flags): + // If '--flag arg' then + // delete arg from args. + fallthrough // (do the same as below) + case strings.HasPrefix(s, "-") && !strings.Contains(s, "=") && len(s) == 2 && !shortHasNoOptDefVal(s[1:], flags): + // If '-f arg' then + // delete 'arg' from args or break the loop if len(args) <= 1. + if len(args) <= 1 { + break Loop + } else { + args = args[1:] + continue + } + case s != "" && !strings.HasPrefix(s, "-"): + commands = append(commands, s) + } + } + + return commands +} + +// argsMinusFirstX removes only the first x from args. Otherwise, commands that look like +// openshift admin policy add-role-to-user admin my-user, lose the admin argument (arg[4]). +func argsMinusFirstX(args []string, x string) []string { + for i, y := range args { + if x == y { + ret := []string{} + ret = append(ret, args[:i]...) + ret = append(ret, args[i+1:]...) + return ret + } + } + return args +} + +func isFlagArg(arg string) bool { + return ((len(arg) >= 3 && arg[1] == '-') || + (len(arg) >= 2 && arg[0] == '-' && arg[1] != '-')) +} + +// Find the target command given the args and command tree +// Meant to be run on the highest node. Only searches down. +func (c *Command) Find(args []string) (*Command, []string, error) { + var innerfind func(*Command, []string) (*Command, []string) + + innerfind = func(c *Command, innerArgs []string) (*Command, []string) { + argsWOflags := stripFlags(innerArgs, c) + if len(argsWOflags) == 0 { + return c, innerArgs + } + nextSubCmd := argsWOflags[0] + + cmd := c.findNext(nextSubCmd) + if cmd != nil { + return innerfind(cmd, argsMinusFirstX(innerArgs, nextSubCmd)) + } + return c, innerArgs + } + + commandFound, a := innerfind(c, args) + if commandFound.Args == nil { + return commandFound, a, legacyArgs(commandFound, stripFlags(a, commandFound)) + } + return commandFound, a, nil +} + +func (c *Command) findSuggestions(arg string) string { + if c.DisableSuggestions { + return "" + } + if c.SuggestionsMinimumDistance <= 0 { + c.SuggestionsMinimumDistance = 2 + } + suggestionsString := "" + if suggestions := c.SuggestionsFor(arg); len(suggestions) > 0 { + suggestionsString += "\n\nDid you mean this?\n" + for _, s := range suggestions { + suggestionsString += fmt.Sprintf("\t%v\n", s) + } + } + return suggestionsString +} + +func (c *Command) findNext(next string) *Command { + matches := make([]*Command, 0) + for _, cmd := range c.commands { + if cmd.Name() == next || cmd.HasAlias(next) { + cmd.commandCalledAs.name = next + return cmd + } + if EnablePrefixMatching && cmd.hasNameOrAliasPrefix(next) { + matches = append(matches, cmd) + } + } + + if len(matches) == 1 { + return matches[0] + } + + return nil +} + +// Traverse the command tree to find the command, and parse args for +// each parent. +func (c *Command) Traverse(args []string) (*Command, []string, error) { + flags := []string{} + inFlag := false + + for i, arg := range args { + switch { + // A long flag with a space separated value + case strings.HasPrefix(arg, "--") && !strings.Contains(arg, "="): + // TODO: this isn't quite right, we should really check ahead for 'true' or 'false' + inFlag = !hasNoOptDefVal(arg[2:], c.Flags()) + flags = append(flags, arg) + continue + // A short flag with a space separated value + case strings.HasPrefix(arg, "-") && !strings.Contains(arg, "=") && len(arg) == 2 && !shortHasNoOptDefVal(arg[1:], c.Flags()): + inFlag = true + flags = append(flags, arg) + continue + // The value for a flag + case inFlag: + inFlag = false + flags = append(flags, arg) + continue + // A flag without a value, or with an `=` separated value + case isFlagArg(arg): + flags = append(flags, arg) + continue + } + + cmd := c.findNext(arg) + if cmd == nil { + return c, args, nil + } + + if err := c.ParseFlags(flags); err != nil { + return nil, args, err + } + return cmd.Traverse(args[i+1:]) + } + return c, args, nil +} + +// SuggestionsFor provides suggestions for the typedName. +func (c *Command) SuggestionsFor(typedName string) []string { + suggestions := []string{} + for _, cmd := range c.commands { + if cmd.IsAvailableCommand() { + levenshteinDistance := ld(typedName, cmd.Name(), true) + suggestByLevenshtein := levenshteinDistance <= c.SuggestionsMinimumDistance + suggestByPrefix := strings.HasPrefix(strings.ToLower(cmd.Name()), strings.ToLower(typedName)) + if suggestByLevenshtein || suggestByPrefix { + suggestions = append(suggestions, cmd.Name()) + } + for _, explicitSuggestion := range cmd.SuggestFor { + if strings.EqualFold(typedName, explicitSuggestion) { + suggestions = append(suggestions, cmd.Name()) + } + } + } + } + return suggestions +} + +// VisitParents visits all parents of the command and invokes fn on each parent. +func (c *Command) VisitParents(fn func(*Command)) { + if c.HasParent() { + fn(c.Parent()) + c.Parent().VisitParents(fn) + } +} + +// Root finds root command. +func (c *Command) Root() *Command { + if c.HasParent() { + return c.Parent().Root() + } + return c +} + +// ArgsLenAtDash will return the length of c.Flags().Args at the moment +// when a -- was found during args parsing. +func (c *Command) ArgsLenAtDash() int { + return c.Flags().ArgsLenAtDash() +} + +func (c *Command) execute(a []string) (err error) { + if c == nil { + return fmt.Errorf("Called Execute() on a nil Command") + } + + if len(c.Deprecated) > 0 { + c.Printf("Command %q is deprecated, %s\n", c.Name(), c.Deprecated) + } + + // initialize help and version flag at the last point possible to allow for user + // overriding + c.InitDefaultHelpFlag() + c.InitDefaultVersionFlag() + + err = c.ParseFlags(a) + if err != nil { + return c.FlagErrorFunc()(c, err) + } + + // If help is called, regardless of other flags, return we want help. + // Also say we need help if the command isn't runnable. + helpVal, err := c.Flags().GetBool("help") + if err != nil { + // should be impossible to get here as we always declare a help + // flag in InitDefaultHelpFlag() + c.Println("\"help\" flag declared as non-bool. Please correct your code") + return err + } + + if helpVal { + return flag.ErrHelp + } + + // for back-compat, only add version flag behavior if version is defined + if c.Version != "" { + versionVal, err := c.Flags().GetBool("version") + if err != nil { + c.Println("\"version\" flag declared as non-bool. Please correct your code") + return err + } + if versionVal { + err := tmpl(c.OutOrStdout(), c.VersionTemplate(), c) + if err != nil { + c.Println(err) + } + return err + } + } + + if !c.Runnable() { + return flag.ErrHelp + } + + c.preRun() + + argWoFlags := c.Flags().Args() + if c.DisableFlagParsing { + argWoFlags = a + } + + if err := c.ValidateArgs(argWoFlags); err != nil { + return err + } + + for p := c; p != nil; p = p.Parent() { + if p.PersistentPreRunE != nil { + if err := p.PersistentPreRunE(c, argWoFlags); err != nil { + return err + } + break + } else if p.PersistentPreRun != nil { + p.PersistentPreRun(c, argWoFlags) + break + } + } + if c.PreRunE != nil { + if err := c.PreRunE(c, argWoFlags); err != nil { + return err + } + } else if c.PreRun != nil { + c.PreRun(c, argWoFlags) + } + + if err := c.validateRequiredFlags(); err != nil { + return err + } + if c.RunE != nil { + if err := c.RunE(c, argWoFlags); err != nil { + return err + } + } else { + c.Run(c, argWoFlags) + } + if c.PostRunE != nil { + if err := c.PostRunE(c, argWoFlags); err != nil { + return err + } + } else if c.PostRun != nil { + c.PostRun(c, argWoFlags) + } + for p := c; p != nil; p = p.Parent() { + if p.PersistentPostRunE != nil { + if err := p.PersistentPostRunE(c, argWoFlags); err != nil { + return err + } + break + } else if p.PersistentPostRun != nil { + p.PersistentPostRun(c, argWoFlags) + break + } + } + + return nil +} + +func (c *Command) preRun() { + for _, x := range initializers { + x(c) + } +} + +// Execute uses the args (os.Args[1:] by default) +// and run through the command tree finding appropriate matches +// for commands and then corresponding flags. +func (c *Command) Execute() error { + _, err := c.ExecuteC() + return err +} + +// ExecuteC executes the command. +func (c *Command) ExecuteC() (cmd *Command, err error) { + // Regardless of what command execute is called on, run on Root only + if c.HasParent() { + return c.Root().ExecuteC() + } + + // windows hook + if preExecHookFn != nil { + preExecHookFn(c) + } + + // initialize help as the last point possible to allow for user + // overriding + c.InitDefaultHelpCmd() + + var args []string + + // Workaround FAIL with "go test -v" or "cobra.test -test.v", see #155 + if c.args == nil && filepath.Base(os.Args[0]) != "cobra.test" { + args = os.Args[1:] + } else { + args = c.args + } + + var flags []string + if c.TraverseChildren { + cmd, flags, err = c.Traverse(args) + } else { + cmd, flags, err = c.Find(args) + } + if err != nil { + // If found parse to a subcommand and then failed, talk about the subcommand + if cmd != nil { + c = cmd + } + if !c.SilenceErrors { + c.Println("Error:", err.Error()) + c.Printf("Run '%v --help' for usage.\n", c.CommandPath()) + } + return c, err + } + + cmd.commandCalledAs.called = true + if cmd.commandCalledAs.name == "" { + cmd.commandCalledAs.name = cmd.Name() + } + + err = cmd.execute(flags) + if err != nil { + // Always show help if requested, even if SilenceErrors is in + // effect + if err == flag.ErrHelp { + cmd.HelpFunc()(cmd, args) + return cmd, nil + } + + // If root command has SilentErrors flagged, + // all subcommands should respect it + if !cmd.SilenceErrors && !c.SilenceErrors { + c.Println("Error:", err.Error()) + } + + // If root command has SilentUsage flagged, + // all subcommands should respect it + if !cmd.SilenceUsage && !c.SilenceUsage { + c.Println(cmd.UsageString()) + } + } + return cmd, err +} + +func (c *Command) ValidateArgs(args []string) error { + if c.Args == nil { + return nil + } + return c.Args(c, args) +} + +func (c *Command) validateRequiredFlags() error { + flags := c.Flags() + missingFlagNames := []string{} + flags.VisitAll(func(pflag *flag.Flag) { + requiredAnnotation, found := pflag.Annotations[BashCompOneRequiredFlag] + if !found { + return + } + if (requiredAnnotation[0] == "true") && !pflag.Changed { + missingFlagNames = append(missingFlagNames, pflag.Name) + } + }) + + if len(missingFlagNames) > 0 { + return fmt.Errorf(`required flag(s) "%s" not set`, strings.Join(missingFlagNames, `", "`)) + } + return nil +} + +// InitDefaultHelpFlag adds default help flag to c. +// It is called automatically by executing the c or by calling help and usage. +// If c already has help flag, it will do nothing. +func (c *Command) InitDefaultHelpFlag() { + c.mergePersistentFlags() + if c.Flags().Lookup("help") == nil { + usage := "help for " + if c.Name() == "" { + usage += "this command" + } else { + usage += c.Name() + } + c.Flags().BoolP("help", "h", false, usage) + } +} + +// InitDefaultVersionFlag adds default version flag to c. +// It is called automatically by executing the c. +// If c already has a version flag, it will do nothing. +// If c.Version is empty, it will do nothing. +func (c *Command) InitDefaultVersionFlag() { + if c.Version == "" { + return + } + + c.mergePersistentFlags() + if c.Flags().Lookup("version") == nil { + usage := "version for " + if c.Name() == "" { + usage += "this command" + } else { + usage += c.Name() + } + c.Flags().Bool("version", false, usage) + } +} + +// InitDefaultHelpCmd adds default help command to c. +// It is called automatically by executing the c or by calling help and usage. +// If c already has help command or c has no subcommands, it will do nothing. +func (c *Command) InitDefaultHelpCmd() { + if !c.HasSubCommands() { + return + } + + if c.helpCommand == nil { + c.helpCommand = &Command{ + Use: "help [command]", + Short: "Help about any command", + Long: `Help provides help for any command in the application. +Simply type ` + c.Name() + ` help [path to command] for full details.`, + + Run: func(c *Command, args []string) { + cmd, _, e := c.Root().Find(args) + if cmd == nil || e != nil { + c.Printf("Unknown help topic %#q\n", args) + c.Root().Usage() + } else { + cmd.InitDefaultHelpFlag() // make possible 'help' flag to be shown + cmd.Help() + } + }, + } + } + c.RemoveCommand(c.helpCommand) + c.AddCommand(c.helpCommand) +} + +// ResetCommands delete parent, subcommand and help command from c. +func (c *Command) ResetCommands() { + c.parent = nil + c.commands = nil + c.helpCommand = nil + c.parentsPflags = nil +} + +// Sorts commands by their names. +type commandSorterByName []*Command + +func (c commandSorterByName) Len() int { return len(c) } +func (c commandSorterByName) Swap(i, j int) { c[i], c[j] = c[j], c[i] } +func (c commandSorterByName) Less(i, j int) bool { return c[i].Name() < c[j].Name() } + +// Commands returns a sorted slice of child commands. +func (c *Command) Commands() []*Command { + // do not sort commands if it already sorted or sorting was disabled + if EnableCommandSorting && !c.commandsAreSorted { + sort.Sort(commandSorterByName(c.commands)) + c.commandsAreSorted = true + } + return c.commands +} + +// AddCommand adds one or more commands to this parent command. +func (c *Command) AddCommand(cmds ...*Command) { + for i, x := range cmds { + if cmds[i] == c { + panic("Command can't be a child of itself") + } + cmds[i].parent = c + // update max lengths + usageLen := len(x.Use) + if usageLen > c.commandsMaxUseLen { + c.commandsMaxUseLen = usageLen + } + commandPathLen := len(x.CommandPath()) + if commandPathLen > c.commandsMaxCommandPathLen { + c.commandsMaxCommandPathLen = commandPathLen + } + nameLen := len(x.Name()) + if nameLen > c.commandsMaxNameLen { + c.commandsMaxNameLen = nameLen + } + // If global normalization function exists, update all children + if c.globNormFunc != nil { + x.SetGlobalNormalizationFunc(c.globNormFunc) + } + c.commands = append(c.commands, x) + c.commandsAreSorted = false + } +} + +// RemoveCommand removes one or more commands from a parent command. +func (c *Command) RemoveCommand(cmds ...*Command) { + commands := []*Command{} +main: + for _, command := range c.commands { + for _, cmd := range cmds { + if command == cmd { + command.parent = nil + continue main + } + } + commands = append(commands, command) + } + c.commands = commands + // recompute all lengths + c.commandsMaxUseLen = 0 + c.commandsMaxCommandPathLen = 0 + c.commandsMaxNameLen = 0 + for _, command := range c.commands { + usageLen := len(command.Use) + if usageLen > c.commandsMaxUseLen { + c.commandsMaxUseLen = usageLen + } + commandPathLen := len(command.CommandPath()) + if commandPathLen > c.commandsMaxCommandPathLen { + c.commandsMaxCommandPathLen = commandPathLen + } + nameLen := len(command.Name()) + if nameLen > c.commandsMaxNameLen { + c.commandsMaxNameLen = nameLen + } + } +} + +// Print is a convenience method to Print to the defined output, fallback to Stderr if not set. +func (c *Command) Print(i ...interface{}) { + fmt.Fprint(c.OutOrStderr(), i...) +} + +// Println is a convenience method to Println to the defined output, fallback to Stderr if not set. +func (c *Command) Println(i ...interface{}) { + c.Print(fmt.Sprintln(i...)) +} + +// Printf is a convenience method to Printf to the defined output, fallback to Stderr if not set. +func (c *Command) Printf(format string, i ...interface{}) { + c.Print(fmt.Sprintf(format, i...)) +} + +// CommandPath returns the full path to this command. +func (c *Command) CommandPath() string { + if c.HasParent() { + return c.Parent().CommandPath() + " " + c.Name() + } + return c.Name() +} + +// UseLine puts out the full usage for a given command (including parents). +func (c *Command) UseLine() string { + var useline string + if c.HasParent() { + useline = c.parent.CommandPath() + " " + c.Use + } else { + useline = c.Use + } + if c.DisableFlagsInUseLine { + return useline + } + if c.HasAvailableFlags() && !strings.Contains(useline, "[flags]") { + useline += " [flags]" + } + return useline +} + +// DebugFlags used to determine which flags have been assigned to which commands +// and which persist. +func (c *Command) DebugFlags() { + c.Println("DebugFlags called on", c.Name()) + var debugflags func(*Command) + + debugflags = func(x *Command) { + if x.HasFlags() || x.HasPersistentFlags() { + c.Println(x.Name()) + } + if x.HasFlags() { + x.flags.VisitAll(func(f *flag.Flag) { + if x.HasPersistentFlags() && x.persistentFlag(f.Name) != nil { + c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [LP]") + } else { + c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [L]") + } + }) + } + if x.HasPersistentFlags() { + x.pflags.VisitAll(func(f *flag.Flag) { + if x.HasFlags() { + if x.flags.Lookup(f.Name) == nil { + c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [P]") + } + } else { + c.Println(" -"+f.Shorthand+",", "--"+f.Name, "["+f.DefValue+"]", "", f.Value, " [P]") + } + }) + } + c.Println(x.flagErrorBuf) + if x.HasSubCommands() { + for _, y := range x.commands { + debugflags(y) + } + } + } + + debugflags(c) +} + +// Name returns the command's name: the first word in the use line. +func (c *Command) Name() string { + name := c.Use + i := strings.Index(name, " ") + if i >= 0 { + name = name[:i] + } + return name +} + +// HasAlias determines if a given string is an alias of the command. +func (c *Command) HasAlias(s string) bool { + for _, a := range c.Aliases { + if a == s { + return true + } + } + return false +} + +// CalledAs returns the command name or alias that was used to invoke +// this command or an empty string if the command has not been called. +func (c *Command) CalledAs() string { + if c.commandCalledAs.called { + return c.commandCalledAs.name + } + return "" +} + +// hasNameOrAliasPrefix returns true if the Name or any of aliases start +// with prefix +func (c *Command) hasNameOrAliasPrefix(prefix string) bool { + if strings.HasPrefix(c.Name(), prefix) { + c.commandCalledAs.name = c.Name() + return true + } + for _, alias := range c.Aliases { + if strings.HasPrefix(alias, prefix) { + c.commandCalledAs.name = alias + return true + } + } + return false +} + +// NameAndAliases returns a list of the command name and all aliases +func (c *Command) NameAndAliases() string { + return strings.Join(append([]string{c.Name()}, c.Aliases...), ", ") +} + +// HasExample determines if the command has example. +func (c *Command) HasExample() bool { + return len(c.Example) > 0 +} + +// Runnable determines if the command is itself runnable. +func (c *Command) Runnable() bool { + return c.Run != nil || c.RunE != nil +} + +// HasSubCommands determines if the command has children commands. +func (c *Command) HasSubCommands() bool { + return len(c.commands) > 0 +} + +// IsAvailableCommand determines if a command is available as a non-help command +// (this includes all non deprecated/hidden commands). +func (c *Command) IsAvailableCommand() bool { + if len(c.Deprecated) != 0 || c.Hidden { + return false + } + + if c.HasParent() && c.Parent().helpCommand == c { + return false + } + + if c.Runnable() || c.HasAvailableSubCommands() { + return true + } + + return false +} + +// IsAdditionalHelpTopicCommand determines if a command is an additional +// help topic command; additional help topic command is determined by the +// fact that it is NOT runnable/hidden/deprecated, and has no sub commands that +// are runnable/hidden/deprecated. +// Concrete example: https://github.com/spf13/cobra/issues/393#issuecomment-282741924. +func (c *Command) IsAdditionalHelpTopicCommand() bool { + // if a command is runnable, deprecated, or hidden it is not a 'help' command + if c.Runnable() || len(c.Deprecated) != 0 || c.Hidden { + return false + } + + // if any non-help sub commands are found, the command is not a 'help' command + for _, sub := range c.commands { + if !sub.IsAdditionalHelpTopicCommand() { + return false + } + } + + // the command either has no sub commands, or no non-help sub commands + return true +} + +// HasHelpSubCommands determines if a command has any available 'help' sub commands +// that need to be shown in the usage/help default template under 'additional help +// topics'. +func (c *Command) HasHelpSubCommands() bool { + // return true on the first found available 'help' sub command + for _, sub := range c.commands { + if sub.IsAdditionalHelpTopicCommand() { + return true + } + } + + // the command either has no sub commands, or no available 'help' sub commands + return false +} + +// HasAvailableSubCommands determines if a command has available sub commands that +// need to be shown in the usage/help default template under 'available commands'. +func (c *Command) HasAvailableSubCommands() bool { + // return true on the first found available (non deprecated/help/hidden) + // sub command + for _, sub := range c.commands { + if sub.IsAvailableCommand() { + return true + } + } + + // the command either has no sub commands, or no available (non deprecated/help/hidden) + // sub commands + return false +} + +// HasParent determines if the command is a child command. +func (c *Command) HasParent() bool { + return c.parent != nil +} + +// GlobalNormalizationFunc returns the global normalization function or nil if it doesn't exist. +func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) flag.NormalizedName { + return c.globNormFunc +} + +// Flags returns the complete FlagSet that applies +// to this command (local and persistent declared here and by all parents). +func (c *Command) Flags() *flag.FlagSet { + if c.flags == nil { + c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + c.flags.SetOutput(c.flagErrorBuf) + } + + return c.flags +} + +// LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands. +func (c *Command) LocalNonPersistentFlags() *flag.FlagSet { + persistentFlags := c.PersistentFlags() + + out := flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.LocalFlags().VisitAll(func(f *flag.Flag) { + if persistentFlags.Lookup(f.Name) == nil { + out.AddFlag(f) + } + }) + return out +} + +// LocalFlags returns the local FlagSet specifically set in the current command. +func (c *Command) LocalFlags() *flag.FlagSet { + c.mergePersistentFlags() + + if c.lflags == nil { + c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + c.lflags.SetOutput(c.flagErrorBuf) + } + c.lflags.SortFlags = c.Flags().SortFlags + if c.globNormFunc != nil { + c.lflags.SetNormalizeFunc(c.globNormFunc) + } + + addToLocal := func(f *flag.Flag) { + if c.lflags.Lookup(f.Name) == nil && c.parentsPflags.Lookup(f.Name) == nil { + c.lflags.AddFlag(f) + } + } + c.Flags().VisitAll(addToLocal) + c.PersistentFlags().VisitAll(addToLocal) + return c.lflags +} + +// InheritedFlags returns all flags which were inherited from parents commands. +func (c *Command) InheritedFlags() *flag.FlagSet { + c.mergePersistentFlags() + + if c.iflags == nil { + c.iflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + c.iflags.SetOutput(c.flagErrorBuf) + } + + local := c.LocalFlags() + if c.globNormFunc != nil { + c.iflags.SetNormalizeFunc(c.globNormFunc) + } + + c.parentsPflags.VisitAll(func(f *flag.Flag) { + if c.iflags.Lookup(f.Name) == nil && local.Lookup(f.Name) == nil { + c.iflags.AddFlag(f) + } + }) + return c.iflags +} + +// NonInheritedFlags returns all flags which were not inherited from parent commands. +func (c *Command) NonInheritedFlags() *flag.FlagSet { + return c.LocalFlags() +} + +// PersistentFlags returns the persistent FlagSet specifically set in the current command. +func (c *Command) PersistentFlags() *flag.FlagSet { + if c.pflags == nil { + c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + c.pflags.SetOutput(c.flagErrorBuf) + } + return c.pflags +} + +// ResetFlags deletes all flags from command. +func (c *Command) ResetFlags() { + c.flagErrorBuf = new(bytes.Buffer) + c.flagErrorBuf.Reset() + c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.flags.SetOutput(c.flagErrorBuf) + c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.pflags.SetOutput(c.flagErrorBuf) + + c.lflags = nil + c.iflags = nil + c.parentsPflags = nil +} + +// HasFlags checks if the command contains any flags (local plus persistent from the entire structure). +func (c *Command) HasFlags() bool { + return c.Flags().HasFlags() +} + +// HasPersistentFlags checks if the command contains persistent flags. +func (c *Command) HasPersistentFlags() bool { + return c.PersistentFlags().HasFlags() +} + +// HasLocalFlags checks if the command has flags specifically declared locally. +func (c *Command) HasLocalFlags() bool { + return c.LocalFlags().HasFlags() +} + +// HasInheritedFlags checks if the command has flags inherited from its parent command. +func (c *Command) HasInheritedFlags() bool { + return c.InheritedFlags().HasFlags() +} + +// HasAvailableFlags checks if the command contains any flags (local plus persistent from the entire +// structure) which are not hidden or deprecated. +func (c *Command) HasAvailableFlags() bool { + return c.Flags().HasAvailableFlags() +} + +// HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated. +func (c *Command) HasAvailablePersistentFlags() bool { + return c.PersistentFlags().HasAvailableFlags() +} + +// HasAvailableLocalFlags checks if the command has flags specifically declared locally which are not hidden +// or deprecated. +func (c *Command) HasAvailableLocalFlags() bool { + return c.LocalFlags().HasAvailableFlags() +} + +// HasAvailableInheritedFlags checks if the command has flags inherited from its parent command which are +// not hidden or deprecated. +func (c *Command) HasAvailableInheritedFlags() bool { + return c.InheritedFlags().HasAvailableFlags() +} + +// Flag climbs up the command tree looking for matching flag. +func (c *Command) Flag(name string) (flag *flag.Flag) { + flag = c.Flags().Lookup(name) + + if flag == nil { + flag = c.persistentFlag(name) + } + + return +} + +// Recursively find matching persistent flag. +func (c *Command) persistentFlag(name string) (flag *flag.Flag) { + if c.HasPersistentFlags() { + flag = c.PersistentFlags().Lookup(name) + } + + if flag == nil { + c.updateParentsPflags() + flag = c.parentsPflags.Lookup(name) + } + return +} + +// ParseFlags parses persistent flag tree and local flags. +func (c *Command) ParseFlags(args []string) error { + if c.DisableFlagParsing { + return nil + } + + if c.flagErrorBuf == nil { + c.flagErrorBuf = new(bytes.Buffer) + } + beforeErrorBufLen := c.flagErrorBuf.Len() + c.mergePersistentFlags() + + //do it here after merging all flags and just before parse + c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist) + + err := c.Flags().Parse(args) + // Print warnings if they occurred (e.g. deprecated flag messages). + if c.flagErrorBuf.Len()-beforeErrorBufLen > 0 && err == nil { + c.Print(c.flagErrorBuf.String()) + } + + return err +} + +// Parent returns a commands parent command. +func (c *Command) Parent() *Command { + return c.parent +} + +// mergePersistentFlags merges c.PersistentFlags() to c.Flags() +// and adds missing persistent flags of all parents. +func (c *Command) mergePersistentFlags() { + c.updateParentsPflags() + c.Flags().AddFlagSet(c.PersistentFlags()) + c.Flags().AddFlagSet(c.parentsPflags) +} + +// updateParentsPflags updates c.parentsPflags by adding +// new persistent flags of all parents. +// If c.parentsPflags == nil, it makes new. +func (c *Command) updateParentsPflags() { + if c.parentsPflags == nil { + c.parentsPflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.parentsPflags.SetOutput(c.flagErrorBuf) + c.parentsPflags.SortFlags = false + } + + if c.globNormFunc != nil { + c.parentsPflags.SetNormalizeFunc(c.globNormFunc) + } + + c.Root().PersistentFlags().AddFlagSet(flag.CommandLine) + + c.VisitParents(func(parent *Command) { + c.parentsPflags.AddFlagSet(parent.PersistentFlags()) + }) +} diff --git a/vendor/github.com/spf13/cobra/command_notwin.go b/vendor/github.com/spf13/cobra/command_notwin.go new file mode 100644 index 0000000000..6159c1cc19 --- /dev/null +++ b/vendor/github.com/spf13/cobra/command_notwin.go @@ -0,0 +1,5 @@ +// +build !windows + +package cobra + +var preExecHookFn func(*Command) diff --git a/vendor/github.com/spf13/cobra/command_win.go b/vendor/github.com/spf13/cobra/command_win.go new file mode 100644 index 0000000000..edec728e4f --- /dev/null +++ b/vendor/github.com/spf13/cobra/command_win.go @@ -0,0 +1,20 @@ +// +build windows + +package cobra + +import ( + "os" + "time" + + "github.com/inconshreveable/mousetrap" +) + +var preExecHookFn = preExecHook + +func preExecHook(c *Command) { + if MousetrapHelpText != "" && mousetrap.StartedByExplorer() { + c.Print(MousetrapHelpText) + time.Sleep(5 * time.Second) + os.Exit(1) + } +} diff --git a/vendor/github.com/spf13/cobra/zsh_completions.go b/vendor/github.com/spf13/cobra/zsh_completions.go new file mode 100644 index 0000000000..889c22e273 --- /dev/null +++ b/vendor/github.com/spf13/cobra/zsh_completions.go @@ -0,0 +1,126 @@ +package cobra + +import ( + "bytes" + "fmt" + "io" + "os" + "strings" +) + +// GenZshCompletionFile generates zsh completion file. +func (c *Command) GenZshCompletionFile(filename string) error { + outFile, err := os.Create(filename) + if err != nil { + return err + } + defer outFile.Close() + + return c.GenZshCompletion(outFile) +} + +// GenZshCompletion generates a zsh completion file and writes to the passed writer. +func (c *Command) GenZshCompletion(w io.Writer) error { + buf := new(bytes.Buffer) + + writeHeader(buf, c) + maxDepth := maxDepth(c) + writeLevelMapping(buf, maxDepth) + writeLevelCases(buf, maxDepth, c) + + _, err := buf.WriteTo(w) + return err +} + +func writeHeader(w io.Writer, cmd *Command) { + fmt.Fprintf(w, "#compdef %s\n\n", cmd.Name()) +} + +func maxDepth(c *Command) int { + if len(c.Commands()) == 0 { + return 0 + } + maxDepthSub := 0 + for _, s := range c.Commands() { + subDepth := maxDepth(s) + if subDepth > maxDepthSub { + maxDepthSub = subDepth + } + } + return 1 + maxDepthSub +} + +func writeLevelMapping(w io.Writer, numLevels int) { + fmt.Fprintln(w, `_arguments \`) + for i := 1; i <= numLevels; i++ { + fmt.Fprintf(w, ` '%d: :->level%d' \`, i, i) + fmt.Fprintln(w) + } + fmt.Fprintf(w, ` '%d: :%s'`, numLevels+1, "_files") + fmt.Fprintln(w) +} + +func writeLevelCases(w io.Writer, maxDepth int, root *Command) { + fmt.Fprintln(w, "case $state in") + defer fmt.Fprintln(w, "esac") + + for i := 1; i <= maxDepth; i++ { + fmt.Fprintf(w, " level%d)\n", i) + writeLevel(w, root, i) + fmt.Fprintln(w, " ;;") + } + fmt.Fprintln(w, " *)") + fmt.Fprintln(w, " _arguments '*: :_files'") + fmt.Fprintln(w, " ;;") +} + +func writeLevel(w io.Writer, root *Command, i int) { + fmt.Fprintf(w, " case $words[%d] in\n", i) + defer fmt.Fprintln(w, " esac") + + commands := filterByLevel(root, i) + byParent := groupByParent(commands) + + for p, c := range byParent { + names := names(c) + fmt.Fprintf(w, " %s)\n", p) + fmt.Fprintf(w, " _arguments '%d: :(%s)'\n", i, strings.Join(names, " ")) + fmt.Fprintln(w, " ;;") + } + fmt.Fprintln(w, " *)") + fmt.Fprintln(w, " _arguments '*: :_files'") + fmt.Fprintln(w, " ;;") + +} + +func filterByLevel(c *Command, l int) []*Command { + cs := make([]*Command, 0) + if l == 0 { + cs = append(cs, c) + return cs + } + for _, s := range c.Commands() { + cs = append(cs, filterByLevel(s, l-1)...) + } + return cs +} + +func groupByParent(commands []*Command) map[string][]*Command { + m := make(map[string][]*Command) + for _, c := range commands { + parent := c.Parent() + if parent == nil { + continue + } + m[parent.Name()] = append(m[parent.Name()], c) + } + return m +} + +func names(commands []*Command) []string { + ns := make([]string, len(commands)) + for i, c := range commands { + ns[i] = c.Name() + } + return ns +} diff --git a/vendor/github.com/spf13/pflag/LICENSE b/vendor/github.com/spf13/pflag/LICENSE new file mode 100644 index 0000000000..63ed1cfea1 --- /dev/null +++ b/vendor/github.com/spf13/pflag/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2012 Alex Ogier. All rights reserved. +Copyright (c) 2012 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. diff --git a/vendor/github.com/spf13/pflag/README.md b/vendor/github.com/spf13/pflag/README.md new file mode 100644 index 0000000000..b052414d12 --- /dev/null +++ b/vendor/github.com/spf13/pflag/README.md @@ -0,0 +1,296 @@ +[![Build Status](https://travis-ci.org/spf13/pflag.svg?branch=master)](https://travis-ci.org/spf13/pflag) +[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/pflag)](https://goreportcard.com/report/github.com/spf13/pflag) +[![GoDoc](https://godoc.org/github.com/spf13/pflag?status.svg)](https://godoc.org/github.com/spf13/pflag) + +## Description + +pflag is a drop-in replacement for Go's flag package, implementing +POSIX/GNU-style --flags. + +pflag is compatible with the [GNU extensions to the POSIX recommendations +for command-line options][1]. For a more precise description, see the +"Command-line flag syntax" section below. + +[1]: http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html + +pflag is available under the same style of BSD license as the Go language, +which can be found in the LICENSE file. + +## Installation + +pflag is available using the standard `go get` command. + +Install by running: + + go get github.com/spf13/pflag + +Run tests by running: + + go test github.com/spf13/pflag + +## Usage + +pflag is a drop-in replacement of Go's native flag package. If you import +pflag under the name "flag" then all code should continue to function +with no changes. + +``` go +import flag "github.com/spf13/pflag" +``` + +There is one exception to this: if you directly instantiate the Flag struct +there is one more field "Shorthand" that you will need to set. +Most code never instantiates this struct directly, and instead uses +functions such as String(), BoolVar(), and Var(), and is therefore +unaffected. + +Define flags using flag.String(), Bool(), Int(), etc. + +This declares an integer flag, -flagname, stored in the pointer ip, with type *int. + +``` go +var ip *int = flag.Int("flagname", 1234, "help message for flagname") +``` + +If you like, you can bind the flag to a variable using the Var() functions. + +``` go +var flagvar int +func init() { + flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname") +} +``` + +Or you can create custom flags that satisfy the Value interface (with +pointer receivers) and couple them to flag parsing by + +``` go +flag.Var(&flagVal, "name", "help message for flagname") +``` + +For such flags, the default value is just the initial value of the variable. + +After all flags are defined, call + +``` go +flag.Parse() +``` + +to parse the command line into the defined flags. + +Flags may then be used directly. If you're using the flags themselves, +they are all pointers; if you bind to variables, they're values. + +``` go +fmt.Println("ip has value ", *ip) +fmt.Println("flagvar has value ", flagvar) +``` + +There are helpers function to get values later if you have the FlagSet but +it was difficult to keep up with all of the flag pointers in your code. +If you have a pflag.FlagSet with a flag called 'flagname' of type int you +can use GetInt() to get the int value. But notice that 'flagname' must exist +and it must be an int. GetString("flagname") will fail. + +``` go +i, err := flagset.GetInt("flagname") +``` + +After parsing, the arguments after the flag are available as the +slice flag.Args() or individually as flag.Arg(i). +The arguments are indexed from 0 through flag.NArg()-1. + +The pflag package also defines some new functions that are not in flag, +that give one-letter shorthands for flags. You can use these by appending +'P' to the name of any function that defines a flag. + +``` go +var ip = flag.IntP("flagname", "f", 1234, "help message") +var flagvar bool +func init() { + flag.BoolVarP(&flagvar, "boolname", "b", true, "help message") +} +flag.VarP(&flagVal, "varname", "v", "help message") +``` + +Shorthand letters can be used with single dashes on the command line. +Boolean shorthand flags can be combined with other shorthand flags. + +The default set of command-line flags is controlled by +top-level functions. The FlagSet type allows one to define +independent sets of flags, such as to implement subcommands +in a command-line interface. The methods of FlagSet are +analogous to the top-level functions for the command-line +flag set. + +## Setting no option default values for flags + +After you create a flag it is possible to set the pflag.NoOptDefVal for +the given flag. Doing this changes the meaning of the flag slightly. If +a flag has a NoOptDefVal and the flag is set on the command line without +an option the flag will be set to the NoOptDefVal. For example given: + +``` go +var ip = flag.IntP("flagname", "f", 1234, "help message") +flag.Lookup("flagname").NoOptDefVal = "4321" +``` + +Would result in something like + +| Parsed Arguments | Resulting Value | +| ------------- | ------------- | +| --flagname=1357 | ip=1357 | +| --flagname | ip=4321 | +| [nothing] | ip=1234 | + +## Command line flag syntax + +``` +--flag // boolean flags, or flags with no option default values +--flag x // only on flags without a default value +--flag=x +``` + +Unlike the flag package, a single dash before an option means something +different than a double dash. Single dashes signify a series of shorthand +letters for flags. All but the last shorthand letter must be boolean flags +or a flag with a default value + +``` +// boolean or flags where the 'no option default value' is set +-f +-f=true +-abc +but +-b true is INVALID + +// non-boolean and flags without a 'no option default value' +-n 1234 +-n=1234 +-n1234 + +// mixed +-abcs "hello" +-absd="hello" +-abcs1234 +``` + +Flag parsing stops after the terminator "--". Unlike the flag package, +flags can be interspersed with arguments anywhere on the command line +before this terminator. + +Integer flags accept 1234, 0664, 0x1234 and may be negative. +Boolean flags (in their long form) accept 1, 0, t, f, true, false, +TRUE, FALSE, True, False. +Duration flags accept any input valid for time.ParseDuration. + +## Mutating or "Normalizing" Flag names + +It is possible to set a custom flag name 'normalization function.' It allows flag names to be mutated both when created in the code and when used on the command line to some 'normalized' form. The 'normalized' form is used for comparison. Two examples of using the custom normalization func follow. + +**Example #1**: You want -, _, and . in flags to compare the same. aka --my-flag == --my_flag == --my.flag + +``` go +func wordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName { + from := []string{"-", "_"} + to := "." + for _, sep := range from { + name = strings.Replace(name, sep, to, -1) + } + return pflag.NormalizedName(name) +} + +myFlagSet.SetNormalizeFunc(wordSepNormalizeFunc) +``` + +**Example #2**: You want to alias two flags. aka --old-flag-name == --new-flag-name + +``` go +func aliasNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName { + switch name { + case "old-flag-name": + name = "new-flag-name" + break + } + return pflag.NormalizedName(name) +} + +myFlagSet.SetNormalizeFunc(aliasNormalizeFunc) +``` + +## Deprecating a flag or its shorthand +It is possible to deprecate a flag, or just its shorthand. Deprecating a flag/shorthand hides it from help text and prints a usage message when the deprecated flag/shorthand is used. + +**Example #1**: You want to deprecate a flag named "badflag" as well as inform the users what flag they should use instead. +```go +// deprecate a flag by specifying its name and a usage message +flags.MarkDeprecated("badflag", "please use --good-flag instead") +``` +This hides "badflag" from help text, and prints `Flag --badflag has been deprecated, please use --good-flag instead` when "badflag" is used. + +**Example #2**: You want to keep a flag name "noshorthandflag" but deprecate its shortname "n". +```go +// deprecate a flag shorthand by specifying its flag name and a usage message +flags.MarkShorthandDeprecated("noshorthandflag", "please use --noshorthandflag only") +``` +This hides the shortname "n" from help text, and prints `Flag shorthand -n has been deprecated, please use --noshorthandflag only` when the shorthand "n" is used. + +Note that usage message is essential here, and it should not be empty. + +## Hidden flags +It is possible to mark a flag as hidden, meaning it will still function as normal, however will not show up in usage/help text. + +**Example**: You have a flag named "secretFlag" that you need for internal use only and don't want it showing up in help text, or for its usage text to be available. +```go +// hide a flag by specifying its name +flags.MarkHidden("secretFlag") +``` + +## Disable sorting of flags +`pflag` allows you to disable sorting of flags for help and usage message. + +**Example**: +```go +flags.BoolP("verbose", "v", false, "verbose output") +flags.String("coolflag", "yeaah", "it's really cool flag") +flags.Int("usefulflag", 777, "sometimes it's very useful") +flags.SortFlags = false +flags.PrintDefaults() +``` +**Output**: +``` + -v, --verbose verbose output + --coolflag string it's really cool flag (default "yeaah") + --usefulflag int sometimes it's very useful (default 777) +``` + + +## Supporting Go flags when using pflag +In order to support flags defined using Go's `flag` package, they must be added to the `pflag` flagset. This is usually necessary +to support flags defined by third-party dependencies (e.g. `golang/glog`). + +**Example**: You want to add the Go flags to the `CommandLine` flagset +```go +import ( + goflag "flag" + flag "github.com/spf13/pflag" +) + +var ip *int = flag.Int("flagname", 1234, "help message for flagname") + +func main() { + flag.CommandLine.AddGoFlagSet(goflag.CommandLine) + flag.Parse() +} +``` + +## More info + +You can see the full reference documentation of the pflag package +[at godoc.org][3], or through go's standard documentation system by +running `godoc -http=:6060` and browsing to +[http://localhost:6060/pkg/github.com/spf13/pflag][2] after +installation. + +[2]: http://localhost:6060/pkg/github.com/spf13/pflag +[3]: http://godoc.org/github.com/spf13/pflag diff --git a/vendor/github.com/spf13/pflag/bool.go b/vendor/github.com/spf13/pflag/bool.go new file mode 100644 index 0000000000..c4c5c0bfda --- /dev/null +++ b/vendor/github.com/spf13/pflag/bool.go @@ -0,0 +1,94 @@ +package pflag + +import "strconv" + +// optional interface to indicate boolean flags that can be +// supplied without "=value" text +type boolFlag interface { + Value + IsBoolFlag() bool +} + +// -- bool Value +type boolValue bool + +func newBoolValue(val bool, p *bool) *boolValue { + *p = val + return (*boolValue)(p) +} + +func (b *boolValue) Set(s string) error { + v, err := strconv.ParseBool(s) + *b = boolValue(v) + return err +} + +func (b *boolValue) Type() string { + return "bool" +} + +func (b *boolValue) String() string { return strconv.FormatBool(bool(*b)) } + +func (b *boolValue) IsBoolFlag() bool { return true } + +func boolConv(sval string) (interface{}, error) { + return strconv.ParseBool(sval) +} + +// GetBool return the bool value of a flag with the given name +func (f *FlagSet) GetBool(name string) (bool, error) { + val, err := f.getFlagType(name, "bool", boolConv) + if err != nil { + return false, err + } + return val.(bool), nil +} + +// BoolVar defines a bool flag with specified name, default value, and usage string. +// The argument p points to a bool variable in which to store the value of the flag. +func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) { + f.BoolVarP(p, name, "", value, usage) +} + +// BoolVarP is like BoolVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BoolVarP(p *bool, name, shorthand string, value bool, usage string) { + flag := f.VarPF(newBoolValue(value, p), name, shorthand, usage) + flag.NoOptDefVal = "true" +} + +// BoolVar defines a bool flag with specified name, default value, and usage string. +// The argument p points to a bool variable in which to store the value of the flag. +func BoolVar(p *bool, name string, value bool, usage string) { + BoolVarP(p, name, "", value, usage) +} + +// BoolVarP is like BoolVar, but accepts a shorthand letter that can be used after a single dash. +func BoolVarP(p *bool, name, shorthand string, value bool, usage string) { + flag := CommandLine.VarPF(newBoolValue(value, p), name, shorthand, usage) + flag.NoOptDefVal = "true" +} + +// Bool defines a bool flag with specified name, default value, and usage string. +// The return value is the address of a bool variable that stores the value of the flag. +func (f *FlagSet) Bool(name string, value bool, usage string) *bool { + return f.BoolP(name, "", value, usage) +} + +// BoolP is like Bool, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BoolP(name, shorthand string, value bool, usage string) *bool { + p := new(bool) + f.BoolVarP(p, name, shorthand, value, usage) + return p +} + +// Bool defines a bool flag with specified name, default value, and usage string. +// The return value is the address of a bool variable that stores the value of the flag. +func Bool(name string, value bool, usage string) *bool { + return BoolP(name, "", value, usage) +} + +// BoolP is like Bool, but accepts a shorthand letter that can be used after a single dash. +func BoolP(name, shorthand string, value bool, usage string) *bool { + b := CommandLine.BoolP(name, shorthand, value, usage) + return b +} diff --git a/vendor/github.com/spf13/pflag/bool_slice.go b/vendor/github.com/spf13/pflag/bool_slice.go new file mode 100644 index 0000000000..5af02f1a75 --- /dev/null +++ b/vendor/github.com/spf13/pflag/bool_slice.go @@ -0,0 +1,147 @@ +package pflag + +import ( + "io" + "strconv" + "strings" +) + +// -- boolSlice Value +type boolSliceValue struct { + value *[]bool + changed bool +} + +func newBoolSliceValue(val []bool, p *[]bool) *boolSliceValue { + bsv := new(boolSliceValue) + bsv.value = p + *bsv.value = val + return bsv +} + +// Set converts, and assigns, the comma-separated boolean argument string representation as the []bool value of this flag. +// If Set is called on a flag that already has a []bool assigned, the newly converted values will be appended. +func (s *boolSliceValue) Set(val string) error { + + // remove all quote characters + rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") + + // read flag arguments with CSV parser + boolStrSlice, err := readAsCSV(rmQuote.Replace(val)) + if err != nil && err != io.EOF { + return err + } + + // parse boolean values into slice + out := make([]bool, 0, len(boolStrSlice)) + for _, boolStr := range boolStrSlice { + b, err := strconv.ParseBool(strings.TrimSpace(boolStr)) + if err != nil { + return err + } + out = append(out, b) + } + + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + + s.changed = true + + return nil +} + +// Type returns a string that uniquely represents this flag's type. +func (s *boolSliceValue) Type() string { + return "boolSlice" +} + +// String defines a "native" format for this boolean slice flag value. +func (s *boolSliceValue) String() string { + + boolStrSlice := make([]string, len(*s.value)) + for i, b := range *s.value { + boolStrSlice[i] = strconv.FormatBool(b) + } + + out, _ := writeAsCSV(boolStrSlice) + + return "[" + out + "]" +} + +func boolSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []bool{}, nil + } + ss := strings.Split(val, ",") + out := make([]bool, len(ss)) + for i, t := range ss { + var err error + out[i], err = strconv.ParseBool(t) + if err != nil { + return nil, err + } + } + return out, nil +} + +// GetBoolSlice returns the []bool value of a flag with the given name. +func (f *FlagSet) GetBoolSlice(name string) ([]bool, error) { + val, err := f.getFlagType(name, "boolSlice", boolSliceConv) + if err != nil { + return []bool{}, err + } + return val.([]bool), nil +} + +// BoolSliceVar defines a boolSlice flag with specified name, default value, and usage string. +// The argument p points to a []bool variable in which to store the value of the flag. +func (f *FlagSet) BoolSliceVar(p *[]bool, name string, value []bool, usage string) { + f.VarP(newBoolSliceValue(value, p), name, "", usage) +} + +// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) { + f.VarP(newBoolSliceValue(value, p), name, shorthand, usage) +} + +// BoolSliceVar defines a []bool flag with specified name, default value, and usage string. +// The argument p points to a []bool variable in which to store the value of the flag. +func BoolSliceVar(p *[]bool, name string, value []bool, usage string) { + CommandLine.VarP(newBoolSliceValue(value, p), name, "", usage) +} + +// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash. +func BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) { + CommandLine.VarP(newBoolSliceValue(value, p), name, shorthand, usage) +} + +// BoolSlice defines a []bool flag with specified name, default value, and usage string. +// The return value is the address of a []bool variable that stores the value of the flag. +func (f *FlagSet) BoolSlice(name string, value []bool, usage string) *[]bool { + p := []bool{} + f.BoolSliceVarP(&p, name, "", value, usage) + return &p +} + +// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool { + p := []bool{} + f.BoolSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// BoolSlice defines a []bool flag with specified name, default value, and usage string. +// The return value is the address of a []bool variable that stores the value of the flag. +func BoolSlice(name string, value []bool, usage string) *[]bool { + return CommandLine.BoolSliceP(name, "", value, usage) +} + +// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash. +func BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool { + return CommandLine.BoolSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/bytes.go b/vendor/github.com/spf13/pflag/bytes.go new file mode 100644 index 0000000000..67d5304570 --- /dev/null +++ b/vendor/github.com/spf13/pflag/bytes.go @@ -0,0 +1,209 @@ +package pflag + +import ( + "encoding/base64" + "encoding/hex" + "fmt" + "strings" +) + +// BytesHex adapts []byte for use as a flag. Value of flag is HEX encoded +type bytesHexValue []byte + +// String implements pflag.Value.String. +func (bytesHex bytesHexValue) String() string { + return fmt.Sprintf("%X", []byte(bytesHex)) +} + +// Set implements pflag.Value.Set. +func (bytesHex *bytesHexValue) Set(value string) error { + bin, err := hex.DecodeString(strings.TrimSpace(value)) + + if err != nil { + return err + } + + *bytesHex = bin + + return nil +} + +// Type implements pflag.Value.Type. +func (*bytesHexValue) Type() string { + return "bytesHex" +} + +func newBytesHexValue(val []byte, p *[]byte) *bytesHexValue { + *p = val + return (*bytesHexValue)(p) +} + +func bytesHexConv(sval string) (interface{}, error) { + + bin, err := hex.DecodeString(sval) + + if err == nil { + return bin, nil + } + + return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err) +} + +// GetBytesHex return the []byte value of a flag with the given name +func (f *FlagSet) GetBytesHex(name string) ([]byte, error) { + val, err := f.getFlagType(name, "bytesHex", bytesHexConv) + + if err != nil { + return []byte{}, err + } + + return val.([]byte), nil +} + +// BytesHexVar defines an []byte flag with specified name, default value, and usage string. +// The argument p points to an []byte variable in which to store the value of the flag. +func (f *FlagSet) BytesHexVar(p *[]byte, name string, value []byte, usage string) { + f.VarP(newBytesHexValue(value, p), name, "", usage) +} + +// BytesHexVarP is like BytesHexVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BytesHexVarP(p *[]byte, name, shorthand string, value []byte, usage string) { + f.VarP(newBytesHexValue(value, p), name, shorthand, usage) +} + +// BytesHexVar defines an []byte flag with specified name, default value, and usage string. +// The argument p points to an []byte variable in which to store the value of the flag. +func BytesHexVar(p *[]byte, name string, value []byte, usage string) { + CommandLine.VarP(newBytesHexValue(value, p), name, "", usage) +} + +// BytesHexVarP is like BytesHexVar, but accepts a shorthand letter that can be used after a single dash. +func BytesHexVarP(p *[]byte, name, shorthand string, value []byte, usage string) { + CommandLine.VarP(newBytesHexValue(value, p), name, shorthand, usage) +} + +// BytesHex defines an []byte flag with specified name, default value, and usage string. +// The return value is the address of an []byte variable that stores the value of the flag. +func (f *FlagSet) BytesHex(name string, value []byte, usage string) *[]byte { + p := new([]byte) + f.BytesHexVarP(p, name, "", value, usage) + return p +} + +// BytesHexP is like BytesHex, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BytesHexP(name, shorthand string, value []byte, usage string) *[]byte { + p := new([]byte) + f.BytesHexVarP(p, name, shorthand, value, usage) + return p +} + +// BytesHex defines an []byte flag with specified name, default value, and usage string. +// The return value is the address of an []byte variable that stores the value of the flag. +func BytesHex(name string, value []byte, usage string) *[]byte { + return CommandLine.BytesHexP(name, "", value, usage) +} + +// BytesHexP is like BytesHex, but accepts a shorthand letter that can be used after a single dash. +func BytesHexP(name, shorthand string, value []byte, usage string) *[]byte { + return CommandLine.BytesHexP(name, shorthand, value, usage) +} + +// BytesBase64 adapts []byte for use as a flag. Value of flag is Base64 encoded +type bytesBase64Value []byte + +// String implements pflag.Value.String. +func (bytesBase64 bytesBase64Value) String() string { + return base64.StdEncoding.EncodeToString([]byte(bytesBase64)) +} + +// Set implements pflag.Value.Set. +func (bytesBase64 *bytesBase64Value) Set(value string) error { + bin, err := base64.StdEncoding.DecodeString(strings.TrimSpace(value)) + + if err != nil { + return err + } + + *bytesBase64 = bin + + return nil +} + +// Type implements pflag.Value.Type. +func (*bytesBase64Value) Type() string { + return "bytesBase64" +} + +func newBytesBase64Value(val []byte, p *[]byte) *bytesBase64Value { + *p = val + return (*bytesBase64Value)(p) +} + +func bytesBase64ValueConv(sval string) (interface{}, error) { + + bin, err := base64.StdEncoding.DecodeString(sval) + if err == nil { + return bin, nil + } + + return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err) +} + +// GetBytesBase64 return the []byte value of a flag with the given name +func (f *FlagSet) GetBytesBase64(name string) ([]byte, error) { + val, err := f.getFlagType(name, "bytesBase64", bytesBase64ValueConv) + + if err != nil { + return []byte{}, err + } + + return val.([]byte), nil +} + +// BytesBase64Var defines an []byte flag with specified name, default value, and usage string. +// The argument p points to an []byte variable in which to store the value of the flag. +func (f *FlagSet) BytesBase64Var(p *[]byte, name string, value []byte, usage string) { + f.VarP(newBytesBase64Value(value, p), name, "", usage) +} + +// BytesBase64VarP is like BytesBase64Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BytesBase64VarP(p *[]byte, name, shorthand string, value []byte, usage string) { + f.VarP(newBytesBase64Value(value, p), name, shorthand, usage) +} + +// BytesBase64Var defines an []byte flag with specified name, default value, and usage string. +// The argument p points to an []byte variable in which to store the value of the flag. +func BytesBase64Var(p *[]byte, name string, value []byte, usage string) { + CommandLine.VarP(newBytesBase64Value(value, p), name, "", usage) +} + +// BytesBase64VarP is like BytesBase64Var, but accepts a shorthand letter that can be used after a single dash. +func BytesBase64VarP(p *[]byte, name, shorthand string, value []byte, usage string) { + CommandLine.VarP(newBytesBase64Value(value, p), name, shorthand, usage) +} + +// BytesBase64 defines an []byte flag with specified name, default value, and usage string. +// The return value is the address of an []byte variable that stores the value of the flag. +func (f *FlagSet) BytesBase64(name string, value []byte, usage string) *[]byte { + p := new([]byte) + f.BytesBase64VarP(p, name, "", value, usage) + return p +} + +// BytesBase64P is like BytesBase64, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BytesBase64P(name, shorthand string, value []byte, usage string) *[]byte { + p := new([]byte) + f.BytesBase64VarP(p, name, shorthand, value, usage) + return p +} + +// BytesBase64 defines an []byte flag with specified name, default value, and usage string. +// The return value is the address of an []byte variable that stores the value of the flag. +func BytesBase64(name string, value []byte, usage string) *[]byte { + return CommandLine.BytesBase64P(name, "", value, usage) +} + +// BytesBase64P is like BytesBase64, but accepts a shorthand letter that can be used after a single dash. +func BytesBase64P(name, shorthand string, value []byte, usage string) *[]byte { + return CommandLine.BytesBase64P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/count.go b/vendor/github.com/spf13/pflag/count.go new file mode 100644 index 0000000000..aa126e44d1 --- /dev/null +++ b/vendor/github.com/spf13/pflag/count.go @@ -0,0 +1,96 @@ +package pflag + +import "strconv" + +// -- count Value +type countValue int + +func newCountValue(val int, p *int) *countValue { + *p = val + return (*countValue)(p) +} + +func (i *countValue) Set(s string) error { + // "+1" means that no specific value was passed, so increment + if s == "+1" { + *i = countValue(*i + 1) + return nil + } + v, err := strconv.ParseInt(s, 0, 0) + *i = countValue(v) + return err +} + +func (i *countValue) Type() string { + return "count" +} + +func (i *countValue) String() string { return strconv.Itoa(int(*i)) } + +func countConv(sval string) (interface{}, error) { + i, err := strconv.Atoi(sval) + if err != nil { + return nil, err + } + return i, nil +} + +// GetCount return the int value of a flag with the given name +func (f *FlagSet) GetCount(name string) (int, error) { + val, err := f.getFlagType(name, "count", countConv) + if err != nil { + return 0, err + } + return val.(int), nil +} + +// CountVar defines a count flag with specified name, default value, and usage string. +// The argument p points to an int variable in which to store the value of the flag. +// A count flag will add 1 to its value evey time it is found on the command line +func (f *FlagSet) CountVar(p *int, name string, usage string) { + f.CountVarP(p, name, "", usage) +} + +// CountVarP is like CountVar only take a shorthand for the flag name. +func (f *FlagSet) CountVarP(p *int, name, shorthand string, usage string) { + flag := f.VarPF(newCountValue(0, p), name, shorthand, usage) + flag.NoOptDefVal = "+1" +} + +// CountVar like CountVar only the flag is placed on the CommandLine instead of a given flag set +func CountVar(p *int, name string, usage string) { + CommandLine.CountVar(p, name, usage) +} + +// CountVarP is like CountVar only take a shorthand for the flag name. +func CountVarP(p *int, name, shorthand string, usage string) { + CommandLine.CountVarP(p, name, shorthand, usage) +} + +// Count defines a count flag with specified name, default value, and usage string. +// The return value is the address of an int variable that stores the value of the flag. +// A count flag will add 1 to its value evey time it is found on the command line +func (f *FlagSet) Count(name string, usage string) *int { + p := new(int) + f.CountVarP(p, name, "", usage) + return p +} + +// CountP is like Count only takes a shorthand for the flag name. +func (f *FlagSet) CountP(name, shorthand string, usage string) *int { + p := new(int) + f.CountVarP(p, name, shorthand, usage) + return p +} + +// Count defines a count flag with specified name, default value, and usage string. +// The return value is the address of an int variable that stores the value of the flag. +// A count flag will add 1 to its value evey time it is found on the command line +func Count(name string, usage string) *int { + return CommandLine.CountP(name, "", usage) +} + +// CountP is like Count only takes a shorthand for the flag name. +func CountP(name, shorthand string, usage string) *int { + return CommandLine.CountP(name, shorthand, usage) +} diff --git a/vendor/github.com/spf13/pflag/duration.go b/vendor/github.com/spf13/pflag/duration.go new file mode 100644 index 0000000000..e9debef88e --- /dev/null +++ b/vendor/github.com/spf13/pflag/duration.go @@ -0,0 +1,86 @@ +package pflag + +import ( + "time" +) + +// -- time.Duration Value +type durationValue time.Duration + +func newDurationValue(val time.Duration, p *time.Duration) *durationValue { + *p = val + return (*durationValue)(p) +} + +func (d *durationValue) Set(s string) error { + v, err := time.ParseDuration(s) + *d = durationValue(v) + return err +} + +func (d *durationValue) Type() string { + return "duration" +} + +func (d *durationValue) String() string { return (*time.Duration)(d).String() } + +func durationConv(sval string) (interface{}, error) { + return time.ParseDuration(sval) +} + +// GetDuration return the duration value of a flag with the given name +func (f *FlagSet) GetDuration(name string) (time.Duration, error) { + val, err := f.getFlagType(name, "duration", durationConv) + if err != nil { + return 0, err + } + return val.(time.Duration), nil +} + +// DurationVar defines a time.Duration flag with specified name, default value, and usage string. +// The argument p points to a time.Duration variable in which to store the value of the flag. +func (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) { + f.VarP(newDurationValue(value, p), name, "", usage) +} + +// DurationVarP is like DurationVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) DurationVarP(p *time.Duration, name, shorthand string, value time.Duration, usage string) { + f.VarP(newDurationValue(value, p), name, shorthand, usage) +} + +// DurationVar defines a time.Duration flag with specified name, default value, and usage string. +// The argument p points to a time.Duration variable in which to store the value of the flag. +func DurationVar(p *time.Duration, name string, value time.Duration, usage string) { + CommandLine.VarP(newDurationValue(value, p), name, "", usage) +} + +// DurationVarP is like DurationVar, but accepts a shorthand letter that can be used after a single dash. +func DurationVarP(p *time.Duration, name, shorthand string, value time.Duration, usage string) { + CommandLine.VarP(newDurationValue(value, p), name, shorthand, usage) +} + +// Duration defines a time.Duration flag with specified name, default value, and usage string. +// The return value is the address of a time.Duration variable that stores the value of the flag. +func (f *FlagSet) Duration(name string, value time.Duration, usage string) *time.Duration { + p := new(time.Duration) + f.DurationVarP(p, name, "", value, usage) + return p +} + +// DurationP is like Duration, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) DurationP(name, shorthand string, value time.Duration, usage string) *time.Duration { + p := new(time.Duration) + f.DurationVarP(p, name, shorthand, value, usage) + return p +} + +// Duration defines a time.Duration flag with specified name, default value, and usage string. +// The return value is the address of a time.Duration variable that stores the value of the flag. +func Duration(name string, value time.Duration, usage string) *time.Duration { + return CommandLine.DurationP(name, "", value, usage) +} + +// DurationP is like Duration, but accepts a shorthand letter that can be used after a single dash. +func DurationP(name, shorthand string, value time.Duration, usage string) *time.Duration { + return CommandLine.DurationP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/duration_slice.go b/vendor/github.com/spf13/pflag/duration_slice.go new file mode 100644 index 0000000000..52c6b6dc10 --- /dev/null +++ b/vendor/github.com/spf13/pflag/duration_slice.go @@ -0,0 +1,128 @@ +package pflag + +import ( + "fmt" + "strings" + "time" +) + +// -- durationSlice Value +type durationSliceValue struct { + value *[]time.Duration + changed bool +} + +func newDurationSliceValue(val []time.Duration, p *[]time.Duration) *durationSliceValue { + dsv := new(durationSliceValue) + dsv.value = p + *dsv.value = val + return dsv +} + +func (s *durationSliceValue) Set(val string) error { + ss := strings.Split(val, ",") + out := make([]time.Duration, len(ss)) + for i, d := range ss { + var err error + out[i], err = time.ParseDuration(d) + if err != nil { + return err + } + + } + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + s.changed = true + return nil +} + +func (s *durationSliceValue) Type() string { + return "durationSlice" +} + +func (s *durationSliceValue) String() string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = fmt.Sprintf("%s", d) + } + return "[" + strings.Join(out, ",") + "]" +} + +func durationSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []time.Duration{}, nil + } + ss := strings.Split(val, ",") + out := make([]time.Duration, len(ss)) + for i, d := range ss { + var err error + out[i], err = time.ParseDuration(d) + if err != nil { + return nil, err + } + + } + return out, nil +} + +// GetDurationSlice returns the []time.Duration value of a flag with the given name +func (f *FlagSet) GetDurationSlice(name string) ([]time.Duration, error) { + val, err := f.getFlagType(name, "durationSlice", durationSliceConv) + if err != nil { + return []time.Duration{}, err + } + return val.([]time.Duration), nil +} + +// DurationSliceVar defines a durationSlice flag with specified name, default value, and usage string. +// The argument p points to a []time.Duration variable in which to store the value of the flag. +func (f *FlagSet) DurationSliceVar(p *[]time.Duration, name string, value []time.Duration, usage string) { + f.VarP(newDurationSliceValue(value, p), name, "", usage) +} + +// DurationSliceVarP is like DurationSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) DurationSliceVarP(p *[]time.Duration, name, shorthand string, value []time.Duration, usage string) { + f.VarP(newDurationSliceValue(value, p), name, shorthand, usage) +} + +// DurationSliceVar defines a duration[] flag with specified name, default value, and usage string. +// The argument p points to a duration[] variable in which to store the value of the flag. +func DurationSliceVar(p *[]time.Duration, name string, value []time.Duration, usage string) { + CommandLine.VarP(newDurationSliceValue(value, p), name, "", usage) +} + +// DurationSliceVarP is like DurationSliceVar, but accepts a shorthand letter that can be used after a single dash. +func DurationSliceVarP(p *[]time.Duration, name, shorthand string, value []time.Duration, usage string) { + CommandLine.VarP(newDurationSliceValue(value, p), name, shorthand, usage) +} + +// DurationSlice defines a []time.Duration flag with specified name, default value, and usage string. +// The return value is the address of a []time.Duration variable that stores the value of the flag. +func (f *FlagSet) DurationSlice(name string, value []time.Duration, usage string) *[]time.Duration { + p := []time.Duration{} + f.DurationSliceVarP(&p, name, "", value, usage) + return &p +} + +// DurationSliceP is like DurationSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) DurationSliceP(name, shorthand string, value []time.Duration, usage string) *[]time.Duration { + p := []time.Duration{} + f.DurationSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// DurationSlice defines a []time.Duration flag with specified name, default value, and usage string. +// The return value is the address of a []time.Duration variable that stores the value of the flag. +func DurationSlice(name string, value []time.Duration, usage string) *[]time.Duration { + return CommandLine.DurationSliceP(name, "", value, usage) +} + +// DurationSliceP is like DurationSlice, but accepts a shorthand letter that can be used after a single dash. +func DurationSliceP(name, shorthand string, value []time.Duration, usage string) *[]time.Duration { + return CommandLine.DurationSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/flag.go b/vendor/github.com/spf13/pflag/flag.go new file mode 100644 index 0000000000..5cc710ccdd --- /dev/null +++ b/vendor/github.com/spf13/pflag/flag.go @@ -0,0 +1,1224 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package pflag is a drop-in replacement for Go's flag package, implementing +POSIX/GNU-style --flags. + +pflag is compatible with the GNU extensions to the POSIX recommendations +for command-line options. See +http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html + +Usage: + +pflag is a drop-in replacement of Go's native flag package. If you import +pflag under the name "flag" then all code should continue to function +with no changes. + + import flag "github.com/spf13/pflag" + +There is one exception to this: if you directly instantiate the Flag struct +there is one more field "Shorthand" that you will need to set. +Most code never instantiates this struct directly, and instead uses +functions such as String(), BoolVar(), and Var(), and is therefore +unaffected. + +Define flags using flag.String(), Bool(), Int(), etc. + +This declares an integer flag, -flagname, stored in the pointer ip, with type *int. + var ip = flag.Int("flagname", 1234, "help message for flagname") +If you like, you can bind the flag to a variable using the Var() functions. + var flagvar int + func init() { + flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname") + } +Or you can create custom flags that satisfy the Value interface (with +pointer receivers) and couple them to flag parsing by + flag.Var(&flagVal, "name", "help message for flagname") +For such flags, the default value is just the initial value of the variable. + +After all flags are defined, call + flag.Parse() +to parse the command line into the defined flags. + +Flags may then be used directly. If you're using the flags themselves, +they are all pointers; if you bind to variables, they're values. + fmt.Println("ip has value ", *ip) + fmt.Println("flagvar has value ", flagvar) + +After parsing, the arguments after the flag are available as the +slice flag.Args() or individually as flag.Arg(i). +The arguments are indexed from 0 through flag.NArg()-1. + +The pflag package also defines some new functions that are not in flag, +that give one-letter shorthands for flags. You can use these by appending +'P' to the name of any function that defines a flag. + var ip = flag.IntP("flagname", "f", 1234, "help message") + var flagvar bool + func init() { + flag.BoolVarP("boolname", "b", true, "help message") + } + flag.VarP(&flagVar, "varname", "v", 1234, "help message") +Shorthand letters can be used with single dashes on the command line. +Boolean shorthand flags can be combined with other shorthand flags. + +Command line flag syntax: + --flag // boolean flags only + --flag=x + +Unlike the flag package, a single dash before an option means something +different than a double dash. Single dashes signify a series of shorthand +letters for flags. All but the last shorthand letter must be boolean flags. + // boolean flags + -f + -abc + // non-boolean flags + -n 1234 + -Ifile + // mixed + -abcs "hello" + -abcn1234 + +Flag parsing stops after the terminator "--". Unlike the flag package, +flags can be interspersed with arguments anywhere on the command line +before this terminator. + +Integer flags accept 1234, 0664, 0x1234 and may be negative. +Boolean flags (in their long form) accept 1, 0, t, f, true, false, +TRUE, FALSE, True, False. +Duration flags accept any input valid for time.ParseDuration. + +The default set of command-line flags is controlled by +top-level functions. The FlagSet type allows one to define +independent sets of flags, such as to implement subcommands +in a command-line interface. The methods of FlagSet are +analogous to the top-level functions for the command-line +flag set. +*/ +package pflag + +import ( + "bytes" + "errors" + goflag "flag" + "fmt" + "io" + "os" + "sort" + "strings" +) + +// ErrHelp is the error returned if the flag -help is invoked but no such flag is defined. +var ErrHelp = errors.New("pflag: help requested") + +// ErrorHandling defines how to handle flag parsing errors. +type ErrorHandling int + +const ( + // ContinueOnError will return an err from Parse() if an error is found + ContinueOnError ErrorHandling = iota + // ExitOnError will call os.Exit(2) if an error is found when parsing + ExitOnError + // PanicOnError will panic() if an error is found when parsing flags + PanicOnError +) + +// ParseErrorsWhitelist defines the parsing errors that can be ignored +type ParseErrorsWhitelist struct { + // UnknownFlags will ignore unknown flags errors and continue parsing rest of the flags + UnknownFlags bool +} + +// NormalizedName is a flag name that has been normalized according to rules +// for the FlagSet (e.g. making '-' and '_' equivalent). +type NormalizedName string + +// A FlagSet represents a set of defined flags. +type FlagSet struct { + // Usage is the function called when an error occurs while parsing flags. + // The field is a function (not a method) that may be changed to point to + // a custom error handler. + Usage func() + + // SortFlags is used to indicate, if user wants to have sorted flags in + // help/usage messages. + SortFlags bool + + // ParseErrorsWhitelist is used to configure a whitelist of errors + ParseErrorsWhitelist ParseErrorsWhitelist + + name string + parsed bool + actual map[NormalizedName]*Flag + orderedActual []*Flag + sortedActual []*Flag + formal map[NormalizedName]*Flag + orderedFormal []*Flag + sortedFormal []*Flag + shorthands map[byte]*Flag + args []string // arguments after flags + argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no -- + errorHandling ErrorHandling + output io.Writer // nil means stderr; use out() accessor + interspersed bool // allow interspersed option/non-option args + normalizeNameFunc func(f *FlagSet, name string) NormalizedName + + addedGoFlagSets []*goflag.FlagSet +} + +// A Flag represents the state of a flag. +type Flag struct { + Name string // name as it appears on command line + Shorthand string // one-letter abbreviated flag + Usage string // help message + Value Value // value as set + DefValue string // default value (as text); for usage message + Changed bool // If the user set the value (or if left to default) + NoOptDefVal string // default value (as text); if the flag is on the command line without any options + Deprecated string // If this flag is deprecated, this string is the new or now thing to use + Hidden bool // used by cobra.Command to allow flags to be hidden from help/usage text + ShorthandDeprecated string // If the shorthand of this flag is deprecated, this string is the new or now thing to use + Annotations map[string][]string // used by cobra.Command bash autocomple code +} + +// Value is the interface to the dynamic value stored in a flag. +// (The default value is represented as a string.) +type Value interface { + String() string + Set(string) error + Type() string +} + +// sortFlags returns the flags as a slice in lexicographical sorted order. +func sortFlags(flags map[NormalizedName]*Flag) []*Flag { + list := make(sort.StringSlice, len(flags)) + i := 0 + for k := range flags { + list[i] = string(k) + i++ + } + list.Sort() + result := make([]*Flag, len(list)) + for i, name := range list { + result[i] = flags[NormalizedName(name)] + } + return result +} + +// SetNormalizeFunc allows you to add a function which can translate flag names. +// Flags added to the FlagSet will be translated and then when anything tries to +// look up the flag that will also be translated. So it would be possible to create +// a flag named "getURL" and have it translated to "geturl". A user could then pass +// "--getUrl" which may also be translated to "geturl" and everything will work. +func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) { + f.normalizeNameFunc = n + f.sortedFormal = f.sortedFormal[:0] + for fname, flag := range f.formal { + nname := f.normalizeFlagName(flag.Name) + if fname == nname { + continue + } + flag.Name = string(nname) + delete(f.formal, fname) + f.formal[nname] = flag + if _, set := f.actual[fname]; set { + delete(f.actual, fname) + f.actual[nname] = flag + } + } +} + +// GetNormalizeFunc returns the previously set NormalizeFunc of a function which +// does no translation, if not set previously. +func (f *FlagSet) GetNormalizeFunc() func(f *FlagSet, name string) NormalizedName { + if f.normalizeNameFunc != nil { + return f.normalizeNameFunc + } + return func(f *FlagSet, name string) NormalizedName { return NormalizedName(name) } +} + +func (f *FlagSet) normalizeFlagName(name string) NormalizedName { + n := f.GetNormalizeFunc() + return n(f, name) +} + +func (f *FlagSet) out() io.Writer { + if f.output == nil { + return os.Stderr + } + return f.output +} + +// SetOutput sets the destination for usage and error messages. +// If output is nil, os.Stderr is used. +func (f *FlagSet) SetOutput(output io.Writer) { + f.output = output +} + +// VisitAll visits the flags in lexicographical order or +// in primordial order if f.SortFlags is false, calling fn for each. +// It visits all flags, even those not set. +func (f *FlagSet) VisitAll(fn func(*Flag)) { + if len(f.formal) == 0 { + return + } + + var flags []*Flag + if f.SortFlags { + if len(f.formal) != len(f.sortedFormal) { + f.sortedFormal = sortFlags(f.formal) + } + flags = f.sortedFormal + } else { + flags = f.orderedFormal + } + + for _, flag := range flags { + fn(flag) + } +} + +// HasFlags returns a bool to indicate if the FlagSet has any flags defined. +func (f *FlagSet) HasFlags() bool { + return len(f.formal) > 0 +} + +// HasAvailableFlags returns a bool to indicate if the FlagSet has any flags +// that are not hidden. +func (f *FlagSet) HasAvailableFlags() bool { + for _, flag := range f.formal { + if !flag.Hidden { + return true + } + } + return false +} + +// VisitAll visits the command-line flags in lexicographical order or +// in primordial order if f.SortFlags is false, calling fn for each. +// It visits all flags, even those not set. +func VisitAll(fn func(*Flag)) { + CommandLine.VisitAll(fn) +} + +// Visit visits the flags in lexicographical order or +// in primordial order if f.SortFlags is false, calling fn for each. +// It visits only those flags that have been set. +func (f *FlagSet) Visit(fn func(*Flag)) { + if len(f.actual) == 0 { + return + } + + var flags []*Flag + if f.SortFlags { + if len(f.actual) != len(f.sortedActual) { + f.sortedActual = sortFlags(f.actual) + } + flags = f.sortedActual + } else { + flags = f.orderedActual + } + + for _, flag := range flags { + fn(flag) + } +} + +// Visit visits the command-line flags in lexicographical order or +// in primordial order if f.SortFlags is false, calling fn for each. +// It visits only those flags that have been set. +func Visit(fn func(*Flag)) { + CommandLine.Visit(fn) +} + +// Lookup returns the Flag structure of the named flag, returning nil if none exists. +func (f *FlagSet) Lookup(name string) *Flag { + return f.lookup(f.normalizeFlagName(name)) +} + +// ShorthandLookup returns the Flag structure of the short handed flag, +// returning nil if none exists. +// It panics, if len(name) > 1. +func (f *FlagSet) ShorthandLookup(name string) *Flag { + if name == "" { + return nil + } + if len(name) > 1 { + msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name) + fmt.Fprintf(f.out(), msg) + panic(msg) + } + c := name[0] + return f.shorthands[c] +} + +// lookup returns the Flag structure of the named flag, returning nil if none exists. +func (f *FlagSet) lookup(name NormalizedName) *Flag { + return f.formal[name] +} + +// func to return a given type for a given flag name +func (f *FlagSet) getFlagType(name string, ftype string, convFunc func(sval string) (interface{}, error)) (interface{}, error) { + flag := f.Lookup(name) + if flag == nil { + err := fmt.Errorf("flag accessed but not defined: %s", name) + return nil, err + } + + if flag.Value.Type() != ftype { + err := fmt.Errorf("trying to get %s value of flag of type %s", ftype, flag.Value.Type()) + return nil, err + } + + sval := flag.Value.String() + result, err := convFunc(sval) + if err != nil { + return nil, err + } + return result, nil +} + +// ArgsLenAtDash will return the length of f.Args at the moment when a -- was +// found during arg parsing. This allows your program to know which args were +// before the -- and which came after. +func (f *FlagSet) ArgsLenAtDash() int { + return f.argsLenAtDash +} + +// MarkDeprecated indicated that a flag is deprecated in your program. It will +// continue to function but will not show up in help or usage messages. Using +// this flag will also print the given usageMessage. +func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error { + flag := f.Lookup(name) + if flag == nil { + return fmt.Errorf("flag %q does not exist", name) + } + if usageMessage == "" { + return fmt.Errorf("deprecated message for flag %q must be set", name) + } + flag.Deprecated = usageMessage + flag.Hidden = true + return nil +} + +// MarkShorthandDeprecated will mark the shorthand of a flag deprecated in your +// program. It will continue to function but will not show up in help or usage +// messages. Using this flag will also print the given usageMessage. +func (f *FlagSet) MarkShorthandDeprecated(name string, usageMessage string) error { + flag := f.Lookup(name) + if flag == nil { + return fmt.Errorf("flag %q does not exist", name) + } + if usageMessage == "" { + return fmt.Errorf("deprecated message for flag %q must be set", name) + } + flag.ShorthandDeprecated = usageMessage + return nil +} + +// MarkHidden sets a flag to 'hidden' in your program. It will continue to +// function but will not show up in help or usage messages. +func (f *FlagSet) MarkHidden(name string) error { + flag := f.Lookup(name) + if flag == nil { + return fmt.Errorf("flag %q does not exist", name) + } + flag.Hidden = true + return nil +} + +// Lookup returns the Flag structure of the named command-line flag, +// returning nil if none exists. +func Lookup(name string) *Flag { + return CommandLine.Lookup(name) +} + +// ShorthandLookup returns the Flag structure of the short handed flag, +// returning nil if none exists. +func ShorthandLookup(name string) *Flag { + return CommandLine.ShorthandLookup(name) +} + +// Set sets the value of the named flag. +func (f *FlagSet) Set(name, value string) error { + normalName := f.normalizeFlagName(name) + flag, ok := f.formal[normalName] + if !ok { + return fmt.Errorf("no such flag -%v", name) + } + + err := flag.Value.Set(value) + if err != nil { + var flagName string + if flag.Shorthand != "" && flag.ShorthandDeprecated == "" { + flagName = fmt.Sprintf("-%s, --%s", flag.Shorthand, flag.Name) + } else { + flagName = fmt.Sprintf("--%s", flag.Name) + } + return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err) + } + + if !flag.Changed { + if f.actual == nil { + f.actual = make(map[NormalizedName]*Flag) + } + f.actual[normalName] = flag + f.orderedActual = append(f.orderedActual, flag) + + flag.Changed = true + } + + if flag.Deprecated != "" { + fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated) + } + return nil +} + +// SetAnnotation allows one to set arbitrary annotations on a flag in the FlagSet. +// This is sometimes used by spf13/cobra programs which want to generate additional +// bash completion information. +func (f *FlagSet) SetAnnotation(name, key string, values []string) error { + normalName := f.normalizeFlagName(name) + flag, ok := f.formal[normalName] + if !ok { + return fmt.Errorf("no such flag -%v", name) + } + if flag.Annotations == nil { + flag.Annotations = map[string][]string{} + } + flag.Annotations[key] = values + return nil +} + +// Changed returns true if the flag was explicitly set during Parse() and false +// otherwise +func (f *FlagSet) Changed(name string) bool { + flag := f.Lookup(name) + // If a flag doesn't exist, it wasn't changed.... + if flag == nil { + return false + } + return flag.Changed +} + +// Set sets the value of the named command-line flag. +func Set(name, value string) error { + return CommandLine.Set(name, value) +} + +// PrintDefaults prints, to standard error unless configured +// otherwise, the default values of all defined flags in the set. +func (f *FlagSet) PrintDefaults() { + usages := f.FlagUsages() + fmt.Fprint(f.out(), usages) +} + +// defaultIsZeroValue returns true if the default value for this flag represents +// a zero value. +func (f *Flag) defaultIsZeroValue() bool { + switch f.Value.(type) { + case boolFlag: + return f.DefValue == "false" + case *durationValue: + // Beginning in Go 1.7, duration zero values are "0s" + return f.DefValue == "0" || f.DefValue == "0s" + case *intValue, *int8Value, *int32Value, *int64Value, *uintValue, *uint8Value, *uint16Value, *uint32Value, *uint64Value, *countValue, *float32Value, *float64Value: + return f.DefValue == "0" + case *stringValue: + return f.DefValue == "" + case *ipValue, *ipMaskValue, *ipNetValue: + return f.DefValue == "" + case *intSliceValue, *stringSliceValue, *stringArrayValue: + return f.DefValue == "[]" + default: + switch f.Value.String() { + case "false": + return true + case "": + return true + case "": + return true + case "0": + return true + } + return false + } +} + +// UnquoteUsage extracts a back-quoted name from the usage +// string for a flag and returns it and the un-quoted usage. +// Given "a `name` to show" it returns ("name", "a name to show"). +// If there are no back quotes, the name is an educated guess of the +// type of the flag's value, or the empty string if the flag is boolean. +func UnquoteUsage(flag *Flag) (name string, usage string) { + // Look for a back-quoted name, but avoid the strings package. + usage = flag.Usage + for i := 0; i < len(usage); i++ { + if usage[i] == '`' { + for j := i + 1; j < len(usage); j++ { + if usage[j] == '`' { + name = usage[i+1 : j] + usage = usage[:i] + name + usage[j+1:] + return name, usage + } + } + break // Only one back quote; use type name. + } + } + + name = flag.Value.Type() + switch name { + case "bool": + name = "" + case "float64": + name = "float" + case "int64": + name = "int" + case "uint64": + name = "uint" + case "stringSlice": + name = "strings" + case "intSlice": + name = "ints" + case "uintSlice": + name = "uints" + case "boolSlice": + name = "bools" + } + + return +} + +// Splits the string `s` on whitespace into an initial substring up to +// `i` runes in length and the remainder. Will go `slop` over `i` if +// that encompasses the entire string (which allows the caller to +// avoid short orphan words on the final line). +func wrapN(i, slop int, s string) (string, string) { + if i+slop > len(s) { + return s, "" + } + + w := strings.LastIndexAny(s[:i], " \t\n") + if w <= 0 { + return s, "" + } + nlPos := strings.LastIndex(s[:i], "\n") + if nlPos > 0 && nlPos < w { + return s[:nlPos], s[nlPos+1:] + } + return s[:w], s[w+1:] +} + +// Wraps the string `s` to a maximum width `w` with leading indent +// `i`. The first line is not indented (this is assumed to be done by +// caller). Pass `w` == 0 to do no wrapping +func wrap(i, w int, s string) string { + if w == 0 { + return strings.Replace(s, "\n", "\n"+strings.Repeat(" ", i), -1) + } + + // space between indent i and end of line width w into which + // we should wrap the text. + wrap := w - i + + var r, l string + + // Not enough space for sensible wrapping. Wrap as a block on + // the next line instead. + if wrap < 24 { + i = 16 + wrap = w - i + r += "\n" + strings.Repeat(" ", i) + } + // If still not enough space then don't even try to wrap. + if wrap < 24 { + return strings.Replace(s, "\n", r, -1) + } + + // Try to avoid short orphan words on the final line, by + // allowing wrapN to go a bit over if that would fit in the + // remainder of the line. + slop := 5 + wrap = wrap - slop + + // Handle first line, which is indented by the caller (or the + // special case above) + l, s = wrapN(wrap, slop, s) + r = r + strings.Replace(l, "\n", "\n"+strings.Repeat(" ", i), -1) + + // Now wrap the rest + for s != "" { + var t string + + t, s = wrapN(wrap, slop, s) + r = r + "\n" + strings.Repeat(" ", i) + strings.Replace(t, "\n", "\n"+strings.Repeat(" ", i), -1) + } + + return r + +} + +// FlagUsagesWrapped returns a string containing the usage information +// for all flags in the FlagSet. Wrapped to `cols` columns (0 for no +// wrapping) +func (f *FlagSet) FlagUsagesWrapped(cols int) string { + buf := new(bytes.Buffer) + + lines := make([]string, 0, len(f.formal)) + + maxlen := 0 + f.VisitAll(func(flag *Flag) { + if flag.Hidden { + return + } + + line := "" + if flag.Shorthand != "" && flag.ShorthandDeprecated == "" { + line = fmt.Sprintf(" -%s, --%s", flag.Shorthand, flag.Name) + } else { + line = fmt.Sprintf(" --%s", flag.Name) + } + + varname, usage := UnquoteUsage(flag) + if varname != "" { + line += " " + varname + } + if flag.NoOptDefVal != "" { + switch flag.Value.Type() { + case "string": + line += fmt.Sprintf("[=\"%s\"]", flag.NoOptDefVal) + case "bool": + if flag.NoOptDefVal != "true" { + line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) + } + case "count": + if flag.NoOptDefVal != "+1" { + line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) + } + default: + line += fmt.Sprintf("[=%s]", flag.NoOptDefVal) + } + } + + // This special character will be replaced with spacing once the + // correct alignment is calculated + line += "\x00" + if len(line) > maxlen { + maxlen = len(line) + } + + line += usage + if !flag.defaultIsZeroValue() { + if flag.Value.Type() == "string" { + line += fmt.Sprintf(" (default %q)", flag.DefValue) + } else { + line += fmt.Sprintf(" (default %s)", flag.DefValue) + } + } + if len(flag.Deprecated) != 0 { + line += fmt.Sprintf(" (DEPRECATED: %s)", flag.Deprecated) + } + + lines = append(lines, line) + }) + + for _, line := range lines { + sidx := strings.Index(line, "\x00") + spacing := strings.Repeat(" ", maxlen-sidx) + // maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx + fmt.Fprintln(buf, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:])) + } + + return buf.String() +} + +// FlagUsages returns a string containing the usage information for all flags in +// the FlagSet +func (f *FlagSet) FlagUsages() string { + return f.FlagUsagesWrapped(0) +} + +// PrintDefaults prints to standard error the default values of all defined command-line flags. +func PrintDefaults() { + CommandLine.PrintDefaults() +} + +// defaultUsage is the default function to print a usage message. +func defaultUsage(f *FlagSet) { + fmt.Fprintf(f.out(), "Usage of %s:\n", f.name) + f.PrintDefaults() +} + +// NOTE: Usage is not just defaultUsage(CommandLine) +// because it serves (via godoc flag Usage) as the example +// for how to write your own usage function. + +// Usage prints to standard error a usage message documenting all defined command-line flags. +// The function is a variable that may be changed to point to a custom function. +// By default it prints a simple header and calls PrintDefaults; for details about the +// format of the output and how to control it, see the documentation for PrintDefaults. +var Usage = func() { + fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) + PrintDefaults() +} + +// NFlag returns the number of flags that have been set. +func (f *FlagSet) NFlag() int { return len(f.actual) } + +// NFlag returns the number of command-line flags that have been set. +func NFlag() int { return len(CommandLine.actual) } + +// Arg returns the i'th argument. Arg(0) is the first remaining argument +// after flags have been processed. +func (f *FlagSet) Arg(i int) string { + if i < 0 || i >= len(f.args) { + return "" + } + return f.args[i] +} + +// Arg returns the i'th command-line argument. Arg(0) is the first remaining argument +// after flags have been processed. +func Arg(i int) string { + return CommandLine.Arg(i) +} + +// NArg is the number of arguments remaining after flags have been processed. +func (f *FlagSet) NArg() int { return len(f.args) } + +// NArg is the number of arguments remaining after flags have been processed. +func NArg() int { return len(CommandLine.args) } + +// Args returns the non-flag arguments. +func (f *FlagSet) Args() []string { return f.args } + +// Args returns the non-flag command-line arguments. +func Args() []string { return CommandLine.args } + +// Var defines a flag with the specified name and usage string. The type and +// value of the flag are represented by the first argument, of type Value, which +// typically holds a user-defined implementation of Value. For instance, the +// caller could create a flag that turns a comma-separated string into a slice +// of strings by giving the slice the methods of Value; in particular, Set would +// decompose the comma-separated string into the slice. +func (f *FlagSet) Var(value Value, name string, usage string) { + f.VarP(value, name, "", usage) +} + +// VarPF is like VarP, but returns the flag created +func (f *FlagSet) VarPF(value Value, name, shorthand, usage string) *Flag { + // Remember the default value as a string; it won't change. + flag := &Flag{ + Name: name, + Shorthand: shorthand, + Usage: usage, + Value: value, + DefValue: value.String(), + } + f.AddFlag(flag) + return flag +} + +// VarP is like Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) VarP(value Value, name, shorthand, usage string) { + f.VarPF(value, name, shorthand, usage) +} + +// AddFlag will add the flag to the FlagSet +func (f *FlagSet) AddFlag(flag *Flag) { + normalizedFlagName := f.normalizeFlagName(flag.Name) + + _, alreadyThere := f.formal[normalizedFlagName] + if alreadyThere { + msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name) + fmt.Fprintln(f.out(), msg) + panic(msg) // Happens only if flags are declared with identical names + } + if f.formal == nil { + f.formal = make(map[NormalizedName]*Flag) + } + + flag.Name = string(normalizedFlagName) + f.formal[normalizedFlagName] = flag + f.orderedFormal = append(f.orderedFormal, flag) + + if flag.Shorthand == "" { + return + } + if len(flag.Shorthand) > 1 { + msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand) + fmt.Fprintf(f.out(), msg) + panic(msg) + } + if f.shorthands == nil { + f.shorthands = make(map[byte]*Flag) + } + c := flag.Shorthand[0] + used, alreadyThere := f.shorthands[c] + if alreadyThere { + msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name) + fmt.Fprintf(f.out(), msg) + panic(msg) + } + f.shorthands[c] = flag +} + +// AddFlagSet adds one FlagSet to another. If a flag is already present in f +// the flag from newSet will be ignored. +func (f *FlagSet) AddFlagSet(newSet *FlagSet) { + if newSet == nil { + return + } + newSet.VisitAll(func(flag *Flag) { + if f.Lookup(flag.Name) == nil { + f.AddFlag(flag) + } + }) +} + +// Var defines a flag with the specified name and usage string. The type and +// value of the flag are represented by the first argument, of type Value, which +// typically holds a user-defined implementation of Value. For instance, the +// caller could create a flag that turns a comma-separated string into a slice +// of strings by giving the slice the methods of Value; in particular, Set would +// decompose the comma-separated string into the slice. +func Var(value Value, name string, usage string) { + CommandLine.VarP(value, name, "", usage) +} + +// VarP is like Var, but accepts a shorthand letter that can be used after a single dash. +func VarP(value Value, name, shorthand, usage string) { + CommandLine.VarP(value, name, shorthand, usage) +} + +// failf prints to standard error a formatted error and usage message and +// returns the error. +func (f *FlagSet) failf(format string, a ...interface{}) error { + err := fmt.Errorf(format, a...) + if f.errorHandling != ContinueOnError { + fmt.Fprintln(f.out(), err) + f.usage() + } + return err +} + +// usage calls the Usage method for the flag set, or the usage function if +// the flag set is CommandLine. +func (f *FlagSet) usage() { + if f == CommandLine { + Usage() + } else if f.Usage == nil { + defaultUsage(f) + } else { + f.Usage() + } +} + +//--unknown (args will be empty) +//--unknown --next-flag ... (args will be --next-flag ...) +//--unknown arg ... (args will be arg ...) +func stripUnknownFlagValue(args []string) []string { + if len(args) == 0 { + //--unknown + return args + } + + first := args[0] + if first[0] == '-' { + //--unknown --next-flag ... + return args + } + + //--unknown arg ... (args will be arg ...) + return args[1:] +} + +func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) { + a = args + name := s[2:] + if len(name) == 0 || name[0] == '-' || name[0] == '=' { + err = f.failf("bad flag syntax: %s", s) + return + } + + split := strings.SplitN(name, "=", 2) + name = split[0] + flag, exists := f.formal[f.normalizeFlagName(name)] + + if !exists { + switch { + case name == "help": + f.usage() + return a, ErrHelp + case f.ParseErrorsWhitelist.UnknownFlags: + // --unknown=unknownval arg ... + // we do not want to lose arg in this case + if len(split) >= 2 { + return a, nil + } + + return stripUnknownFlagValue(a), nil + default: + err = f.failf("unknown flag: --%s", name) + return + } + } + + var value string + if len(split) == 2 { + // '--flag=arg' + value = split[1] + } else if flag.NoOptDefVal != "" { + // '--flag' (arg was optional) + value = flag.NoOptDefVal + } else if len(a) > 0 { + // '--flag arg' + value = a[0] + a = a[1:] + } else { + // '--flag' (arg was required) + err = f.failf("flag needs an argument: %s", s) + return + } + + err = fn(flag, value) + if err != nil { + f.failf(err.Error()) + } + return +} + +func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) { + outArgs = args + + if strings.HasPrefix(shorthands, "test.") { + return + } + + outShorts = shorthands[1:] + c := shorthands[0] + + flag, exists := f.shorthands[c] + if !exists { + switch { + case c == 'h': + f.usage() + err = ErrHelp + return + case f.ParseErrorsWhitelist.UnknownFlags: + // '-f=arg arg ...' + // we do not want to lose arg in this case + if len(shorthands) > 2 && shorthands[1] == '=' { + outShorts = "" + return + } + + outArgs = stripUnknownFlagValue(outArgs) + return + default: + err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands) + return + } + } + + var value string + if len(shorthands) > 2 && shorthands[1] == '=' { + // '-f=arg' + value = shorthands[2:] + outShorts = "" + } else if flag.NoOptDefVal != "" { + // '-f' (arg was optional) + value = flag.NoOptDefVal + } else if len(shorthands) > 1 { + // '-farg' + value = shorthands[1:] + outShorts = "" + } else if len(args) > 0 { + // '-f arg' + value = args[0] + outArgs = args[1:] + } else { + // '-f' (arg was required) + err = f.failf("flag needs an argument: %q in -%s", c, shorthands) + return + } + + if flag.ShorthandDeprecated != "" { + fmt.Fprintf(f.out(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated) + } + + err = fn(flag, value) + if err != nil { + f.failf(err.Error()) + } + return +} + +func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []string, err error) { + a = args + shorthands := s[1:] + + // "shorthands" can be a series of shorthand letters of flags (e.g. "-vvv"). + for len(shorthands) > 0 { + shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn) + if err != nil { + return + } + } + + return +} + +func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) { + for len(args) > 0 { + s := args[0] + args = args[1:] + if len(s) == 0 || s[0] != '-' || len(s) == 1 { + if !f.interspersed { + f.args = append(f.args, s) + f.args = append(f.args, args...) + return nil + } + f.args = append(f.args, s) + continue + } + + if s[1] == '-' { + if len(s) == 2 { // "--" terminates the flags + f.argsLenAtDash = len(f.args) + f.args = append(f.args, args...) + break + } + args, err = f.parseLongArg(s, args, fn) + } else { + args, err = f.parseShortArg(s, args, fn) + } + if err != nil { + return + } + } + return +} + +// Parse parses flag definitions from the argument list, which should not +// include the command name. Must be called after all flags in the FlagSet +// are defined and before flags are accessed by the program. +// The return value will be ErrHelp if -help was set but not defined. +func (f *FlagSet) Parse(arguments []string) error { + if f.addedGoFlagSets != nil { + for _, goFlagSet := range f.addedGoFlagSets { + goFlagSet.Parse(nil) + } + } + f.parsed = true + + if len(arguments) < 0 { + return nil + } + + f.args = make([]string, 0, len(arguments)) + + set := func(flag *Flag, value string) error { + return f.Set(flag.Name, value) + } + + err := f.parseArgs(arguments, set) + if err != nil { + switch f.errorHandling { + case ContinueOnError: + return err + case ExitOnError: + fmt.Println(err) + os.Exit(2) + case PanicOnError: + panic(err) + } + } + return nil +} + +type parseFunc func(flag *Flag, value string) error + +// ParseAll parses flag definitions from the argument list, which should not +// include the command name. The arguments for fn are flag and value. Must be +// called after all flags in the FlagSet are defined and before flags are +// accessed by the program. The return value will be ErrHelp if -help was set +// but not defined. +func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) error) error { + f.parsed = true + f.args = make([]string, 0, len(arguments)) + + err := f.parseArgs(arguments, fn) + if err != nil { + switch f.errorHandling { + case ContinueOnError: + return err + case ExitOnError: + os.Exit(2) + case PanicOnError: + panic(err) + } + } + return nil +} + +// Parsed reports whether f.Parse has been called. +func (f *FlagSet) Parsed() bool { + return f.parsed +} + +// Parse parses the command-line flags from os.Args[1:]. Must be called +// after all flags are defined and before flags are accessed by the program. +func Parse() { + // Ignore errors; CommandLine is set for ExitOnError. + CommandLine.Parse(os.Args[1:]) +} + +// ParseAll parses the command-line flags from os.Args[1:] and called fn for each. +// The arguments for fn are flag and value. Must be called after all flags are +// defined and before flags are accessed by the program. +func ParseAll(fn func(flag *Flag, value string) error) { + // Ignore errors; CommandLine is set for ExitOnError. + CommandLine.ParseAll(os.Args[1:], fn) +} + +// SetInterspersed sets whether to support interspersed option/non-option arguments. +func SetInterspersed(interspersed bool) { + CommandLine.SetInterspersed(interspersed) +} + +// Parsed returns true if the command-line flags have been parsed. +func Parsed() bool { + return CommandLine.Parsed() +} + +// CommandLine is the default set of command-line flags, parsed from os.Args. +var CommandLine = NewFlagSet(os.Args[0], ExitOnError) + +// NewFlagSet returns a new, empty flag set with the specified name, +// error handling property and SortFlags set to true. +func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet { + f := &FlagSet{ + name: name, + errorHandling: errorHandling, + argsLenAtDash: -1, + interspersed: true, + SortFlags: true, + } + return f +} + +// SetInterspersed sets whether to support interspersed option/non-option arguments. +func (f *FlagSet) SetInterspersed(interspersed bool) { + f.interspersed = interspersed +} + +// Init sets the name and error handling property for a flag set. +// By default, the zero FlagSet uses an empty name and the +// ContinueOnError error handling policy. +func (f *FlagSet) Init(name string, errorHandling ErrorHandling) { + f.name = name + f.errorHandling = errorHandling + f.argsLenAtDash = -1 +} diff --git a/vendor/github.com/spf13/pflag/float32.go b/vendor/github.com/spf13/pflag/float32.go new file mode 100644 index 0000000000..a243f81f7f --- /dev/null +++ b/vendor/github.com/spf13/pflag/float32.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- float32 Value +type float32Value float32 + +func newFloat32Value(val float32, p *float32) *float32Value { + *p = val + return (*float32Value)(p) +} + +func (f *float32Value) Set(s string) error { + v, err := strconv.ParseFloat(s, 32) + *f = float32Value(v) + return err +} + +func (f *float32Value) Type() string { + return "float32" +} + +func (f *float32Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 32) } + +func float32Conv(sval string) (interface{}, error) { + v, err := strconv.ParseFloat(sval, 32) + if err != nil { + return 0, err + } + return float32(v), nil +} + +// GetFloat32 return the float32 value of a flag with the given name +func (f *FlagSet) GetFloat32(name string) (float32, error) { + val, err := f.getFlagType(name, "float32", float32Conv) + if err != nil { + return 0, err + } + return val.(float32), nil +} + +// Float32Var defines a float32 flag with specified name, default value, and usage string. +// The argument p points to a float32 variable in which to store the value of the flag. +func (f *FlagSet) Float32Var(p *float32, name string, value float32, usage string) { + f.VarP(newFloat32Value(value, p), name, "", usage) +} + +// Float32VarP is like Float32Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Float32VarP(p *float32, name, shorthand string, value float32, usage string) { + f.VarP(newFloat32Value(value, p), name, shorthand, usage) +} + +// Float32Var defines a float32 flag with specified name, default value, and usage string. +// The argument p points to a float32 variable in which to store the value of the flag. +func Float32Var(p *float32, name string, value float32, usage string) { + CommandLine.VarP(newFloat32Value(value, p), name, "", usage) +} + +// Float32VarP is like Float32Var, but accepts a shorthand letter that can be used after a single dash. +func Float32VarP(p *float32, name, shorthand string, value float32, usage string) { + CommandLine.VarP(newFloat32Value(value, p), name, shorthand, usage) +} + +// Float32 defines a float32 flag with specified name, default value, and usage string. +// The return value is the address of a float32 variable that stores the value of the flag. +func (f *FlagSet) Float32(name string, value float32, usage string) *float32 { + p := new(float32) + f.Float32VarP(p, name, "", value, usage) + return p +} + +// Float32P is like Float32, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Float32P(name, shorthand string, value float32, usage string) *float32 { + p := new(float32) + f.Float32VarP(p, name, shorthand, value, usage) + return p +} + +// Float32 defines a float32 flag with specified name, default value, and usage string. +// The return value is the address of a float32 variable that stores the value of the flag. +func Float32(name string, value float32, usage string) *float32 { + return CommandLine.Float32P(name, "", value, usage) +} + +// Float32P is like Float32, but accepts a shorthand letter that can be used after a single dash. +func Float32P(name, shorthand string, value float32, usage string) *float32 { + return CommandLine.Float32P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/float64.go b/vendor/github.com/spf13/pflag/float64.go new file mode 100644 index 0000000000..04b5492a7d --- /dev/null +++ b/vendor/github.com/spf13/pflag/float64.go @@ -0,0 +1,84 @@ +package pflag + +import "strconv" + +// -- float64 Value +type float64Value float64 + +func newFloat64Value(val float64, p *float64) *float64Value { + *p = val + return (*float64Value)(p) +} + +func (f *float64Value) Set(s string) error { + v, err := strconv.ParseFloat(s, 64) + *f = float64Value(v) + return err +} + +func (f *float64Value) Type() string { + return "float64" +} + +func (f *float64Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 64) } + +func float64Conv(sval string) (interface{}, error) { + return strconv.ParseFloat(sval, 64) +} + +// GetFloat64 return the float64 value of a flag with the given name +func (f *FlagSet) GetFloat64(name string) (float64, error) { + val, err := f.getFlagType(name, "float64", float64Conv) + if err != nil { + return 0, err + } + return val.(float64), nil +} + +// Float64Var defines a float64 flag with specified name, default value, and usage string. +// The argument p points to a float64 variable in which to store the value of the flag. +func (f *FlagSet) Float64Var(p *float64, name string, value float64, usage string) { + f.VarP(newFloat64Value(value, p), name, "", usage) +} + +// Float64VarP is like Float64Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Float64VarP(p *float64, name, shorthand string, value float64, usage string) { + f.VarP(newFloat64Value(value, p), name, shorthand, usage) +} + +// Float64Var defines a float64 flag with specified name, default value, and usage string. +// The argument p points to a float64 variable in which to store the value of the flag. +func Float64Var(p *float64, name string, value float64, usage string) { + CommandLine.VarP(newFloat64Value(value, p), name, "", usage) +} + +// Float64VarP is like Float64Var, but accepts a shorthand letter that can be used after a single dash. +func Float64VarP(p *float64, name, shorthand string, value float64, usage string) { + CommandLine.VarP(newFloat64Value(value, p), name, shorthand, usage) +} + +// Float64 defines a float64 flag with specified name, default value, and usage string. +// The return value is the address of a float64 variable that stores the value of the flag. +func (f *FlagSet) Float64(name string, value float64, usage string) *float64 { + p := new(float64) + f.Float64VarP(p, name, "", value, usage) + return p +} + +// Float64P is like Float64, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Float64P(name, shorthand string, value float64, usage string) *float64 { + p := new(float64) + f.Float64VarP(p, name, shorthand, value, usage) + return p +} + +// Float64 defines a float64 flag with specified name, default value, and usage string. +// The return value is the address of a float64 variable that stores the value of the flag. +func Float64(name string, value float64, usage string) *float64 { + return CommandLine.Float64P(name, "", value, usage) +} + +// Float64P is like Float64, but accepts a shorthand letter that can be used after a single dash. +func Float64P(name, shorthand string, value float64, usage string) *float64 { + return CommandLine.Float64P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/golangflag.go b/vendor/github.com/spf13/pflag/golangflag.go new file mode 100644 index 0000000000..d3dd72b7fe --- /dev/null +++ b/vendor/github.com/spf13/pflag/golangflag.go @@ -0,0 +1,105 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package pflag + +import ( + goflag "flag" + "reflect" + "strings" +) + +// flagValueWrapper implements pflag.Value around a flag.Value. The main +// difference here is the addition of the Type method that returns a string +// name of the type. As this is generally unknown, we approximate that with +// reflection. +type flagValueWrapper struct { + inner goflag.Value + flagType string +} + +// We are just copying the boolFlag interface out of goflag as that is what +// they use to decide if a flag should get "true" when no arg is given. +type goBoolFlag interface { + goflag.Value + IsBoolFlag() bool +} + +func wrapFlagValue(v goflag.Value) Value { + // If the flag.Value happens to also be a pflag.Value, just use it directly. + if pv, ok := v.(Value); ok { + return pv + } + + pv := &flagValueWrapper{ + inner: v, + } + + t := reflect.TypeOf(v) + if t.Kind() == reflect.Interface || t.Kind() == reflect.Ptr { + t = t.Elem() + } + + pv.flagType = strings.TrimSuffix(t.Name(), "Value") + return pv +} + +func (v *flagValueWrapper) String() string { + return v.inner.String() +} + +func (v *flagValueWrapper) Set(s string) error { + return v.inner.Set(s) +} + +func (v *flagValueWrapper) Type() string { + return v.flagType +} + +// PFlagFromGoFlag will return a *pflag.Flag given a *flag.Flag +// If the *flag.Flag.Name was a single character (ex: `v`) it will be accessiblei +// with both `-v` and `--v` in flags. If the golang flag was more than a single +// character (ex: `verbose`) it will only be accessible via `--verbose` +func PFlagFromGoFlag(goflag *goflag.Flag) *Flag { + // Remember the default value as a string; it won't change. + flag := &Flag{ + Name: goflag.Name, + Usage: goflag.Usage, + Value: wrapFlagValue(goflag.Value), + // Looks like golang flags don't set DefValue correctly :-( + //DefValue: goflag.DefValue, + DefValue: goflag.Value.String(), + } + // Ex: if the golang flag was -v, allow both -v and --v to work + if len(flag.Name) == 1 { + flag.Shorthand = flag.Name + } + if fv, ok := goflag.Value.(goBoolFlag); ok && fv.IsBoolFlag() { + flag.NoOptDefVal = "true" + } + return flag +} + +// AddGoFlag will add the given *flag.Flag to the pflag.FlagSet +func (f *FlagSet) AddGoFlag(goflag *goflag.Flag) { + if f.Lookup(goflag.Name) != nil { + return + } + newflag := PFlagFromGoFlag(goflag) + f.AddFlag(newflag) +} + +// AddGoFlagSet will add the given *flag.FlagSet to the pflag.FlagSet +func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) { + if newSet == nil { + return + } + newSet.VisitAll(func(goflag *goflag.Flag) { + f.AddGoFlag(goflag) + }) + if f.addedGoFlagSets == nil { + f.addedGoFlagSets = make([]*goflag.FlagSet, 0) + } + f.addedGoFlagSets = append(f.addedGoFlagSets, newSet) +} diff --git a/vendor/github.com/spf13/pflag/int.go b/vendor/github.com/spf13/pflag/int.go new file mode 100644 index 0000000000..1474b89df6 --- /dev/null +++ b/vendor/github.com/spf13/pflag/int.go @@ -0,0 +1,84 @@ +package pflag + +import "strconv" + +// -- int Value +type intValue int + +func newIntValue(val int, p *int) *intValue { + *p = val + return (*intValue)(p) +} + +func (i *intValue) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 64) + *i = intValue(v) + return err +} + +func (i *intValue) Type() string { + return "int" +} + +func (i *intValue) String() string { return strconv.Itoa(int(*i)) } + +func intConv(sval string) (interface{}, error) { + return strconv.Atoi(sval) +} + +// GetInt return the int value of a flag with the given name +func (f *FlagSet) GetInt(name string) (int, error) { + val, err := f.getFlagType(name, "int", intConv) + if err != nil { + return 0, err + } + return val.(int), nil +} + +// IntVar defines an int flag with specified name, default value, and usage string. +// The argument p points to an int variable in which to store the value of the flag. +func (f *FlagSet) IntVar(p *int, name string, value int, usage string) { + f.VarP(newIntValue(value, p), name, "", usage) +} + +// IntVarP is like IntVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IntVarP(p *int, name, shorthand string, value int, usage string) { + f.VarP(newIntValue(value, p), name, shorthand, usage) +} + +// IntVar defines an int flag with specified name, default value, and usage string. +// The argument p points to an int variable in which to store the value of the flag. +func IntVar(p *int, name string, value int, usage string) { + CommandLine.VarP(newIntValue(value, p), name, "", usage) +} + +// IntVarP is like IntVar, but accepts a shorthand letter that can be used after a single dash. +func IntVarP(p *int, name, shorthand string, value int, usage string) { + CommandLine.VarP(newIntValue(value, p), name, shorthand, usage) +} + +// Int defines an int flag with specified name, default value, and usage string. +// The return value is the address of an int variable that stores the value of the flag. +func (f *FlagSet) Int(name string, value int, usage string) *int { + p := new(int) + f.IntVarP(p, name, "", value, usage) + return p +} + +// IntP is like Int, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IntP(name, shorthand string, value int, usage string) *int { + p := new(int) + f.IntVarP(p, name, shorthand, value, usage) + return p +} + +// Int defines an int flag with specified name, default value, and usage string. +// The return value is the address of an int variable that stores the value of the flag. +func Int(name string, value int, usage string) *int { + return CommandLine.IntP(name, "", value, usage) +} + +// IntP is like Int, but accepts a shorthand letter that can be used after a single dash. +func IntP(name, shorthand string, value int, usage string) *int { + return CommandLine.IntP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/int16.go b/vendor/github.com/spf13/pflag/int16.go new file mode 100644 index 0000000000..f1a01d05e6 --- /dev/null +++ b/vendor/github.com/spf13/pflag/int16.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- int16 Value +type int16Value int16 + +func newInt16Value(val int16, p *int16) *int16Value { + *p = val + return (*int16Value)(p) +} + +func (i *int16Value) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 16) + *i = int16Value(v) + return err +} + +func (i *int16Value) Type() string { + return "int16" +} + +func (i *int16Value) String() string { return strconv.FormatInt(int64(*i), 10) } + +func int16Conv(sval string) (interface{}, error) { + v, err := strconv.ParseInt(sval, 0, 16) + if err != nil { + return 0, err + } + return int16(v), nil +} + +// GetInt16 returns the int16 value of a flag with the given name +func (f *FlagSet) GetInt16(name string) (int16, error) { + val, err := f.getFlagType(name, "int16", int16Conv) + if err != nil { + return 0, err + } + return val.(int16), nil +} + +// Int16Var defines an int16 flag with specified name, default value, and usage string. +// The argument p points to an int16 variable in which to store the value of the flag. +func (f *FlagSet) Int16Var(p *int16, name string, value int16, usage string) { + f.VarP(newInt16Value(value, p), name, "", usage) +} + +// Int16VarP is like Int16Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int16VarP(p *int16, name, shorthand string, value int16, usage string) { + f.VarP(newInt16Value(value, p), name, shorthand, usage) +} + +// Int16Var defines an int16 flag with specified name, default value, and usage string. +// The argument p points to an int16 variable in which to store the value of the flag. +func Int16Var(p *int16, name string, value int16, usage string) { + CommandLine.VarP(newInt16Value(value, p), name, "", usage) +} + +// Int16VarP is like Int16Var, but accepts a shorthand letter that can be used after a single dash. +func Int16VarP(p *int16, name, shorthand string, value int16, usage string) { + CommandLine.VarP(newInt16Value(value, p), name, shorthand, usage) +} + +// Int16 defines an int16 flag with specified name, default value, and usage string. +// The return value is the address of an int16 variable that stores the value of the flag. +func (f *FlagSet) Int16(name string, value int16, usage string) *int16 { + p := new(int16) + f.Int16VarP(p, name, "", value, usage) + return p +} + +// Int16P is like Int16, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int16P(name, shorthand string, value int16, usage string) *int16 { + p := new(int16) + f.Int16VarP(p, name, shorthand, value, usage) + return p +} + +// Int16 defines an int16 flag with specified name, default value, and usage string. +// The return value is the address of an int16 variable that stores the value of the flag. +func Int16(name string, value int16, usage string) *int16 { + return CommandLine.Int16P(name, "", value, usage) +} + +// Int16P is like Int16, but accepts a shorthand letter that can be used after a single dash. +func Int16P(name, shorthand string, value int16, usage string) *int16 { + return CommandLine.Int16P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/int32.go b/vendor/github.com/spf13/pflag/int32.go new file mode 100644 index 0000000000..9b95944f0f --- /dev/null +++ b/vendor/github.com/spf13/pflag/int32.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- int32 Value +type int32Value int32 + +func newInt32Value(val int32, p *int32) *int32Value { + *p = val + return (*int32Value)(p) +} + +func (i *int32Value) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 32) + *i = int32Value(v) + return err +} + +func (i *int32Value) Type() string { + return "int32" +} + +func (i *int32Value) String() string { return strconv.FormatInt(int64(*i), 10) } + +func int32Conv(sval string) (interface{}, error) { + v, err := strconv.ParseInt(sval, 0, 32) + if err != nil { + return 0, err + } + return int32(v), nil +} + +// GetInt32 return the int32 value of a flag with the given name +func (f *FlagSet) GetInt32(name string) (int32, error) { + val, err := f.getFlagType(name, "int32", int32Conv) + if err != nil { + return 0, err + } + return val.(int32), nil +} + +// Int32Var defines an int32 flag with specified name, default value, and usage string. +// The argument p points to an int32 variable in which to store the value of the flag. +func (f *FlagSet) Int32Var(p *int32, name string, value int32, usage string) { + f.VarP(newInt32Value(value, p), name, "", usage) +} + +// Int32VarP is like Int32Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int32VarP(p *int32, name, shorthand string, value int32, usage string) { + f.VarP(newInt32Value(value, p), name, shorthand, usage) +} + +// Int32Var defines an int32 flag with specified name, default value, and usage string. +// The argument p points to an int32 variable in which to store the value of the flag. +func Int32Var(p *int32, name string, value int32, usage string) { + CommandLine.VarP(newInt32Value(value, p), name, "", usage) +} + +// Int32VarP is like Int32Var, but accepts a shorthand letter that can be used after a single dash. +func Int32VarP(p *int32, name, shorthand string, value int32, usage string) { + CommandLine.VarP(newInt32Value(value, p), name, shorthand, usage) +} + +// Int32 defines an int32 flag with specified name, default value, and usage string. +// The return value is the address of an int32 variable that stores the value of the flag. +func (f *FlagSet) Int32(name string, value int32, usage string) *int32 { + p := new(int32) + f.Int32VarP(p, name, "", value, usage) + return p +} + +// Int32P is like Int32, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int32P(name, shorthand string, value int32, usage string) *int32 { + p := new(int32) + f.Int32VarP(p, name, shorthand, value, usage) + return p +} + +// Int32 defines an int32 flag with specified name, default value, and usage string. +// The return value is the address of an int32 variable that stores the value of the flag. +func Int32(name string, value int32, usage string) *int32 { + return CommandLine.Int32P(name, "", value, usage) +} + +// Int32P is like Int32, but accepts a shorthand letter that can be used after a single dash. +func Int32P(name, shorthand string, value int32, usage string) *int32 { + return CommandLine.Int32P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/int64.go b/vendor/github.com/spf13/pflag/int64.go new file mode 100644 index 0000000000..0026d781d9 --- /dev/null +++ b/vendor/github.com/spf13/pflag/int64.go @@ -0,0 +1,84 @@ +package pflag + +import "strconv" + +// -- int64 Value +type int64Value int64 + +func newInt64Value(val int64, p *int64) *int64Value { + *p = val + return (*int64Value)(p) +} + +func (i *int64Value) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 64) + *i = int64Value(v) + return err +} + +func (i *int64Value) Type() string { + return "int64" +} + +func (i *int64Value) String() string { return strconv.FormatInt(int64(*i), 10) } + +func int64Conv(sval string) (interface{}, error) { + return strconv.ParseInt(sval, 0, 64) +} + +// GetInt64 return the int64 value of a flag with the given name +func (f *FlagSet) GetInt64(name string) (int64, error) { + val, err := f.getFlagType(name, "int64", int64Conv) + if err != nil { + return 0, err + } + return val.(int64), nil +} + +// Int64Var defines an int64 flag with specified name, default value, and usage string. +// The argument p points to an int64 variable in which to store the value of the flag. +func (f *FlagSet) Int64Var(p *int64, name string, value int64, usage string) { + f.VarP(newInt64Value(value, p), name, "", usage) +} + +// Int64VarP is like Int64Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int64VarP(p *int64, name, shorthand string, value int64, usage string) { + f.VarP(newInt64Value(value, p), name, shorthand, usage) +} + +// Int64Var defines an int64 flag with specified name, default value, and usage string. +// The argument p points to an int64 variable in which to store the value of the flag. +func Int64Var(p *int64, name string, value int64, usage string) { + CommandLine.VarP(newInt64Value(value, p), name, "", usage) +} + +// Int64VarP is like Int64Var, but accepts a shorthand letter that can be used after a single dash. +func Int64VarP(p *int64, name, shorthand string, value int64, usage string) { + CommandLine.VarP(newInt64Value(value, p), name, shorthand, usage) +} + +// Int64 defines an int64 flag with specified name, default value, and usage string. +// The return value is the address of an int64 variable that stores the value of the flag. +func (f *FlagSet) Int64(name string, value int64, usage string) *int64 { + p := new(int64) + f.Int64VarP(p, name, "", value, usage) + return p +} + +// Int64P is like Int64, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int64P(name, shorthand string, value int64, usage string) *int64 { + p := new(int64) + f.Int64VarP(p, name, shorthand, value, usage) + return p +} + +// Int64 defines an int64 flag with specified name, default value, and usage string. +// The return value is the address of an int64 variable that stores the value of the flag. +func Int64(name string, value int64, usage string) *int64 { + return CommandLine.Int64P(name, "", value, usage) +} + +// Int64P is like Int64, but accepts a shorthand letter that can be used after a single dash. +func Int64P(name, shorthand string, value int64, usage string) *int64 { + return CommandLine.Int64P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/int8.go b/vendor/github.com/spf13/pflag/int8.go new file mode 100644 index 0000000000..4da92228e6 --- /dev/null +++ b/vendor/github.com/spf13/pflag/int8.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- int8 Value +type int8Value int8 + +func newInt8Value(val int8, p *int8) *int8Value { + *p = val + return (*int8Value)(p) +} + +func (i *int8Value) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 8) + *i = int8Value(v) + return err +} + +func (i *int8Value) Type() string { + return "int8" +} + +func (i *int8Value) String() string { return strconv.FormatInt(int64(*i), 10) } + +func int8Conv(sval string) (interface{}, error) { + v, err := strconv.ParseInt(sval, 0, 8) + if err != nil { + return 0, err + } + return int8(v), nil +} + +// GetInt8 return the int8 value of a flag with the given name +func (f *FlagSet) GetInt8(name string) (int8, error) { + val, err := f.getFlagType(name, "int8", int8Conv) + if err != nil { + return 0, err + } + return val.(int8), nil +} + +// Int8Var defines an int8 flag with specified name, default value, and usage string. +// The argument p points to an int8 variable in which to store the value of the flag. +func (f *FlagSet) Int8Var(p *int8, name string, value int8, usage string) { + f.VarP(newInt8Value(value, p), name, "", usage) +} + +// Int8VarP is like Int8Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int8VarP(p *int8, name, shorthand string, value int8, usage string) { + f.VarP(newInt8Value(value, p), name, shorthand, usage) +} + +// Int8Var defines an int8 flag with specified name, default value, and usage string. +// The argument p points to an int8 variable in which to store the value of the flag. +func Int8Var(p *int8, name string, value int8, usage string) { + CommandLine.VarP(newInt8Value(value, p), name, "", usage) +} + +// Int8VarP is like Int8Var, but accepts a shorthand letter that can be used after a single dash. +func Int8VarP(p *int8, name, shorthand string, value int8, usage string) { + CommandLine.VarP(newInt8Value(value, p), name, shorthand, usage) +} + +// Int8 defines an int8 flag with specified name, default value, and usage string. +// The return value is the address of an int8 variable that stores the value of the flag. +func (f *FlagSet) Int8(name string, value int8, usage string) *int8 { + p := new(int8) + f.Int8VarP(p, name, "", value, usage) + return p +} + +// Int8P is like Int8, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Int8P(name, shorthand string, value int8, usage string) *int8 { + p := new(int8) + f.Int8VarP(p, name, shorthand, value, usage) + return p +} + +// Int8 defines an int8 flag with specified name, default value, and usage string. +// The return value is the address of an int8 variable that stores the value of the flag. +func Int8(name string, value int8, usage string) *int8 { + return CommandLine.Int8P(name, "", value, usage) +} + +// Int8P is like Int8, but accepts a shorthand letter that can be used after a single dash. +func Int8P(name, shorthand string, value int8, usage string) *int8 { + return CommandLine.Int8P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/int_slice.go b/vendor/github.com/spf13/pflag/int_slice.go new file mode 100644 index 0000000000..1e7c9edde9 --- /dev/null +++ b/vendor/github.com/spf13/pflag/int_slice.go @@ -0,0 +1,128 @@ +package pflag + +import ( + "fmt" + "strconv" + "strings" +) + +// -- intSlice Value +type intSliceValue struct { + value *[]int + changed bool +} + +func newIntSliceValue(val []int, p *[]int) *intSliceValue { + isv := new(intSliceValue) + isv.value = p + *isv.value = val + return isv +} + +func (s *intSliceValue) Set(val string) error { + ss := strings.Split(val, ",") + out := make([]int, len(ss)) + for i, d := range ss { + var err error + out[i], err = strconv.Atoi(d) + if err != nil { + return err + } + + } + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + s.changed = true + return nil +} + +func (s *intSliceValue) Type() string { + return "intSlice" +} + +func (s *intSliceValue) String() string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = fmt.Sprintf("%d", d) + } + return "[" + strings.Join(out, ",") + "]" +} + +func intSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []int{}, nil + } + ss := strings.Split(val, ",") + out := make([]int, len(ss)) + for i, d := range ss { + var err error + out[i], err = strconv.Atoi(d) + if err != nil { + return nil, err + } + + } + return out, nil +} + +// GetIntSlice return the []int value of a flag with the given name +func (f *FlagSet) GetIntSlice(name string) ([]int, error) { + val, err := f.getFlagType(name, "intSlice", intSliceConv) + if err != nil { + return []int{}, err + } + return val.([]int), nil +} + +// IntSliceVar defines a intSlice flag with specified name, default value, and usage string. +// The argument p points to a []int variable in which to store the value of the flag. +func (f *FlagSet) IntSliceVar(p *[]int, name string, value []int, usage string) { + f.VarP(newIntSliceValue(value, p), name, "", usage) +} + +// IntSliceVarP is like IntSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IntSliceVarP(p *[]int, name, shorthand string, value []int, usage string) { + f.VarP(newIntSliceValue(value, p), name, shorthand, usage) +} + +// IntSliceVar defines a int[] flag with specified name, default value, and usage string. +// The argument p points to a int[] variable in which to store the value of the flag. +func IntSliceVar(p *[]int, name string, value []int, usage string) { + CommandLine.VarP(newIntSliceValue(value, p), name, "", usage) +} + +// IntSliceVarP is like IntSliceVar, but accepts a shorthand letter that can be used after a single dash. +func IntSliceVarP(p *[]int, name, shorthand string, value []int, usage string) { + CommandLine.VarP(newIntSliceValue(value, p), name, shorthand, usage) +} + +// IntSlice defines a []int flag with specified name, default value, and usage string. +// The return value is the address of a []int variable that stores the value of the flag. +func (f *FlagSet) IntSlice(name string, value []int, usage string) *[]int { + p := []int{} + f.IntSliceVarP(&p, name, "", value, usage) + return &p +} + +// IntSliceP is like IntSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IntSliceP(name, shorthand string, value []int, usage string) *[]int { + p := []int{} + f.IntSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// IntSlice defines a []int flag with specified name, default value, and usage string. +// The return value is the address of a []int variable that stores the value of the flag. +func IntSlice(name string, value []int, usage string) *[]int { + return CommandLine.IntSliceP(name, "", value, usage) +} + +// IntSliceP is like IntSlice, but accepts a shorthand letter that can be used after a single dash. +func IntSliceP(name, shorthand string, value []int, usage string) *[]int { + return CommandLine.IntSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/ip.go b/vendor/github.com/spf13/pflag/ip.go new file mode 100644 index 0000000000..3d414ba69f --- /dev/null +++ b/vendor/github.com/spf13/pflag/ip.go @@ -0,0 +1,94 @@ +package pflag + +import ( + "fmt" + "net" + "strings" +) + +// -- net.IP value +type ipValue net.IP + +func newIPValue(val net.IP, p *net.IP) *ipValue { + *p = val + return (*ipValue)(p) +} + +func (i *ipValue) String() string { return net.IP(*i).String() } +func (i *ipValue) Set(s string) error { + ip := net.ParseIP(strings.TrimSpace(s)) + if ip == nil { + return fmt.Errorf("failed to parse IP: %q", s) + } + *i = ipValue(ip) + return nil +} + +func (i *ipValue) Type() string { + return "ip" +} + +func ipConv(sval string) (interface{}, error) { + ip := net.ParseIP(sval) + if ip != nil { + return ip, nil + } + return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval) +} + +// GetIP return the net.IP value of a flag with the given name +func (f *FlagSet) GetIP(name string) (net.IP, error) { + val, err := f.getFlagType(name, "ip", ipConv) + if err != nil { + return nil, err + } + return val.(net.IP), nil +} + +// IPVar defines an net.IP flag with specified name, default value, and usage string. +// The argument p points to an net.IP variable in which to store the value of the flag. +func (f *FlagSet) IPVar(p *net.IP, name string, value net.IP, usage string) { + f.VarP(newIPValue(value, p), name, "", usage) +} + +// IPVarP is like IPVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPVarP(p *net.IP, name, shorthand string, value net.IP, usage string) { + f.VarP(newIPValue(value, p), name, shorthand, usage) +} + +// IPVar defines an net.IP flag with specified name, default value, and usage string. +// The argument p points to an net.IP variable in which to store the value of the flag. +func IPVar(p *net.IP, name string, value net.IP, usage string) { + CommandLine.VarP(newIPValue(value, p), name, "", usage) +} + +// IPVarP is like IPVar, but accepts a shorthand letter that can be used after a single dash. +func IPVarP(p *net.IP, name, shorthand string, value net.IP, usage string) { + CommandLine.VarP(newIPValue(value, p), name, shorthand, usage) +} + +// IP defines an net.IP flag with specified name, default value, and usage string. +// The return value is the address of an net.IP variable that stores the value of the flag. +func (f *FlagSet) IP(name string, value net.IP, usage string) *net.IP { + p := new(net.IP) + f.IPVarP(p, name, "", value, usage) + return p +} + +// IPP is like IP, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPP(name, shorthand string, value net.IP, usage string) *net.IP { + p := new(net.IP) + f.IPVarP(p, name, shorthand, value, usage) + return p +} + +// IP defines an net.IP flag with specified name, default value, and usage string. +// The return value is the address of an net.IP variable that stores the value of the flag. +func IP(name string, value net.IP, usage string) *net.IP { + return CommandLine.IPP(name, "", value, usage) +} + +// IPP is like IP, but accepts a shorthand letter that can be used after a single dash. +func IPP(name, shorthand string, value net.IP, usage string) *net.IP { + return CommandLine.IPP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/ip_slice.go b/vendor/github.com/spf13/pflag/ip_slice.go new file mode 100644 index 0000000000..7dd196fe3f --- /dev/null +++ b/vendor/github.com/spf13/pflag/ip_slice.go @@ -0,0 +1,148 @@ +package pflag + +import ( + "fmt" + "io" + "net" + "strings" +) + +// -- ipSlice Value +type ipSliceValue struct { + value *[]net.IP + changed bool +} + +func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue { + ipsv := new(ipSliceValue) + ipsv.value = p + *ipsv.value = val + return ipsv +} + +// Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag. +// If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended. +func (s *ipSliceValue) Set(val string) error { + + // remove all quote characters + rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") + + // read flag arguments with CSV parser + ipStrSlice, err := readAsCSV(rmQuote.Replace(val)) + if err != nil && err != io.EOF { + return err + } + + // parse ip values into slice + out := make([]net.IP, 0, len(ipStrSlice)) + for _, ipStr := range ipStrSlice { + ip := net.ParseIP(strings.TrimSpace(ipStr)) + if ip == nil { + return fmt.Errorf("invalid string being converted to IP address: %s", ipStr) + } + out = append(out, ip) + } + + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + + s.changed = true + + return nil +} + +// Type returns a string that uniquely represents this flag's type. +func (s *ipSliceValue) Type() string { + return "ipSlice" +} + +// String defines a "native" format for this net.IP slice flag value. +func (s *ipSliceValue) String() string { + + ipStrSlice := make([]string, len(*s.value)) + for i, ip := range *s.value { + ipStrSlice[i] = ip.String() + } + + out, _ := writeAsCSV(ipStrSlice) + + return "[" + out + "]" +} + +func ipSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Emtpy string would cause a slice with one (empty) entry + if len(val) == 0 { + return []net.IP{}, nil + } + ss := strings.Split(val, ",") + out := make([]net.IP, len(ss)) + for i, sval := range ss { + ip := net.ParseIP(strings.TrimSpace(sval)) + if ip == nil { + return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval) + } + out[i] = ip + } + return out, nil +} + +// GetIPSlice returns the []net.IP value of a flag with the given name +func (f *FlagSet) GetIPSlice(name string) ([]net.IP, error) { + val, err := f.getFlagType(name, "ipSlice", ipSliceConv) + if err != nil { + return []net.IP{}, err + } + return val.([]net.IP), nil +} + +// IPSliceVar defines a ipSlice flag with specified name, default value, and usage string. +// The argument p points to a []net.IP variable in which to store the value of the flag. +func (f *FlagSet) IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) { + f.VarP(newIPSliceValue(value, p), name, "", usage) +} + +// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) { + f.VarP(newIPSliceValue(value, p), name, shorthand, usage) +} + +// IPSliceVar defines a []net.IP flag with specified name, default value, and usage string. +// The argument p points to a []net.IP variable in which to store the value of the flag. +func IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) { + CommandLine.VarP(newIPSliceValue(value, p), name, "", usage) +} + +// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash. +func IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) { + CommandLine.VarP(newIPSliceValue(value, p), name, shorthand, usage) +} + +// IPSlice defines a []net.IP flag with specified name, default value, and usage string. +// The return value is the address of a []net.IP variable that stores the value of that flag. +func (f *FlagSet) IPSlice(name string, value []net.IP, usage string) *[]net.IP { + p := []net.IP{} + f.IPSliceVarP(&p, name, "", value, usage) + return &p +} + +// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP { + p := []net.IP{} + f.IPSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// IPSlice defines a []net.IP flag with specified name, default value, and usage string. +// The return value is the address of a []net.IP variable that stores the value of the flag. +func IPSlice(name string, value []net.IP, usage string) *[]net.IP { + return CommandLine.IPSliceP(name, "", value, usage) +} + +// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash. +func IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP { + return CommandLine.IPSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/ipmask.go b/vendor/github.com/spf13/pflag/ipmask.go new file mode 100644 index 0000000000..5bd44bd21d --- /dev/null +++ b/vendor/github.com/spf13/pflag/ipmask.go @@ -0,0 +1,122 @@ +package pflag + +import ( + "fmt" + "net" + "strconv" +) + +// -- net.IPMask value +type ipMaskValue net.IPMask + +func newIPMaskValue(val net.IPMask, p *net.IPMask) *ipMaskValue { + *p = val + return (*ipMaskValue)(p) +} + +func (i *ipMaskValue) String() string { return net.IPMask(*i).String() } +func (i *ipMaskValue) Set(s string) error { + ip := ParseIPv4Mask(s) + if ip == nil { + return fmt.Errorf("failed to parse IP mask: %q", s) + } + *i = ipMaskValue(ip) + return nil +} + +func (i *ipMaskValue) Type() string { + return "ipMask" +} + +// ParseIPv4Mask written in IP form (e.g. 255.255.255.0). +// This function should really belong to the net package. +func ParseIPv4Mask(s string) net.IPMask { + mask := net.ParseIP(s) + if mask == nil { + if len(s) != 8 { + return nil + } + // net.IPMask.String() actually outputs things like ffffff00 + // so write a horrible parser for that as well :-( + m := []int{} + for i := 0; i < 4; i++ { + b := "0x" + s[2*i:2*i+2] + d, err := strconv.ParseInt(b, 0, 0) + if err != nil { + return nil + } + m = append(m, int(d)) + } + s := fmt.Sprintf("%d.%d.%d.%d", m[0], m[1], m[2], m[3]) + mask = net.ParseIP(s) + if mask == nil { + return nil + } + } + return net.IPv4Mask(mask[12], mask[13], mask[14], mask[15]) +} + +func parseIPv4Mask(sval string) (interface{}, error) { + mask := ParseIPv4Mask(sval) + if mask == nil { + return nil, fmt.Errorf("unable to parse %s as net.IPMask", sval) + } + return mask, nil +} + +// GetIPv4Mask return the net.IPv4Mask value of a flag with the given name +func (f *FlagSet) GetIPv4Mask(name string) (net.IPMask, error) { + val, err := f.getFlagType(name, "ipMask", parseIPv4Mask) + if err != nil { + return nil, err + } + return val.(net.IPMask), nil +} + +// IPMaskVar defines an net.IPMask flag with specified name, default value, and usage string. +// The argument p points to an net.IPMask variable in which to store the value of the flag. +func (f *FlagSet) IPMaskVar(p *net.IPMask, name string, value net.IPMask, usage string) { + f.VarP(newIPMaskValue(value, p), name, "", usage) +} + +// IPMaskVarP is like IPMaskVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPMaskVarP(p *net.IPMask, name, shorthand string, value net.IPMask, usage string) { + f.VarP(newIPMaskValue(value, p), name, shorthand, usage) +} + +// IPMaskVar defines an net.IPMask flag with specified name, default value, and usage string. +// The argument p points to an net.IPMask variable in which to store the value of the flag. +func IPMaskVar(p *net.IPMask, name string, value net.IPMask, usage string) { + CommandLine.VarP(newIPMaskValue(value, p), name, "", usage) +} + +// IPMaskVarP is like IPMaskVar, but accepts a shorthand letter that can be used after a single dash. +func IPMaskVarP(p *net.IPMask, name, shorthand string, value net.IPMask, usage string) { + CommandLine.VarP(newIPMaskValue(value, p), name, shorthand, usage) +} + +// IPMask defines an net.IPMask flag with specified name, default value, and usage string. +// The return value is the address of an net.IPMask variable that stores the value of the flag. +func (f *FlagSet) IPMask(name string, value net.IPMask, usage string) *net.IPMask { + p := new(net.IPMask) + f.IPMaskVarP(p, name, "", value, usage) + return p +} + +// IPMaskP is like IPMask, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPMaskP(name, shorthand string, value net.IPMask, usage string) *net.IPMask { + p := new(net.IPMask) + f.IPMaskVarP(p, name, shorthand, value, usage) + return p +} + +// IPMask defines an net.IPMask flag with specified name, default value, and usage string. +// The return value is the address of an net.IPMask variable that stores the value of the flag. +func IPMask(name string, value net.IPMask, usage string) *net.IPMask { + return CommandLine.IPMaskP(name, "", value, usage) +} + +// IPMaskP is like IP, but accepts a shorthand letter that can be used after a single dash. +func IPMaskP(name, shorthand string, value net.IPMask, usage string) *net.IPMask { + return CommandLine.IPMaskP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/ipnet.go b/vendor/github.com/spf13/pflag/ipnet.go new file mode 100644 index 0000000000..e2c1b8bcd5 --- /dev/null +++ b/vendor/github.com/spf13/pflag/ipnet.go @@ -0,0 +1,98 @@ +package pflag + +import ( + "fmt" + "net" + "strings" +) + +// IPNet adapts net.IPNet for use as a flag. +type ipNetValue net.IPNet + +func (ipnet ipNetValue) String() string { + n := net.IPNet(ipnet) + return n.String() +} + +func (ipnet *ipNetValue) Set(value string) error { + _, n, err := net.ParseCIDR(strings.TrimSpace(value)) + if err != nil { + return err + } + *ipnet = ipNetValue(*n) + return nil +} + +func (*ipNetValue) Type() string { + return "ipNet" +} + +func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue { + *p = val + return (*ipNetValue)(p) +} + +func ipNetConv(sval string) (interface{}, error) { + _, n, err := net.ParseCIDR(strings.TrimSpace(sval)) + if err == nil { + return *n, nil + } + return nil, fmt.Errorf("invalid string being converted to IPNet: %s", sval) +} + +// GetIPNet return the net.IPNet value of a flag with the given name +func (f *FlagSet) GetIPNet(name string) (net.IPNet, error) { + val, err := f.getFlagType(name, "ipNet", ipNetConv) + if err != nil { + return net.IPNet{}, err + } + return val.(net.IPNet), nil +} + +// IPNetVar defines an net.IPNet flag with specified name, default value, and usage string. +// The argument p points to an net.IPNet variable in which to store the value of the flag. +func (f *FlagSet) IPNetVar(p *net.IPNet, name string, value net.IPNet, usage string) { + f.VarP(newIPNetValue(value, p), name, "", usage) +} + +// IPNetVarP is like IPNetVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPNetVarP(p *net.IPNet, name, shorthand string, value net.IPNet, usage string) { + f.VarP(newIPNetValue(value, p), name, shorthand, usage) +} + +// IPNetVar defines an net.IPNet flag with specified name, default value, and usage string. +// The argument p points to an net.IPNet variable in which to store the value of the flag. +func IPNetVar(p *net.IPNet, name string, value net.IPNet, usage string) { + CommandLine.VarP(newIPNetValue(value, p), name, "", usage) +} + +// IPNetVarP is like IPNetVar, but accepts a shorthand letter that can be used after a single dash. +func IPNetVarP(p *net.IPNet, name, shorthand string, value net.IPNet, usage string) { + CommandLine.VarP(newIPNetValue(value, p), name, shorthand, usage) +} + +// IPNet defines an net.IPNet flag with specified name, default value, and usage string. +// The return value is the address of an net.IPNet variable that stores the value of the flag. +func (f *FlagSet) IPNet(name string, value net.IPNet, usage string) *net.IPNet { + p := new(net.IPNet) + f.IPNetVarP(p, name, "", value, usage) + return p +} + +// IPNetP is like IPNet, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPNetP(name, shorthand string, value net.IPNet, usage string) *net.IPNet { + p := new(net.IPNet) + f.IPNetVarP(p, name, shorthand, value, usage) + return p +} + +// IPNet defines an net.IPNet flag with specified name, default value, and usage string. +// The return value is the address of an net.IPNet variable that stores the value of the flag. +func IPNet(name string, value net.IPNet, usage string) *net.IPNet { + return CommandLine.IPNetP(name, "", value, usage) +} + +// IPNetP is like IPNet, but accepts a shorthand letter that can be used after a single dash. +func IPNetP(name, shorthand string, value net.IPNet, usage string) *net.IPNet { + return CommandLine.IPNetP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/string.go b/vendor/github.com/spf13/pflag/string.go new file mode 100644 index 0000000000..04e0a26ff7 --- /dev/null +++ b/vendor/github.com/spf13/pflag/string.go @@ -0,0 +1,80 @@ +package pflag + +// -- string Value +type stringValue string + +func newStringValue(val string, p *string) *stringValue { + *p = val + return (*stringValue)(p) +} + +func (s *stringValue) Set(val string) error { + *s = stringValue(val) + return nil +} +func (s *stringValue) Type() string { + return "string" +} + +func (s *stringValue) String() string { return string(*s) } + +func stringConv(sval string) (interface{}, error) { + return sval, nil +} + +// GetString return the string value of a flag with the given name +func (f *FlagSet) GetString(name string) (string, error) { + val, err := f.getFlagType(name, "string", stringConv) + if err != nil { + return "", err + } + return val.(string), nil +} + +// StringVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a string variable in which to store the value of the flag. +func (f *FlagSet) StringVar(p *string, name string, value string, usage string) { + f.VarP(newStringValue(value, p), name, "", usage) +} + +// StringVarP is like StringVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringVarP(p *string, name, shorthand string, value string, usage string) { + f.VarP(newStringValue(value, p), name, shorthand, usage) +} + +// StringVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a string variable in which to store the value of the flag. +func StringVar(p *string, name string, value string, usage string) { + CommandLine.VarP(newStringValue(value, p), name, "", usage) +} + +// StringVarP is like StringVar, but accepts a shorthand letter that can be used after a single dash. +func StringVarP(p *string, name, shorthand string, value string, usage string) { + CommandLine.VarP(newStringValue(value, p), name, shorthand, usage) +} + +// String defines a string flag with specified name, default value, and usage string. +// The return value is the address of a string variable that stores the value of the flag. +func (f *FlagSet) String(name string, value string, usage string) *string { + p := new(string) + f.StringVarP(p, name, "", value, usage) + return p +} + +// StringP is like String, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringP(name, shorthand string, value string, usage string) *string { + p := new(string) + f.StringVarP(p, name, shorthand, value, usage) + return p +} + +// String defines a string flag with specified name, default value, and usage string. +// The return value is the address of a string variable that stores the value of the flag. +func String(name string, value string, usage string) *string { + return CommandLine.StringP(name, "", value, usage) +} + +// StringP is like String, but accepts a shorthand letter that can be used after a single dash. +func StringP(name, shorthand string, value string, usage string) *string { + return CommandLine.StringP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/string_array.go b/vendor/github.com/spf13/pflag/string_array.go new file mode 100644 index 0000000000..fa7bc60187 --- /dev/null +++ b/vendor/github.com/spf13/pflag/string_array.go @@ -0,0 +1,103 @@ +package pflag + +// -- stringArray Value +type stringArrayValue struct { + value *[]string + changed bool +} + +func newStringArrayValue(val []string, p *[]string) *stringArrayValue { + ssv := new(stringArrayValue) + ssv.value = p + *ssv.value = val + return ssv +} + +func (s *stringArrayValue) Set(val string) error { + if !s.changed { + *s.value = []string{val} + s.changed = true + } else { + *s.value = append(*s.value, val) + } + return nil +} + +func (s *stringArrayValue) Type() string { + return "stringArray" +} + +func (s *stringArrayValue) String() string { + str, _ := writeAsCSV(*s.value) + return "[" + str + "]" +} + +func stringArrayConv(sval string) (interface{}, error) { + sval = sval[1 : len(sval)-1] + // An empty string would cause a array with one (empty) string + if len(sval) == 0 { + return []string{}, nil + } + return readAsCSV(sval) +} + +// GetStringArray return the []string value of a flag with the given name +func (f *FlagSet) GetStringArray(name string) ([]string, error) { + val, err := f.getFlagType(name, "stringArray", stringArrayConv) + if err != nil { + return []string{}, err + } + return val.([]string), nil +} + +// StringArrayVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a []string variable in which to store the values of the multiple flags. +// The value of each argument will not try to be separated by comma. Use a StringSlice for that. +func (f *FlagSet) StringArrayVar(p *[]string, name string, value []string, usage string) { + f.VarP(newStringArrayValue(value, p), name, "", usage) +} + +// StringArrayVarP is like StringArrayVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringArrayVarP(p *[]string, name, shorthand string, value []string, usage string) { + f.VarP(newStringArrayValue(value, p), name, shorthand, usage) +} + +// StringArrayVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a []string variable in which to store the value of the flag. +// The value of each argument will not try to be separated by comma. Use a StringSlice for that. +func StringArrayVar(p *[]string, name string, value []string, usage string) { + CommandLine.VarP(newStringArrayValue(value, p), name, "", usage) +} + +// StringArrayVarP is like StringArrayVar, but accepts a shorthand letter that can be used after a single dash. +func StringArrayVarP(p *[]string, name, shorthand string, value []string, usage string) { + CommandLine.VarP(newStringArrayValue(value, p), name, shorthand, usage) +} + +// StringArray defines a string flag with specified name, default value, and usage string. +// The return value is the address of a []string variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma. Use a StringSlice for that. +func (f *FlagSet) StringArray(name string, value []string, usage string) *[]string { + p := []string{} + f.StringArrayVarP(&p, name, "", value, usage) + return &p +} + +// StringArrayP is like StringArray, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringArrayP(name, shorthand string, value []string, usage string) *[]string { + p := []string{} + f.StringArrayVarP(&p, name, shorthand, value, usage) + return &p +} + +// StringArray defines a string flag with specified name, default value, and usage string. +// The return value is the address of a []string variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma. Use a StringSlice for that. +func StringArray(name string, value []string, usage string) *[]string { + return CommandLine.StringArrayP(name, "", value, usage) +} + +// StringArrayP is like StringArray, but accepts a shorthand letter that can be used after a single dash. +func StringArrayP(name, shorthand string, value []string, usage string) *[]string { + return CommandLine.StringArrayP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/string_slice.go b/vendor/github.com/spf13/pflag/string_slice.go new file mode 100644 index 0000000000..0cd3ccc083 --- /dev/null +++ b/vendor/github.com/spf13/pflag/string_slice.go @@ -0,0 +1,149 @@ +package pflag + +import ( + "bytes" + "encoding/csv" + "strings" +) + +// -- stringSlice Value +type stringSliceValue struct { + value *[]string + changed bool +} + +func newStringSliceValue(val []string, p *[]string) *stringSliceValue { + ssv := new(stringSliceValue) + ssv.value = p + *ssv.value = val + return ssv +} + +func readAsCSV(val string) ([]string, error) { + if val == "" { + return []string{}, nil + } + stringReader := strings.NewReader(val) + csvReader := csv.NewReader(stringReader) + return csvReader.Read() +} + +func writeAsCSV(vals []string) (string, error) { + b := &bytes.Buffer{} + w := csv.NewWriter(b) + err := w.Write(vals) + if err != nil { + return "", err + } + w.Flush() + return strings.TrimSuffix(b.String(), "\n"), nil +} + +func (s *stringSliceValue) Set(val string) error { + v, err := readAsCSV(val) + if err != nil { + return err + } + if !s.changed { + *s.value = v + } else { + *s.value = append(*s.value, v...) + } + s.changed = true + return nil +} + +func (s *stringSliceValue) Type() string { + return "stringSlice" +} + +func (s *stringSliceValue) String() string { + str, _ := writeAsCSV(*s.value) + return "[" + str + "]" +} + +func stringSliceConv(sval string) (interface{}, error) { + sval = sval[1 : len(sval)-1] + // An empty string would cause a slice with one (empty) string + if len(sval) == 0 { + return []string{}, nil + } + return readAsCSV(sval) +} + +// GetStringSlice return the []string value of a flag with the given name +func (f *FlagSet) GetStringSlice(name string) ([]string, error) { + val, err := f.getFlagType(name, "stringSlice", stringSliceConv) + if err != nil { + return []string{}, err + } + return val.([]string), nil +} + +// StringSliceVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a []string variable in which to store the value of the flag. +// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. +// For example: +// --ss="v1,v2" -ss="v3" +// will result in +// []string{"v1", "v2", "v3"} +func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) { + f.VarP(newStringSliceValue(value, p), name, "", usage) +} + +// StringSliceVarP is like StringSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []string, usage string) { + f.VarP(newStringSliceValue(value, p), name, shorthand, usage) +} + +// StringSliceVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a []string variable in which to store the value of the flag. +// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. +// For example: +// --ss="v1,v2" -ss="v3" +// will result in +// []string{"v1", "v2", "v3"} +func StringSliceVar(p *[]string, name string, value []string, usage string) { + CommandLine.VarP(newStringSliceValue(value, p), name, "", usage) +} + +// StringSliceVarP is like StringSliceVar, but accepts a shorthand letter that can be used after a single dash. +func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage string) { + CommandLine.VarP(newStringSliceValue(value, p), name, shorthand, usage) +} + +// StringSlice defines a string flag with specified name, default value, and usage string. +// The return value is the address of a []string variable that stores the value of the flag. +// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. +// For example: +// --ss="v1,v2" -ss="v3" +// will result in +// []string{"v1", "v2", "v3"} +func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string { + p := []string{} + f.StringSliceVarP(&p, name, "", value, usage) + return &p +} + +// StringSliceP is like StringSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage string) *[]string { + p := []string{} + f.StringSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// StringSlice defines a string flag with specified name, default value, and usage string. +// The return value is the address of a []string variable that stores the value of the flag. +// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. +// For example: +// --ss="v1,v2" -ss="v3" +// will result in +// []string{"v1", "v2", "v3"} +func StringSlice(name string, value []string, usage string) *[]string { + return CommandLine.StringSliceP(name, "", value, usage) +} + +// StringSliceP is like StringSlice, but accepts a shorthand letter that can be used after a single dash. +func StringSliceP(name, shorthand string, value []string, usage string) *[]string { + return CommandLine.StringSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/string_to_int.go b/vendor/github.com/spf13/pflag/string_to_int.go new file mode 100644 index 0000000000..5ceda3965d --- /dev/null +++ b/vendor/github.com/spf13/pflag/string_to_int.go @@ -0,0 +1,149 @@ +package pflag + +import ( + "bytes" + "fmt" + "strconv" + "strings" +) + +// -- stringToInt Value +type stringToIntValue struct { + value *map[string]int + changed bool +} + +func newStringToIntValue(val map[string]int, p *map[string]int) *stringToIntValue { + ssv := new(stringToIntValue) + ssv.value = p + *ssv.value = val + return ssv +} + +// Format: a=1,b=2 +func (s *stringToIntValue) Set(val string) error { + ss := strings.Split(val, ",") + out := make(map[string]int, len(ss)) + for _, pair := range ss { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + return fmt.Errorf("%s must be formatted as key=value", pair) + } + var err error + out[kv[0]], err = strconv.Atoi(kv[1]) + if err != nil { + return err + } + } + if !s.changed { + *s.value = out + } else { + for k, v := range out { + (*s.value)[k] = v + } + } + s.changed = true + return nil +} + +func (s *stringToIntValue) Type() string { + return "stringToInt" +} + +func (s *stringToIntValue) String() string { + var buf bytes.Buffer + i := 0 + for k, v := range *s.value { + if i > 0 { + buf.WriteRune(',') + } + buf.WriteString(k) + buf.WriteRune('=') + buf.WriteString(strconv.Itoa(v)) + i++ + } + return "[" + buf.String() + "]" +} + +func stringToIntConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // An empty string would cause an empty map + if len(val) == 0 { + return map[string]int{}, nil + } + ss := strings.Split(val, ",") + out := make(map[string]int, len(ss)) + for _, pair := range ss { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + return nil, fmt.Errorf("%s must be formatted as key=value", pair) + } + var err error + out[kv[0]], err = strconv.Atoi(kv[1]) + if err != nil { + return nil, err + } + } + return out, nil +} + +// GetStringToInt return the map[string]int value of a flag with the given name +func (f *FlagSet) GetStringToInt(name string) (map[string]int, error) { + val, err := f.getFlagType(name, "stringToInt", stringToIntConv) + if err != nil { + return map[string]int{}, err + } + return val.(map[string]int), nil +} + +// StringToIntVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a map[string]int variable in which to store the values of the multiple flags. +// The value of each argument will not try to be separated by comma +func (f *FlagSet) StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) { + f.VarP(newStringToIntValue(value, p), name, "", usage) +} + +// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) { + f.VarP(newStringToIntValue(value, p), name, shorthand, usage) +} + +// StringToIntVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a map[string]int variable in which to store the value of the flag. +// The value of each argument will not try to be separated by comma +func StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) { + CommandLine.VarP(newStringToIntValue(value, p), name, "", usage) +} + +// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash. +func StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) { + CommandLine.VarP(newStringToIntValue(value, p), name, shorthand, usage) +} + +// StringToInt defines a string flag with specified name, default value, and usage string. +// The return value is the address of a map[string]int variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma +func (f *FlagSet) StringToInt(name string, value map[string]int, usage string) *map[string]int { + p := map[string]int{} + f.StringToIntVarP(&p, name, "", value, usage) + return &p +} + +// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int { + p := map[string]int{} + f.StringToIntVarP(&p, name, shorthand, value, usage) + return &p +} + +// StringToInt defines a string flag with specified name, default value, and usage string. +// The return value is the address of a map[string]int variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma +func StringToInt(name string, value map[string]int, usage string) *map[string]int { + return CommandLine.StringToIntP(name, "", value, usage) +} + +// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash. +func StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int { + return CommandLine.StringToIntP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/string_to_string.go b/vendor/github.com/spf13/pflag/string_to_string.go new file mode 100644 index 0000000000..890a01afc0 --- /dev/null +++ b/vendor/github.com/spf13/pflag/string_to_string.go @@ -0,0 +1,160 @@ +package pflag + +import ( + "bytes" + "encoding/csv" + "fmt" + "strings" +) + +// -- stringToString Value +type stringToStringValue struct { + value *map[string]string + changed bool +} + +func newStringToStringValue(val map[string]string, p *map[string]string) *stringToStringValue { + ssv := new(stringToStringValue) + ssv.value = p + *ssv.value = val + return ssv +} + +// Format: a=1,b=2 +func (s *stringToStringValue) Set(val string) error { + var ss []string + n := strings.Count(val, "=") + switch n { + case 0: + return fmt.Errorf("%s must be formatted as key=value", val) + case 1: + ss = append(ss, strings.Trim(val, `"`)) + default: + r := csv.NewReader(strings.NewReader(val)) + var err error + ss, err = r.Read() + if err != nil { + return err + } + } + + out := make(map[string]string, len(ss)) + for _, pair := range ss { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + return fmt.Errorf("%s must be formatted as key=value", pair) + } + out[kv[0]] = kv[1] + } + if !s.changed { + *s.value = out + } else { + for k, v := range out { + (*s.value)[k] = v + } + } + s.changed = true + return nil +} + +func (s *stringToStringValue) Type() string { + return "stringToString" +} + +func (s *stringToStringValue) String() string { + records := make([]string, 0, len(*s.value)>>1) + for k, v := range *s.value { + records = append(records, k+"="+v) + } + + var buf bytes.Buffer + w := csv.NewWriter(&buf) + if err := w.Write(records); err != nil { + panic(err) + } + w.Flush() + return "[" + strings.TrimSpace(buf.String()) + "]" +} + +func stringToStringConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // An empty string would cause an empty map + if len(val) == 0 { + return map[string]string{}, nil + } + r := csv.NewReader(strings.NewReader(val)) + ss, err := r.Read() + if err != nil { + return nil, err + } + out := make(map[string]string, len(ss)) + for _, pair := range ss { + kv := strings.SplitN(pair, "=", 2) + if len(kv) != 2 { + return nil, fmt.Errorf("%s must be formatted as key=value", pair) + } + out[kv[0]] = kv[1] + } + return out, nil +} + +// GetStringToString return the map[string]string value of a flag with the given name +func (f *FlagSet) GetStringToString(name string) (map[string]string, error) { + val, err := f.getFlagType(name, "stringToString", stringToStringConv) + if err != nil { + return map[string]string{}, err + } + return val.(map[string]string), nil +} + +// StringToStringVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a map[string]string variable in which to store the values of the multiple flags. +// The value of each argument will not try to be separated by comma +func (f *FlagSet) StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) { + f.VarP(newStringToStringValue(value, p), name, "", usage) +} + +// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) { + f.VarP(newStringToStringValue(value, p), name, shorthand, usage) +} + +// StringToStringVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a map[string]string variable in which to store the value of the flag. +// The value of each argument will not try to be separated by comma +func StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) { + CommandLine.VarP(newStringToStringValue(value, p), name, "", usage) +} + +// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash. +func StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) { + CommandLine.VarP(newStringToStringValue(value, p), name, shorthand, usage) +} + +// StringToString defines a string flag with specified name, default value, and usage string. +// The return value is the address of a map[string]string variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma +func (f *FlagSet) StringToString(name string, value map[string]string, usage string) *map[string]string { + p := map[string]string{} + f.StringToStringVarP(&p, name, "", value, usage) + return &p +} + +// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string { + p := map[string]string{} + f.StringToStringVarP(&p, name, shorthand, value, usage) + return &p +} + +// StringToString defines a string flag with specified name, default value, and usage string. +// The return value is the address of a map[string]string variable that stores the value of the flag. +// The value of each argument will not try to be separated by comma +func StringToString(name string, value map[string]string, usage string) *map[string]string { + return CommandLine.StringToStringP(name, "", value, usage) +} + +// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash. +func StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string { + return CommandLine.StringToStringP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/uint.go b/vendor/github.com/spf13/pflag/uint.go new file mode 100644 index 0000000000..dcbc2b758c --- /dev/null +++ b/vendor/github.com/spf13/pflag/uint.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- uint Value +type uintValue uint + +func newUintValue(val uint, p *uint) *uintValue { + *p = val + return (*uintValue)(p) +} + +func (i *uintValue) Set(s string) error { + v, err := strconv.ParseUint(s, 0, 64) + *i = uintValue(v) + return err +} + +func (i *uintValue) Type() string { + return "uint" +} + +func (i *uintValue) String() string { return strconv.FormatUint(uint64(*i), 10) } + +func uintConv(sval string) (interface{}, error) { + v, err := strconv.ParseUint(sval, 0, 0) + if err != nil { + return 0, err + } + return uint(v), nil +} + +// GetUint return the uint value of a flag with the given name +func (f *FlagSet) GetUint(name string) (uint, error) { + val, err := f.getFlagType(name, "uint", uintConv) + if err != nil { + return 0, err + } + return val.(uint), nil +} + +// UintVar defines a uint flag with specified name, default value, and usage string. +// The argument p points to a uint variable in which to store the value of the flag. +func (f *FlagSet) UintVar(p *uint, name string, value uint, usage string) { + f.VarP(newUintValue(value, p), name, "", usage) +} + +// UintVarP is like UintVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) UintVarP(p *uint, name, shorthand string, value uint, usage string) { + f.VarP(newUintValue(value, p), name, shorthand, usage) +} + +// UintVar defines a uint flag with specified name, default value, and usage string. +// The argument p points to a uint variable in which to store the value of the flag. +func UintVar(p *uint, name string, value uint, usage string) { + CommandLine.VarP(newUintValue(value, p), name, "", usage) +} + +// UintVarP is like UintVar, but accepts a shorthand letter that can be used after a single dash. +func UintVarP(p *uint, name, shorthand string, value uint, usage string) { + CommandLine.VarP(newUintValue(value, p), name, shorthand, usage) +} + +// Uint defines a uint flag with specified name, default value, and usage string. +// The return value is the address of a uint variable that stores the value of the flag. +func (f *FlagSet) Uint(name string, value uint, usage string) *uint { + p := new(uint) + f.UintVarP(p, name, "", value, usage) + return p +} + +// UintP is like Uint, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) UintP(name, shorthand string, value uint, usage string) *uint { + p := new(uint) + f.UintVarP(p, name, shorthand, value, usage) + return p +} + +// Uint defines a uint flag with specified name, default value, and usage string. +// The return value is the address of a uint variable that stores the value of the flag. +func Uint(name string, value uint, usage string) *uint { + return CommandLine.UintP(name, "", value, usage) +} + +// UintP is like Uint, but accepts a shorthand letter that can be used after a single dash. +func UintP(name, shorthand string, value uint, usage string) *uint { + return CommandLine.UintP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/uint16.go b/vendor/github.com/spf13/pflag/uint16.go new file mode 100644 index 0000000000..7e9914eddd --- /dev/null +++ b/vendor/github.com/spf13/pflag/uint16.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- uint16 value +type uint16Value uint16 + +func newUint16Value(val uint16, p *uint16) *uint16Value { + *p = val + return (*uint16Value)(p) +} + +func (i *uint16Value) Set(s string) error { + v, err := strconv.ParseUint(s, 0, 16) + *i = uint16Value(v) + return err +} + +func (i *uint16Value) Type() string { + return "uint16" +} + +func (i *uint16Value) String() string { return strconv.FormatUint(uint64(*i), 10) } + +func uint16Conv(sval string) (interface{}, error) { + v, err := strconv.ParseUint(sval, 0, 16) + if err != nil { + return 0, err + } + return uint16(v), nil +} + +// GetUint16 return the uint16 value of a flag with the given name +func (f *FlagSet) GetUint16(name string) (uint16, error) { + val, err := f.getFlagType(name, "uint16", uint16Conv) + if err != nil { + return 0, err + } + return val.(uint16), nil +} + +// Uint16Var defines a uint flag with specified name, default value, and usage string. +// The argument p points to a uint variable in which to store the value of the flag. +func (f *FlagSet) Uint16Var(p *uint16, name string, value uint16, usage string) { + f.VarP(newUint16Value(value, p), name, "", usage) +} + +// Uint16VarP is like Uint16Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint16VarP(p *uint16, name, shorthand string, value uint16, usage string) { + f.VarP(newUint16Value(value, p), name, shorthand, usage) +} + +// Uint16Var defines a uint flag with specified name, default value, and usage string. +// The argument p points to a uint variable in which to store the value of the flag. +func Uint16Var(p *uint16, name string, value uint16, usage string) { + CommandLine.VarP(newUint16Value(value, p), name, "", usage) +} + +// Uint16VarP is like Uint16Var, but accepts a shorthand letter that can be used after a single dash. +func Uint16VarP(p *uint16, name, shorthand string, value uint16, usage string) { + CommandLine.VarP(newUint16Value(value, p), name, shorthand, usage) +} + +// Uint16 defines a uint flag with specified name, default value, and usage string. +// The return value is the address of a uint variable that stores the value of the flag. +func (f *FlagSet) Uint16(name string, value uint16, usage string) *uint16 { + p := new(uint16) + f.Uint16VarP(p, name, "", value, usage) + return p +} + +// Uint16P is like Uint16, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint16P(name, shorthand string, value uint16, usage string) *uint16 { + p := new(uint16) + f.Uint16VarP(p, name, shorthand, value, usage) + return p +} + +// Uint16 defines a uint flag with specified name, default value, and usage string. +// The return value is the address of a uint variable that stores the value of the flag. +func Uint16(name string, value uint16, usage string) *uint16 { + return CommandLine.Uint16P(name, "", value, usage) +} + +// Uint16P is like Uint16, but accepts a shorthand letter that can be used after a single dash. +func Uint16P(name, shorthand string, value uint16, usage string) *uint16 { + return CommandLine.Uint16P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/uint32.go b/vendor/github.com/spf13/pflag/uint32.go new file mode 100644 index 0000000000..d8024539bf --- /dev/null +++ b/vendor/github.com/spf13/pflag/uint32.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- uint32 value +type uint32Value uint32 + +func newUint32Value(val uint32, p *uint32) *uint32Value { + *p = val + return (*uint32Value)(p) +} + +func (i *uint32Value) Set(s string) error { + v, err := strconv.ParseUint(s, 0, 32) + *i = uint32Value(v) + return err +} + +func (i *uint32Value) Type() string { + return "uint32" +} + +func (i *uint32Value) String() string { return strconv.FormatUint(uint64(*i), 10) } + +func uint32Conv(sval string) (interface{}, error) { + v, err := strconv.ParseUint(sval, 0, 32) + if err != nil { + return 0, err + } + return uint32(v), nil +} + +// GetUint32 return the uint32 value of a flag with the given name +func (f *FlagSet) GetUint32(name string) (uint32, error) { + val, err := f.getFlagType(name, "uint32", uint32Conv) + if err != nil { + return 0, err + } + return val.(uint32), nil +} + +// Uint32Var defines a uint32 flag with specified name, default value, and usage string. +// The argument p points to a uint32 variable in which to store the value of the flag. +func (f *FlagSet) Uint32Var(p *uint32, name string, value uint32, usage string) { + f.VarP(newUint32Value(value, p), name, "", usage) +} + +// Uint32VarP is like Uint32Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint32VarP(p *uint32, name, shorthand string, value uint32, usage string) { + f.VarP(newUint32Value(value, p), name, shorthand, usage) +} + +// Uint32Var defines a uint32 flag with specified name, default value, and usage string. +// The argument p points to a uint32 variable in which to store the value of the flag. +func Uint32Var(p *uint32, name string, value uint32, usage string) { + CommandLine.VarP(newUint32Value(value, p), name, "", usage) +} + +// Uint32VarP is like Uint32Var, but accepts a shorthand letter that can be used after a single dash. +func Uint32VarP(p *uint32, name, shorthand string, value uint32, usage string) { + CommandLine.VarP(newUint32Value(value, p), name, shorthand, usage) +} + +// Uint32 defines a uint32 flag with specified name, default value, and usage string. +// The return value is the address of a uint32 variable that stores the value of the flag. +func (f *FlagSet) Uint32(name string, value uint32, usage string) *uint32 { + p := new(uint32) + f.Uint32VarP(p, name, "", value, usage) + return p +} + +// Uint32P is like Uint32, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint32P(name, shorthand string, value uint32, usage string) *uint32 { + p := new(uint32) + f.Uint32VarP(p, name, shorthand, value, usage) + return p +} + +// Uint32 defines a uint32 flag with specified name, default value, and usage string. +// The return value is the address of a uint32 variable that stores the value of the flag. +func Uint32(name string, value uint32, usage string) *uint32 { + return CommandLine.Uint32P(name, "", value, usage) +} + +// Uint32P is like Uint32, but accepts a shorthand letter that can be used after a single dash. +func Uint32P(name, shorthand string, value uint32, usage string) *uint32 { + return CommandLine.Uint32P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/uint64.go b/vendor/github.com/spf13/pflag/uint64.go new file mode 100644 index 0000000000..f62240f2ce --- /dev/null +++ b/vendor/github.com/spf13/pflag/uint64.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- uint64 Value +type uint64Value uint64 + +func newUint64Value(val uint64, p *uint64) *uint64Value { + *p = val + return (*uint64Value)(p) +} + +func (i *uint64Value) Set(s string) error { + v, err := strconv.ParseUint(s, 0, 64) + *i = uint64Value(v) + return err +} + +func (i *uint64Value) Type() string { + return "uint64" +} + +func (i *uint64Value) String() string { return strconv.FormatUint(uint64(*i), 10) } + +func uint64Conv(sval string) (interface{}, error) { + v, err := strconv.ParseUint(sval, 0, 64) + if err != nil { + return 0, err + } + return uint64(v), nil +} + +// GetUint64 return the uint64 value of a flag with the given name +func (f *FlagSet) GetUint64(name string) (uint64, error) { + val, err := f.getFlagType(name, "uint64", uint64Conv) + if err != nil { + return 0, err + } + return val.(uint64), nil +} + +// Uint64Var defines a uint64 flag with specified name, default value, and usage string. +// The argument p points to a uint64 variable in which to store the value of the flag. +func (f *FlagSet) Uint64Var(p *uint64, name string, value uint64, usage string) { + f.VarP(newUint64Value(value, p), name, "", usage) +} + +// Uint64VarP is like Uint64Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint64VarP(p *uint64, name, shorthand string, value uint64, usage string) { + f.VarP(newUint64Value(value, p), name, shorthand, usage) +} + +// Uint64Var defines a uint64 flag with specified name, default value, and usage string. +// The argument p points to a uint64 variable in which to store the value of the flag. +func Uint64Var(p *uint64, name string, value uint64, usage string) { + CommandLine.VarP(newUint64Value(value, p), name, "", usage) +} + +// Uint64VarP is like Uint64Var, but accepts a shorthand letter that can be used after a single dash. +func Uint64VarP(p *uint64, name, shorthand string, value uint64, usage string) { + CommandLine.VarP(newUint64Value(value, p), name, shorthand, usage) +} + +// Uint64 defines a uint64 flag with specified name, default value, and usage string. +// The return value is the address of a uint64 variable that stores the value of the flag. +func (f *FlagSet) Uint64(name string, value uint64, usage string) *uint64 { + p := new(uint64) + f.Uint64VarP(p, name, "", value, usage) + return p +} + +// Uint64P is like Uint64, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint64P(name, shorthand string, value uint64, usage string) *uint64 { + p := new(uint64) + f.Uint64VarP(p, name, shorthand, value, usage) + return p +} + +// Uint64 defines a uint64 flag with specified name, default value, and usage string. +// The return value is the address of a uint64 variable that stores the value of the flag. +func Uint64(name string, value uint64, usage string) *uint64 { + return CommandLine.Uint64P(name, "", value, usage) +} + +// Uint64P is like Uint64, but accepts a shorthand letter that can be used after a single dash. +func Uint64P(name, shorthand string, value uint64, usage string) *uint64 { + return CommandLine.Uint64P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/uint8.go b/vendor/github.com/spf13/pflag/uint8.go new file mode 100644 index 0000000000..bb0e83c1f6 --- /dev/null +++ b/vendor/github.com/spf13/pflag/uint8.go @@ -0,0 +1,88 @@ +package pflag + +import "strconv" + +// -- uint8 Value +type uint8Value uint8 + +func newUint8Value(val uint8, p *uint8) *uint8Value { + *p = val + return (*uint8Value)(p) +} + +func (i *uint8Value) Set(s string) error { + v, err := strconv.ParseUint(s, 0, 8) + *i = uint8Value(v) + return err +} + +func (i *uint8Value) Type() string { + return "uint8" +} + +func (i *uint8Value) String() string { return strconv.FormatUint(uint64(*i), 10) } + +func uint8Conv(sval string) (interface{}, error) { + v, err := strconv.ParseUint(sval, 0, 8) + if err != nil { + return 0, err + } + return uint8(v), nil +} + +// GetUint8 return the uint8 value of a flag with the given name +func (f *FlagSet) GetUint8(name string) (uint8, error) { + val, err := f.getFlagType(name, "uint8", uint8Conv) + if err != nil { + return 0, err + } + return val.(uint8), nil +} + +// Uint8Var defines a uint8 flag with specified name, default value, and usage string. +// The argument p points to a uint8 variable in which to store the value of the flag. +func (f *FlagSet) Uint8Var(p *uint8, name string, value uint8, usage string) { + f.VarP(newUint8Value(value, p), name, "", usage) +} + +// Uint8VarP is like Uint8Var, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint8VarP(p *uint8, name, shorthand string, value uint8, usage string) { + f.VarP(newUint8Value(value, p), name, shorthand, usage) +} + +// Uint8Var defines a uint8 flag with specified name, default value, and usage string. +// The argument p points to a uint8 variable in which to store the value of the flag. +func Uint8Var(p *uint8, name string, value uint8, usage string) { + CommandLine.VarP(newUint8Value(value, p), name, "", usage) +} + +// Uint8VarP is like Uint8Var, but accepts a shorthand letter that can be used after a single dash. +func Uint8VarP(p *uint8, name, shorthand string, value uint8, usage string) { + CommandLine.VarP(newUint8Value(value, p), name, shorthand, usage) +} + +// Uint8 defines a uint8 flag with specified name, default value, and usage string. +// The return value is the address of a uint8 variable that stores the value of the flag. +func (f *FlagSet) Uint8(name string, value uint8, usage string) *uint8 { + p := new(uint8) + f.Uint8VarP(p, name, "", value, usage) + return p +} + +// Uint8P is like Uint8, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) Uint8P(name, shorthand string, value uint8, usage string) *uint8 { + p := new(uint8) + f.Uint8VarP(p, name, shorthand, value, usage) + return p +} + +// Uint8 defines a uint8 flag with specified name, default value, and usage string. +// The return value is the address of a uint8 variable that stores the value of the flag. +func Uint8(name string, value uint8, usage string) *uint8 { + return CommandLine.Uint8P(name, "", value, usage) +} + +// Uint8P is like Uint8, but accepts a shorthand letter that can be used after a single dash. +func Uint8P(name, shorthand string, value uint8, usage string) *uint8 { + return CommandLine.Uint8P(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/uint_slice.go b/vendor/github.com/spf13/pflag/uint_slice.go new file mode 100644 index 0000000000..edd94c600a --- /dev/null +++ b/vendor/github.com/spf13/pflag/uint_slice.go @@ -0,0 +1,126 @@ +package pflag + +import ( + "fmt" + "strconv" + "strings" +) + +// -- uintSlice Value +type uintSliceValue struct { + value *[]uint + changed bool +} + +func newUintSliceValue(val []uint, p *[]uint) *uintSliceValue { + uisv := new(uintSliceValue) + uisv.value = p + *uisv.value = val + return uisv +} + +func (s *uintSliceValue) Set(val string) error { + ss := strings.Split(val, ",") + out := make([]uint, len(ss)) + for i, d := range ss { + u, err := strconv.ParseUint(d, 10, 0) + if err != nil { + return err + } + out[i] = uint(u) + } + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + s.changed = true + return nil +} + +func (s *uintSliceValue) Type() string { + return "uintSlice" +} + +func (s *uintSliceValue) String() string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = fmt.Sprintf("%d", d) + } + return "[" + strings.Join(out, ",") + "]" +} + +func uintSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []uint{}, nil + } + ss := strings.Split(val, ",") + out := make([]uint, len(ss)) + for i, d := range ss { + u, err := strconv.ParseUint(d, 10, 0) + if err != nil { + return nil, err + } + out[i] = uint(u) + } + return out, nil +} + +// GetUintSlice returns the []uint value of a flag with the given name. +func (f *FlagSet) GetUintSlice(name string) ([]uint, error) { + val, err := f.getFlagType(name, "uintSlice", uintSliceConv) + if err != nil { + return []uint{}, err + } + return val.([]uint), nil +} + +// UintSliceVar defines a uintSlice flag with specified name, default value, and usage string. +// The argument p points to a []uint variable in which to store the value of the flag. +func (f *FlagSet) UintSliceVar(p *[]uint, name string, value []uint, usage string) { + f.VarP(newUintSliceValue(value, p), name, "", usage) +} + +// UintSliceVarP is like UintSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) { + f.VarP(newUintSliceValue(value, p), name, shorthand, usage) +} + +// UintSliceVar defines a uint[] flag with specified name, default value, and usage string. +// The argument p points to a uint[] variable in which to store the value of the flag. +func UintSliceVar(p *[]uint, name string, value []uint, usage string) { + CommandLine.VarP(newUintSliceValue(value, p), name, "", usage) +} + +// UintSliceVarP is like the UintSliceVar, but accepts a shorthand letter that can be used after a single dash. +func UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) { + CommandLine.VarP(newUintSliceValue(value, p), name, shorthand, usage) +} + +// UintSlice defines a []uint flag with specified name, default value, and usage string. +// The return value is the address of a []uint variable that stores the value of the flag. +func (f *FlagSet) UintSlice(name string, value []uint, usage string) *[]uint { + p := []uint{} + f.UintSliceVarP(&p, name, "", value, usage) + return &p +} + +// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) UintSliceP(name, shorthand string, value []uint, usage string) *[]uint { + p := []uint{} + f.UintSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// UintSlice defines a []uint flag with specified name, default value, and usage string. +// The return value is the address of a []uint variable that stores the value of the flag. +func UintSlice(name string, value []uint, usage string) *[]uint { + return CommandLine.UintSliceP(name, "", value, usage) +} + +// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash. +func UintSliceP(name, shorthand string, value []uint, usage string) *[]uint { + return CommandLine.UintSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/auth/credential.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/auth/credential.go new file mode 100644 index 0000000000..0e6dd99c24 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/auth/credential.go @@ -0,0 +1,45 @@ +package auth + +import ( + "crypto/sha1" + "encoding/hex" + "io" + "net/url" + "sort" + "strings" +) + +type Credential struct { + PublicKey string + PrivateKey string +} + +func (c *Credential) CreateSign(query string) string { + // replace "=" "&" + str := strings.Replace(query, "&", "", -1) + str = strings.Replace(str, "=", "", -1) + + // crypto by SHA1 + strUnescaped, _ := url.QueryUnescape(str) + h := sha1.New() + s := strUnescaped + c.PrivateKey + io.WriteString(h, s) + bs := h.Sum(nil) + result := hex.EncodeToString(bs) + + return result +} + +func (c *Credential) BuildCredentialedQuery(query map[string]string) string { + var queryList []string + for k, v := range query { + queryList = append(queryList, k+"="+url.QueryEscape(v)) + } + queryList = append(queryList, "PublicKey="+url.QueryEscape(c.PublicKey)) + sort.Strings(queryList) + queryString := strings.Join(queryList, "&") + + sign := c.CreateSign(queryString) + queryString = queryString + "&Signature=" + sign + return queryString +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/client.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/client.go new file mode 100644 index 0000000000..4982a880a0 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/client.go @@ -0,0 +1,278 @@ +package sdk + +import ( + "encoding/json" + "fmt" + "math/rand" + "net/http" + "net/url" + "runtime" + "time" + + "github.com/ucloud/ucloud-sdk-go/sdk/version" + + "github.com/ucloud/ucloud-sdk-go/sdk/response" + + "github.com/Sirupsen/logrus" + "github.com/parnurzeal/gorequest" + + "github.com/ucloud/ucloud-sdk-go/sdk/auth" + uerr "github.com/ucloud/ucloud-sdk-go/sdk/error" + "github.com/ucloud/ucloud-sdk-go/sdk/log" + "github.com/ucloud/ucloud-sdk-go/sdk/request" + utrace "github.com/ucloud/ucloud-sdk-go/sdk/trace" + "github.com/ucloud/ucloud-sdk-go/sdk/utils" +) + +type Client struct { + credential *auth.Credential + config *ClientConfig +} + +// NewClient will create an client of ucloud sdk +func NewClient(config *ClientConfig, credential *auth.Credential) *Client { + if config.MaxRetries == 0 { + config.MaxRetries = 3 + } + + if config.Timeout == 0 { + config.Timeout = 30 * time.Second + } + + if config.Logger == nil { + log.Init(config.LogLevel) + config.Logger = logrus.WithField("client", "sdk") + } + + if config.Tracer == nil { + tracer := utrace.NewDasTracer() + config.Tracer = &tracer + } + + if config.TracerData == nil { + config.TracerData = make(map[string]interface{}) + } + + if config.HTTPHeaders == nil { + config.HTTPHeaders = make(map[string]string) + } + + config.HTTPHeaders["User-Agent"] = fmt.Sprintf("GO/%s GO-SDK/%s %s", runtime.Version(), version.Version, config.UserAgent) + + return &Client{ + credential: credential, + config: config, + } +} + +// GetCredential will return the creadential config of client. +func (c *Client) GetCredential() *auth.Credential { + return c.credential +} + +// GetConfig will return the config of client. +func (c *Client) GetConfig() *ClientConfig { + return c.config +} + +// DoRequest will send a real http request to api endpoint with retry. +func (c *Client) DoRequest(req *request.HttpRequest, resp response.Common) error { + config := c.GetConfig() + r, err := c.buildSuperAgent(req) + if err != nil { + return err + } + + tracer := config.Tracer + + traceinfo := utrace.NewDasTraceInfo() + traceinfo.SetSDKRequest(req.Query) + + // temporary method, should use new version sdk + sendWithTracer := func(sendType string) (*http.Response, error) { + startTime := time.Now() + innerHttpResp, body, err := c.send(r, sendType) + endTime := time.Now() + + // Unmarshal response + err = json.Unmarshal(body, &resp) + if err != nil { + return nil, err + } + + traceinfo.SetSDKResponse(resp) + traceinfo.SetExtraData("startTime", startTime.UnixNano()/1e6) + traceinfo.SetExtraData("endTime", endTime.UnixNano()/1e6) + traceinfo.SetExtraData("durationTime", endTime.Sub(startTime).Nanoseconds()/1e6) + + for k, v := range config.TracerData { + traceinfo.SetExtraData(k, v) + } + + if tracer != nil { + err = tracer.Send(&traceinfo, c.config.HTTPHeaders) + if err != nil { + fmt.Println(err) + } + } + + return innerHttpResp, nil + } + + httpResp, err := sendWithTracer("Send") + + // exponential backoff delay, maximum 8 minute about. + cfg := c.GetConfig() + for retryCount := 1; utils.IsRetryableError(err) || (httpResp != nil && utils.IsRetryableHTTPStatusCode(httpResp.StatusCode)); retryCount++ { + if retryCount > cfg.MaxRetries { + break + } + + delay := getExpBackoffDelay(retryCount) + time.Sleep(delay) + + httpResp, err = sendWithTracer("Retry") + } + + if err != nil { + if utils.IsTimeoutError(err) { + return uerr.TimeoutError + } else { + return uerr.SendRequestError + } + } + + if utils.IsErrorHTTPStatusCode(httpResp.StatusCode) { + return uerr.SendRequestError + } + + return nil +} + +// InvokeAction will do an action request from a request struct and set response value into res struct pointer +func (c *Client) InvokeAction(action string, req request.Common, resp response.Common) error { + var err error + cfg := c.GetConfig() + defer logForAction(cfg.Logger, action, resp.(response.Common), &err) + + // Build query + query, err := utils.RequestToQuery(req) + if err != nil { + return err + } + + logrus.Infof("Request %#v", query) + + query["Action"] = action + if region := req.GetRegion(); err != nil && len(region) > 0 { + query["Region"] = region + } + if projectId := req.GetProjectId(); err != nil && len(projectId) > 0 { + query["ProjectId"] = projectId + } + + // Build request + httpReq := &request.HttpRequest{ + Url: cfg.BaseUrl, + Method: "GET", + Query: query, + } + + // Send request + err = c.DoRequest(httpReq, resp) + if err != nil { + return err + } + + return nil +} + +func (c *Client) buildSuperAgent(req *request.HttpRequest) (*gorequest.SuperAgent, error) { + config := c.GetConfig() + r := gorequest.New() + r.ClearSuperAgent() + + for k, v := range utils.MergeMap(DefaultHeaders, config.HTTPHeaders, req.Header) { + r.Set(k, v) + } + + goVersion := runtime.Version() + ua := fmt.Sprintf("GO/%s GO-SDK/%s", goVersion, version.Version) + if config.UserAgent != "" { + ua += " " + config.UserAgent + } + r.Set("User-Agent", ua) + + r.Method = req.Method + if !utils.IsAvaliableMethod(r.Method) { + logrus.Errorf("invalid method %s", r.Method) + return nil, uerr.InvalidRequestError + } + + r.Url = req.Url + _, err := url.ParseRequestURI(req.Url) + if err != nil { + logrus.Error(err) + return nil, uerr.InvalidRequestError + } + + if len(req.Content) != 0 { + r.Send(req.Content) + } + + r.Errors = nil + + credential := c.GetCredential() + if credential == nil { + logrus.Errorln("invalid credential infomation, please set it before request.") + return nil, uerr.InvalidRequestError + } + + cfg := c.GetConfig() + r.Timeout(cfg.Timeout) + + r.Query(credential.BuildCredentialedQuery(req.Query)) + return r, nil +} + +func (c *Client) send(r *gorequest.SuperAgent, reqType string) (gorequest.Response, []byte, error) { + var err error + logger := c.GetConfig().Logger.WithField("type", reqType) + + logger.Debugf("%s %s?%s", r.Method, r.Url, r.QueryData.Encode()) + + resp, body, errs := r.EndBytes() + + if len(errs) > 0 { + err = errs[0] + logger.Errorf("%T: %s", err, err) + } else if resp != nil && resp.StatusCode > 400 { + logger.Warnf("%s", resp.Status) + } else { + err = nil + logger.Debugf("%s - %v", body, resp.StatusCode) + } + + return resp, body, err +} + +func logForAction(logger logrus.FieldLogger, action string, resp response.Common, err *error) { + logger = logger.WithField("action", action) + if err != nil && *err != nil { + logger.Errorf("Do %s faild, %s", action, (*err).Error()) + } else if resp != nil && resp.GetRetCode() != 0 { + logger.Errorf("Do %s faild, %s", action, resp.GetMessage()) + } else { + logger.Infof("Do %s successful!", action) + } +} + +func getExpBackoffDelay(retryCount int) time.Duration { + minTime := 100 + if retryCount > 7 { + retryCount = 7 + } + + delay := (1 << (uint(retryCount) * 2)) * (rand.Intn(minTime) + minTime) + return time.Duration(delay) * time.Millisecond +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/config.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/config.go new file mode 100644 index 0000000000..18678c5397 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/config.go @@ -0,0 +1,56 @@ +package sdk + +import ( + "time" + + "github.com/Sirupsen/logrus" + + utrace "github.com/ucloud/ucloud-sdk-go/sdk/trace" +) + +type ClientConfig struct { + // Region is the region of backend service + // See also ... + Region string + + // ProjectId is the unique identify of project, used for organize resources, + // Most of resources should belong to a project. + // Sub-Account must have an project id. + // See also + ProjectId string + + // BaseUrl is the url of backend api + // See also ... + BaseUrl string + + // Logger and LogLevel is the configuration of logrus, + // if logger not be set, use standard output with json formatter as default, + // if logLevel not be set, use INFO level as default. + Logger logrus.FieldLogger + LogLevel logrus.Level + + // Timeout is timeout for every request. + Timeout time.Duration + + // Trace will invoke when any request is completed. + Tracer utrace.Tracer + TracerData map[string]interface{} + + // UserAgent is an attribute for sdk client, used for distinguish who using sdk. + // See also https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent + // It will append to the end of sdk user-agent. + // eg. "Terraform/0.10.1" -> "GO/1.9.1 GO-SDK/0.1.0 Terraform/0.10.1" + // warn. it will conflict with the User-Agent of HTTPHeaders + UserAgent string + + // HTTPHeaders is the specific headers sent to remote server via http protocal + // It is avaliabled when http protocal is enabled. + HTTPHeaders map[string]string + + // AutoRetry is a switch to enable retry policy for timeout/connect failing + // if AutoRetry is enabled, it will enable default retry policy using exponential backoff. + AutoRetry bool + + // MaxRetries is the number of max retry times. + MaxRetries int +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/defaults.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/defaults.go new file mode 100644 index 0000000000..40c423ffae --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/defaults.go @@ -0,0 +1,7 @@ +package sdk + +// DefaultHeaders defined default http headers +var DefaultHeaders = map[string]string{ + "Content-Type": "application/x-www-form-urlencoded", + // "X-SDK-VERSION": VERSION, +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/error/client_error.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/error/client_error.go new file mode 100644 index 0000000000..5e9a28d6ed --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/error/client_error.go @@ -0,0 +1,11 @@ +package error + +import ( + "errors" +) + +var ( + InvalidRequestError = errors.New("client.InvalidRequestError") + SendRequestError = errors.New("client.SendRequestError") + TimeoutError = errors.New("client.TimeoutError") +) diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/error/server_error.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/error/server_error.go new file mode 100644 index 0000000000..d32fcc57c3 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/error/server_error.go @@ -0,0 +1,9 @@ +package error + +import ( + "errors" +) + +var ( + InternalError = errors.New("server.InternalError") +) diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/log/logger.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/log/logger.go new file mode 100644 index 0000000000..6d35f53955 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/log/logger.go @@ -0,0 +1,13 @@ +package log + +import ( + "os" + + logrus "github.com/Sirupsen/logrus" +) + +func Init(level logrus.Level) { + logrus.SetFormatter(&logrus.JSONFormatter{}) + logrus.SetLevel(level) + logrus.SetOutput(os.Stdout) +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/request/common.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/request/common.go new file mode 100644 index 0000000000..4b82041186 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/request/common.go @@ -0,0 +1,35 @@ +package request + +type Common interface { + GetRegion() string + SetRegion(string) + + GetProjectId() string + SetProjectId(string) +} + +type CommonBase struct { + Region string + + ProjectId string +} + +// GetRegion will return region of request +func (c *CommonBase) GetRegion() string { + return c.Region +} + +// SetRegion will set region of request +func (c *CommonBase) SetRegion(region string) { + c.Region = region +} + +// GetProjectId will get project id of request +func (c *CommonBase) GetProjectId() string { + return c.ProjectId +} + +// SetProjectId will set project id of request +func (c *CommonBase) SetProjectId(projectId string) { + c.ProjectId = projectId +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/request/request.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/request/request.go new file mode 100644 index 0000000000..13af729fd0 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/request/request.go @@ -0,0 +1,17 @@ +package request + +const ( + HTTP_REQUEST_TYPE_MULTIPART = "multipart" + HTTP_REQUEST_TYPE_JSON = "json" + HTTP_REQUEST_TYPE_STRING = "string" +) + +type HttpRequest struct { + Url string + Type string + Method string + Query map[string]string + Header map[string]string + Form map[string]string + Content []byte +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/response/common.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/response/common.go new file mode 100644 index 0000000000..15a85dddc3 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/response/common.go @@ -0,0 +1,33 @@ +package response + +// Common describe a response of action, +// it is only used for ucloud open api v1 via HTTP GET and action parameters. +type Common interface { + GetRetCode() int + GetMessage() string + GetAction() string +} + +// CommonBase has common attribute and method, +// it also implement ActionResponse interface. +type CommonBase struct { + Action string + RetCode int + Message string +} + +// GetRetCode will return the error code of ucloud api +// Error is non-zero and succuess is zero +func (c *CommonBase) GetRetCode() int { + return c.RetCode +} + +// GetMessage will return the error message of ucloud api +func (c *CommonBase) GetMessage() string { + return c.Message +} + +// GetAction will return the request action of ucloud api +func (c *CommonBase) GetAction() string { + return c.Action +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/response/response.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/response/response.go new file mode 100644 index 0000000000..a5d6eabd12 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/response/response.go @@ -0,0 +1,5 @@ +package response + +// HttpResponse is a simple wrapper of "net/http" response +type HttpResponse struct { +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/das.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/das.go new file mode 100644 index 0000000000..25e55b322a --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/das.go @@ -0,0 +1,105 @@ +package trace + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + + "github.com/Sirupsen/logrus" + "github.com/pkg/errors" + + "github.com/satori/go.uuid" + + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +// DefaultDasURI is the default das api endpoint at internet. +const DefaultDasURI = "https://das-rpt.ucloud.cn/log" + +// DasTracer is a reporter to send traceback to remote trace system (named dasman) +type DasTracer struct { + URI string +} + +// NewDasTracer will create a new das tracer instance to send tracing report +func NewDasTracer() DasTracer { + return DasTracer{ + URI: DefaultDasURI, + } +} + +// Send will send trace information via a http(s)/tcp connection +func (d *DasTracer) Send(t TraceInfo, header map[string]string) error { + body, err := marshalTraceInfo(t) + if err != nil { + return err + } + client := &http.Client{} + req, err := http.NewRequest("POST", d.URI, bytes.NewReader(body)) + for key, value := range header { + req.Header.Add(key, value) + } + resp, err := client.Do(req) + + if err != nil { + fmt.Println(err) + return err + } + if resp.StatusCode != 200 { + return fmt.Errorf("invalid http status with tracer, %s", resp.Status) + } + return nil +} + +func marshalTraceInfo(t TraceInfo) ([]byte, error) { + // TODO: shouldn't use map, use new version sdk + query := t.GetSDKRequest().(map[string]string) + resp := t.GetSDKResponse().(response.Common) + extra := t.GetExtra() + + dataSet := make([]map[string]interface{}, 0) + dataItem := map[string]interface{}{ + "level": "info", //todo + "topic": "api", + "action": resp.GetAction(), + "command": extra["command"], + "error": extra["error"], + "req": query, + "res": map[string]interface{}{ + "Action": resp.GetAction(), + "RetCode": resp.GetRetCode(), + "Message": resp.GetMessage(), + }, + "st": extra["startTime"], + "rt": extra["endTime"], + "dt": extra["durationTime"], + } + + dataSet = append(dataSet, dataItem) + reqUUID := uuid.NewV4() + sessionID := uuid.NewV4() + payload := map[string]interface{}{ + "aid": "iywtleaa", + "uuid": reqUUID, + "sid": sessionID, + "cs": map[string]interface{}{ + "uname": extra["userName"], + // "cname": extra["companyName"], + }, + "ds": dataSet, + } + if action, ok := query["action"]; ok { + payload["action"] = action + } + + logrus.Infof("payload: %#v", payload) + marshaled, err := json.Marshal(payload) + if err != nil { + return nil, errors.Errorf("cannot to marshal traceinfo, %s", err) + } + for i := 0; i < len(marshaled); i++ { + marshaled[i] = ^marshaled[i] + } + return marshaled, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/iface.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/iface.go new file mode 100644 index 0000000000..7ddd1aa0ef --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/iface.go @@ -0,0 +1,25 @@ +package trace + +// TraceInfo is the detail information of sdk invoking. +type TraceInfo interface { + GetSDKVersion() string + + GetSDKRequest() interface{} + SetSDKRequest(data interface{}) error + + GetSDKResponse() interface{} + SetSDKResponse(data interface{}) error + + IsError() bool + SetError(error) error + + GetTraceback() []StacktraceFrame + + SetExtraData(key string, val interface{}) error + GetExtra() map[string]interface{} +} + +// Tracer is used to send trace information +type Tracer interface { + Send(TraceInfo, map[string]string) error +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/record.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/record.go new file mode 100644 index 0000000000..94c9377e6c --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/record.go @@ -0,0 +1,88 @@ +package trace + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/version" +) + +// DasTraceInfo is an implementation of DasTraceInfo +type DasTraceInfo struct { + SDKVersion string + Channel string + + request interface{} + response interface{} + + err error + traceback []*StacktraceFrame + extra map[string]interface{} +} + +// NewDasTraceInfo will create a new trace info struct with default information +func NewDasTraceInfo() DasTraceInfo { + return DasTraceInfo{ + Channel: "ucloud", + SDKVersion: version.Version, + extra: make(map[string]interface{}), + } +} + +// GetSDKVersion will return version of sdk +func (d *DasTraceInfo) GetSDKVersion() string { + return d.SDKVersion +} + +// GetSDKRequest will return sdk request data +func (d *DasTraceInfo) GetSDKRequest() interface{} { + return d.request +} + +// SetSDKRequest will set sdk request data +func (d *DasTraceInfo) SetSDKRequest(data interface{}) error { + d.request = data + return nil +} + +// GetSDKResponse will return sdk request data +func (d *DasTraceInfo) GetSDKResponse() interface{} { + return d.response +} + +// SetSDKResponse will set sdk request data +func (d *DasTraceInfo) SetSDKResponse(data interface{}) error { + d.response = data + return nil +} + +// IsError will return if this trace record is error +func (d *DasTraceInfo) IsError() bool { + return d.err != nil +} + +// SetError wil set record with error +// if the error has traceback, it will save traceback into this trace infomation record. +func (d *DasTraceInfo) SetError(err error) error { + // TODO: capture error with stacktrace + d.err = err + return nil +} + +// GetTraceback will return all frames of stacktrace +// See also "github.com/pkg/errors" +func (d *DasTraceInfo) GetTraceback() []StacktraceFrame { + return []StacktraceFrame{} +} + +// SetExtraData will set some extra data will be sent to remote server +func (d *DasTraceInfo) SetExtraData(key string, val interface{}) error { + if d.extra == nil { + d.extra = make(map[string]interface{}) + } + + d.extra[key] = val + return nil +} + +// GetExtra will get the key-value map of extra data +func (d *DasTraceInfo) GetExtra() map[string]interface{} { + return d.extra +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/stack.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/stack.go new file mode 100644 index 0000000000..842f1bd598 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/trace/stack.go @@ -0,0 +1,24 @@ +package trace + +// Stacktrace is record of golang stacktrack +type Stacktrace struct { + Frames []*StacktraceFrame `json:"frames"` +} + +// StacktraceFrame is the frame of stacktrace record by "github.com/pkg/errors" +// This stack is also same as "raven-go" +type StacktraceFrame struct { + // At least one required + Filename string `json:"filename,omitempty"` + Function string `json:"function,omitempty"` + Module string `json:"module,omitempty"` + + // Optional + Lineno int `json:"lineno,omitempty"` + Colno int `json:"colno,omitempty"` + AbsolutePath string `json:"abs_path,omitempty"` + ContextLine string `json:"context_line,omitempty"` + PreContext []string `json:"pre_context,omitempty"` + PostContext []string `json:"post_context,omitempty"` + InApp bool `json:"in_app"` +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/collection.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/collection.go new file mode 100644 index 0000000000..effc9df1c5 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/collection.go @@ -0,0 +1,19 @@ +package utils + +// MergeMap will merge two map and return a new map +func MergeMap(args ...map[string]string) map[string]string { + m := map[string]string{} + for _, kv := range args { + for k, v := range kv { + m[k] = v + } + } + return m +} + +// SetMapIfNotExists will set a +func SetMapIfNotExists(m map[string]string, k string, v string) { + if _, ok := m[k]; !ok && v != "" { + m[k] = v + } +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/encoder.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/encoder.go new file mode 100644 index 0000000000..b8b34e2a46 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/encoder.go @@ -0,0 +1,153 @@ +package utils + +import ( + "errors" + "fmt" + "reflect" + "strconv" +) + +const NIL = "nil" + +// StructEncoder convert struct to map[string][string] +// Only allowed 1-layer struct, no recursive +type StructEncoder struct { + IsZeroValueOmitted bool +} + +func NewStructEncoder(isZeroValueOmitted bool) *StructEncoder { + return &StructEncoder{ + IsZeroValueOmitted: isZeroValueOmitted, + } +} + +func (e *StructEncoder) encodeInt(v *reflect.Value) (string, error) { + realV := v.Int() + if e.IsZeroValueOmitted && IsZeroValue(realV) { + return NIL, nil + } + return strconv.FormatInt(realV, 10), nil +} + +func (e *StructEncoder) encodeUint(v *reflect.Value) (string, error) { + realV := v.Uint() + if e.IsZeroValueOmitted && IsZeroValue(realV) { + return NIL, nil + } + return strconv.FormatUint(realV, 10), nil +} + +func (e *StructEncoder) encodeBool(v *reflect.Value) (string, error) { + realV := v.Bool() + if e.IsZeroValueOmitted && IsZeroValue(realV) { + return NIL, nil + } + return strconv.FormatBool(realV), nil +} + +func (e *StructEncoder) encodeString(v *reflect.Value) (string, error) { + realV := v.String() + if e.IsZeroValueOmitted && IsZeroValue(realV) { + return NIL, nil + } + return realV, nil +} + +func (e *StructEncoder) encodeFloat(v *reflect.Value) (string, error) { + realV := v.Float() + if e.IsZeroValueOmitted && IsZeroValue(realV) { + return NIL, nil + } + return strconv.FormatFloat(realV, 'E', -1, 64), nil +} + +func (e *StructEncoder) encodeInterface(v *reflect.Value) (string, error) { + // TODO: ... + return NIL, nil +} + +func (e *StructEncoder) encodeArray(v *reflect.Value) ([]string, error) { + result := make([]string, v.Len()) + for i := 0; i < v.Len(); i++ { + item := v.Index(i) + + encoded, err := e.encodeBuiltin(&item) + if err != nil { + return make([]string, 0), err + } + + result[i] = encoded + } + return result, nil +} + +func (e *StructEncoder) encodeBuiltin(v *reflect.Value) (string, error) { + switch v.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return e.encodeInt(v) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32: + return e.encodeUint(v) + case reflect.Float32, reflect.Float64: + return e.encodeFloat(v) + case reflect.Bool: + return e.encodeBool(v) + case reflect.String: + return e.encodeString(v) + case reflect.Ptr: + ptrValue := v.Elem() + return e.encodeBuiltin(&ptrValue) + default: + return "", errors.New(fmt.Sprintf("Invalid variable type, type must be one of int-, uint-, float-, bool, string and ptr, got %s", v.Kind().String())) + } +} + +func (e *StructEncoder) encode(v *reflect.Value) (map[string]string, error) { + result := make(map[string]string) + + for i := 0; i < v.NumField(); i++ { + f := v.Field(i) + name := v.Type().Field(i).Name + + switch f.Kind() { + case reflect.Slice, reflect.Array: + encodedArray, err := e.encodeArray(&f) + if err != nil { + return result, err + } + + for index, encoded := range encodedArray { + if len(encoded) > 0 { + result[fmt.Sprintf("%s.%v", name, index)] = encoded + } + } + case reflect.Interface: + // TODO: implement ISO8601/RFC3339 like ucloudgo + continue + case reflect.Struct: + // resolve composite common struct + for i := 0; i < f.NumField(); i++ { + composited := f.Field(i) + name := f.Type().Field(i).Name + + encoded, err := e.encodeBuiltin(&composited) + if err != nil { + return result, err + } + + if encoded != NIL { + result[name] = encoded + } + } + default: + encoded, err := e.encodeBuiltin(&f) + if err != nil { + return result, err + } + + if encoded != NIL { + result[name] = encoded + } + } + } + return result, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/request.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/request.go new file mode 100644 index 0000000000..7f3490f9e1 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/request.go @@ -0,0 +1,27 @@ +package utils + +import ( + "reflect" + + "github.com/Sirupsen/logrus" + + uerr "github.com/ucloud/ucloud-sdk-go/sdk/error" +) + +// RequestToQuery used to convert an request struct to query +func RequestToQuery(req interface{}) (map[string]string, error) { + vReq := reflect.ValueOf(req) + if vReq.Kind() != reflect.Ptr { + logrus.Errorf("Request has type %s, want struct pointer.", vReq.Kind().String()) + return make(map[string]string), uerr.InvalidRequestError + } + + v := vReq.Elem() + if v.Kind() != reflect.Struct { + logrus.Errorf("Request has type %s, want struct pointer.", vReq.Kind().String()) + return make(map[string]string), uerr.InvalidRequestError + } + + encoder := NewStructEncoder(true) + return encoder.encode(&v) +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/style.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/style.go new file mode 100644 index 0000000000..066b90ae3a --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/style.go @@ -0,0 +1,35 @@ +package utils + +import "unicode" + +// CamelToUnderscore will convert camel style naming to underscore style +func CamelToUnderscore(s string) string { + r := "" + var prev rune + for _, c := range s { + if unicode.IsLower(prev) && unicode.IsUpper(c) { + r += "_" + } + r += string(unicode.ToLower(c)) + prev = c + } + return r +} + +// UnderscoreToCamel will convert underscore style naming to camel style +func UnderscoreToCamel(s string) string { + r := "" + for i := 0; i < len(s); i++ { + c := s[i] + if c == '_' { + i++ // Skip the underscore + if i < len(s) { + r += string(unicode.ToUpper(rune(s[i]))) + } + continue + } + + r += string(c) + } + return r +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/validator.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/validator.go new file mode 100644 index 0000000000..97dcb68548 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/validator.go @@ -0,0 +1,90 @@ +package utils + +import ( + "fmt" + "net" + "strings" +) + +var avaliableHTTPMethod = []string{"GET", "POST", "PUT", "DELETE", "OPTION", "HEAD", "PATCH"} + +// IsAvaliableMethod will check if a string is an avaliable http method. +func IsAvaliableMethod(method string) bool { + for _, m := range avaliableHTTPMethod { + if m == strings.ToUpper(method) { + return true + } + } + return false +} + +// IsZeroValue will check any value if it is a zero value of it't type. +func IsZeroValue(expr interface{}) bool { + if expr == nil { + return true + } + + switch v := expr.(type) { + case bool: + return false + case string: + return len(v) == 0 + case []byte: + return len(v) == 0 + case int: + return v == int(0) + case int32: + return v == int32(0) + case int64: + return v == int64(0) + case uint: + return v == uint(0) + case uint32: + return v == uint32(0) + case uint64: + return v == uint64(0) + case float32: + return v == float32(0.0) + case float64: + return v == float64(0.0) + default: + panic(fmt.Sprintf("unexpected type %T: %v", v, v)) + } +} + +// IsErrorHTTPStatusCode will check a http status is error +func IsErrorHTTPStatusCode(code int) bool { + if 400 <= code && code < 600 { + return true + } + return false +} + +// IsRetryableHTTPStatusCode will check a http status is retryable +func IsRetryableHTTPStatusCode(code int) bool { + retryableCodes := [...]int{429, 502, 503, 504} + for _, retryableCode := range retryableCodes { + if code == retryableCode { + return true + } + } + return false +} + +// IsTimeoutError will check if the error raise from network timeout +func IsTimeoutError(err error) bool { + if err == nil { + return false + } + netError, isNetError := err.(net.Error) + return isNetError && netError.Timeout() +} + +// IsRetryableError will check if the error is retryable +func IsRetryableError(err error) bool { + if err == nil { + return false + } + _, isNetError := err.(net.Error) + return isNetError +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/waiter.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/waiter.go new file mode 100644 index 0000000000..a32c159e2f --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/utils/waiter.go @@ -0,0 +1,53 @@ +package utils + +import ( + "errors" + "time" + + "github.com/Sirupsen/logrus" +) + +// Waiter to wait sth until it completed. +type Waiter interface { + WaitForCompletion() error + Cancel() error +} + +// FuncWaiter used for waiting any condition function. +type FuncWaiter struct { + Interval time.Duration + MaxAttempts int + Checker func() (bool, error) + IgnoreError bool + + cancel chan struct{} +} + +// WaitForCompletion will wait until the state of consdition is avaliable. +// It will call the condition function to ensure state with interval. +func (w *FuncWaiter) WaitForCompletion() error { + for i := 0; ; i++ { + logrus.Infof("Waiting for completion ... attempted %v times, %v total", i, w.MaxAttempts) + + if i >= w.MaxAttempts { + return errors.New("maximum attemps are reached") + } + + if ok, err := w.Checker(); ok || (!w.IgnoreError && err != nil) { + return err + } + + select { + case <-time.After(w.Interval): + continue + case <-w.cancel: + break + } + } +} + +// Cancel will stop all of WaitForCompletion function call. +func (w *FuncWaiter) Cancel() error { + w.cancel <- struct{}{} + return nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/version.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/version.go new file mode 100644 index 0000000000..17a5c671ad --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/version.go @@ -0,0 +1,5 @@ +package sdk + +// VERSION is the version of sdk +// See also semantic version: https://semver.org/ +const VERSION = "1.0.0" diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/sdk/version/version.go b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/version/version.go new file mode 100644 index 0000000000..091dc30eaa --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/sdk/version/version.go @@ -0,0 +1,5 @@ +package version + +// Version is the version of sdk +// See also semantic version: https://semver.org/ +const Version = "0.1.0" diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/client.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/client.go new file mode 100644 index 0000000000..b7117d7bdf --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/client.go @@ -0,0 +1,42 @@ +package service + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk" + "github.com/ucloud/ucloud-sdk-go/sdk/auth" + "github.com/ucloud/ucloud-sdk-go/service/pathx" + "github.com/ucloud/ucloud-sdk-go/service/uaccount" + "github.com/ucloud/ucloud-sdk-go/service/uhost" + "github.com/ucloud/ucloud-sdk-go/service/ulb" + "github.com/ucloud/ucloud-sdk-go/service/unet" + "github.com/ucloud/ucloud-sdk-go/service/vpc" +) + +type Client struct { + uaccount.UAccountClient + + uhost.UHostClient + + unet.UNetClient + + ulb.ULBClient + + vpc.VPCClient + + pathx.PathXClient +} + +func NewClient(config *sdk.ClientConfig, credential *auth.Credential) *Client { + return &Client{ + *uaccount.NewClient(config, credential), + + *uhost.NewClient(config, credential), + + *unet.NewClient(config, credential), + + *ulb.NewClient(config, credential), + + *vpc.NewClient(config, credential), + + *pathx.NewClient(config, credential), + } +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/client.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/client.go new file mode 100644 index 0000000000..01246ed100 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/client.go @@ -0,0 +1,17 @@ +package pathx + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk" + "github.com/ucloud/ucloud-sdk-go/sdk/auth" +) + +type PathXClient struct { + client *sdk.Client +} + +func NewClient(config *sdk.ClientConfig, credential *auth.Credential) *PathXClient { + client := sdk.NewClient(config, credential) + return &PathXClient{ + client: client, + } +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/create_global_sshinstance.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/create_global_sshinstance.go new file mode 100644 index 0000000000..dcad893edb --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/create_global_sshinstance.go @@ -0,0 +1,68 @@ +//go:generate go run ../../private/cli/gen-api/main.go pathx CreateGlobalSSHInstance + +package pathx + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type CreateGlobalSSHInstanceRequest struct { + request.CommonBase + + // Required, 填写支持SSH访问IP的地区名称,如“洛杉矶”,“新加坡”,“香港”,“东京”,“华盛顿” + Area string + + // Required, 被SSH访问的IP + TargetIP string + + // Required, SSH端口,禁止使用80,443等端口 + Port string + + // Optional, 备注信息 + Remark string + + // Optional, 支付方式,如按月、按年、按时 + ChargeType string + + // Optional, 购买数量 + Quantity string + + // Optional, 使用代金券可冲抵部分费用 + CouponId string +} + +type CreateGlobalSSHInstanceResponse struct { + response.CommonBase + + // 实例ID,资源唯一标识 + InstanceId string + + // 加速域名,访问该域名可就近接入 + AcceleratingDomain string +} + +// NewCreateGlobalSSHInstanceRequest will create request of CreateGlobalSSHInstance action. +func (c *PathXClient) NewCreateGlobalSSHInstanceRequest() *CreateGlobalSSHInstanceRequest { + cfg := c.client.GetConfig() + + return &CreateGlobalSSHInstanceRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// CreateGlobalSSHInstance - 创建GlobalSSH实例 +func (c *PathXClient) CreateGlobalSSHInstance(req *CreateGlobalSSHInstanceRequest) (*CreateGlobalSSHInstanceResponse, error) { + var err error + var res CreateGlobalSSHInstanceResponse + + err = c.client.InvokeAction("CreateGlobalSSHInstance", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/delete_global_sshinstance.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/delete_global_sshinstance.go new file mode 100644 index 0000000000..6db3c155f6 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/delete_global_sshinstance.go @@ -0,0 +1,44 @@ +//go:generate go run ../../private/cli/gen-api/main.go pathx DeleteGlobalSSHInstance + +package pathx + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type DeleteGlobalSSHInstanceRequest struct { + request.CommonBase + + // Required, 实例Id,资源的唯一标识 + InstanceId string +} + +type DeleteGlobalSSHInstanceResponse struct { + response.CommonBase +} + +// NewDeleteGlobalSSHInstanceRequest will create request of DeleteGlobalSSHInstance action. +func (c *PathXClient) NewDeleteGlobalSSHInstanceRequest() *DeleteGlobalSSHInstanceRequest { + cfg := c.client.GetConfig() + + return &DeleteGlobalSSHInstanceRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DeleteGlobalSSHInstance - 删除GlobalSSH实例 +func (c *PathXClient) DeleteGlobalSSHInstance(req *DeleteGlobalSSHInstanceRequest) (*DeleteGlobalSSHInstanceResponse, error) { + var err error + var res DeleteGlobalSSHInstanceResponse + + err = c.client.InvokeAction("DeleteGlobalSSHInstance", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/describe_global_sshinstance.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/describe_global_sshinstance.go new file mode 100644 index 0000000000..f6c7cca25c --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/describe_global_sshinstance.go @@ -0,0 +1,48 @@ +//go:generate go run ../../private/cli/gen-api/main.go pathx DescribeGlobalSSHInstance + +package pathx + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" + . "github.com/ucloud/ucloud-sdk-go/service/pathx/types" +) + +type DescribeGlobalSSHInstanceRequest struct { + request.CommonBase + + // Optional, 实例ID,资源唯一标识 + InstanceId string +} + +type DescribeGlobalSSHInstanceResponse struct { + response.CommonBase + + // GlobalSSH实例列表,实例的属性参考GlobalSSHInfo模型 + InstanceSet []GlobalSSHInfo +} + +// NewDescribeGlobalSSHInstanceRequest will create request of DescribeGlobalSSHInstance action. +func (c *PathXClient) NewDescribeGlobalSSHInstanceRequest() *DescribeGlobalSSHInstanceRequest { + cfg := c.client.GetConfig() + + return &DescribeGlobalSSHInstanceRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DescribeGlobalSSHInstance - 获取GlobalSSH实例列表(传实例ID获取单个实例信息,不传获取项目下全部实例) +func (c *PathXClient) DescribeGlobalSSHInstance(req *DescribeGlobalSSHInstanceRequest) (*DescribeGlobalSSHInstanceResponse, error) { + var err error + var res DescribeGlobalSSHInstanceResponse + + err = c.client.InvokeAction("DescribeGlobalSSHInstance", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/doc.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/doc.go new file mode 100644 index 0000000000..3ed3fc692a --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/doc.go @@ -0,0 +1,11 @@ +/* + Package uhost include resources of ucloud host product + + See also + + - API: https://docs.ucloud.cn/api/pathx-api/index + - Product: https://www.ucloud.cn/site/product/pathx.html + + for detail. +*/ +package pathx diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/modify_global_sshport.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/modify_global_sshport.go new file mode 100644 index 0000000000..d59c1c2c9e --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/modify_global_sshport.go @@ -0,0 +1,47 @@ +//go:generate go run ../../private/cli/gen-api/main.go pathx ModifyGlobalSSHPort + +package pathx + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type ModifyGlobalSSHPortRequest struct { + request.CommonBase + + // Required, 实例ID,资源唯一标识 + InstanceId string + + // Required, 调整后的SSH登陆端口 + Port string +} + +type ModifyGlobalSSHPortResponse struct { + response.CommonBase +} + +// NewModifyGlobalSSHPortRequest will create request of ModifyGlobalSSHPort action. +func (c *PathXClient) NewModifyGlobalSSHPortRequest() *ModifyGlobalSSHPortRequest { + cfg := c.client.GetConfig() + + return &ModifyGlobalSSHPortRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// ModifyGlobalSSHPort - 修改GlobalSSH端口 +func (c *PathXClient) ModifyGlobalSSHPort(req *ModifyGlobalSSHPortRequest) (*ModifyGlobalSSHPortResponse, error) { + var err error + var res ModifyGlobalSSHPortResponse + + err = c.client.InvokeAction("ModifyGlobalSSHPort", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/modify_global_sshremark.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/modify_global_sshremark.go new file mode 100644 index 0000000000..b0dbc1d5b5 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/modify_global_sshremark.go @@ -0,0 +1,47 @@ +//go:generate go run ../../private/cli/gen-api/main.go pathx ModifyGlobalSSHRemark + +package pathx + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type ModifyGlobalSSHRemarkRequest struct { + request.CommonBase + + // Required, 实例ID,资源唯一标识 + InstanceId string + + // Optional, 备注信息,不填默认为空字符串 + Remark string +} + +type ModifyGlobalSSHRemarkResponse struct { + response.CommonBase +} + +// NewModifyGlobalSSHRemarkRequest will create request of ModifyGlobalSSHRemark action. +func (c *PathXClient) NewModifyGlobalSSHRemarkRequest() *ModifyGlobalSSHRemarkRequest { + cfg := c.client.GetConfig() + + return &ModifyGlobalSSHRemarkRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// ModifyGlobalSSHRemark - 修改GlobalSSH备注 +func (c *PathXClient) ModifyGlobalSSHRemark(req *ModifyGlobalSSHRemarkRequest) (*ModifyGlobalSSHRemarkResponse, error) { + var err error + var res ModifyGlobalSSHRemarkResponse + + err = c.client.InvokeAction("ModifyGlobalSSHRemark", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/types/global_sshinfo.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/types/global_sshinfo.go new file mode 100644 index 0000000000..e3266ad671 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/pathx/types/global_sshinfo.go @@ -0,0 +1,32 @@ +package types + +// GlobalSSHInfo - GlobalSSH实例信息 +type GlobalSSHInfo struct { + + // 实例ID,资源唯一标识 + InstanceId string + + // 加速域名 + AcceleratingDomain string + + // 被SSH访问的IP所在地区 + Area string + + // 被SSH访问的EIP + TargetIP string + + // 备注信息 + Remark string + + // SSH登陆端口 + Port int + + // 支付周期,如Month,Year等 + ChargeType string + + // 资源创建时间戳 + CreateTime int + + // 资源过期时间戳 + ExpireTime int +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/client.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/client.go new file mode 100644 index 0000000000..ac86f5fa16 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/client.go @@ -0,0 +1,17 @@ +package uaccount + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk" + "github.com/ucloud/ucloud-sdk-go/sdk/auth" +) + +type UAccountClient struct { + client *sdk.Client +} + +func NewClient(config *sdk.ClientConfig, credential *auth.Credential) *UAccountClient { + client := sdk.NewClient(config, credential) + return &UAccountClient{ + client: client, + } +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/doc.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/doc.go new file mode 100644 index 0000000000..7b104998a9 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/doc.go @@ -0,0 +1,11 @@ +/* + Package uhost include resources of ucloud host product + + See also + + - API: https://docs.ucloud.cn/api/uaccount-api/index + - Product: https://www.ucloud.cn/site/product/uaccount.html + + for detail. +*/ +package uaccount diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/get_project_list.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/get_project_list.go new file mode 100644 index 0000000000..5994613cff --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/get_project_list.go @@ -0,0 +1,51 @@ +//go:generate go run ../../private/cli/gen-api/main.go uaccount GetProjectList + +package uaccount + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" + . "github.com/ucloud/ucloud-sdk-go/service/uaccount/types" +) + +type GetProjectListRequest struct { + request.CommonBase + + // Optional, 是否是财务账号(Yes: 是, No: 否) + IsFinance string +} + +type GetProjectListResponse struct { + response.CommonBase + + // 项目总数 + ProjectCount int + + // JSON格式的项目列表实例 + ProjectSet []ProjectListInfo +} + +// NewGetProjectListRequest will create request of GetProjectList action. +func (c *UAccountClient) NewGetProjectListRequest() *GetProjectListRequest { + cfg := c.client.GetConfig() + + return &GetProjectListRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// GetProjectList - 获取项目列表 +func (c *UAccountClient) GetProjectList(req *GetProjectListRequest) (*GetProjectListResponse, error) { + var err error + var res GetProjectListResponse + + err = c.client.InvokeAction("GetProjectList", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/get_region.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/get_region.go new file mode 100644 index 0000000000..9c2f688eb0 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/get_region.go @@ -0,0 +1,45 @@ +//go:generate go run ../../private/cli/gen-api/main.go uaccount GetRegion + +package uaccount + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" + . "github.com/ucloud/ucloud-sdk-go/service/uaccount/types" +) + +type GetRegionRequest struct { + request.CommonBase +} + +type GetRegionResponse struct { + response.CommonBase + + // 各数据中心信息 + Regions []RegionInfo +} + +// NewGetRegionRequest will create request of GetRegion action. +func (c *UAccountClient) NewGetRegionRequest() *GetRegionRequest { + cfg := c.client.GetConfig() + + return &GetRegionRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// GetRegion - 获取用户在各数据中心的权限等信息 +func (c *UAccountClient) GetRegion(req *GetRegionRequest) (*GetRegionResponse, error) { + var err error + var res GetRegionResponse + + err = c.client.InvokeAction("GetRegion", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/get_user_info.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/get_user_info.go new file mode 100644 index 0000000000..ee8877bbda --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/get_user_info.go @@ -0,0 +1,45 @@ +//go:generate go run ../../private/cli/gen-api/main.go uaccount GetUserInfo + +package uaccount + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" + . "github.com/ucloud/ucloud-sdk-go/service/uaccount/types" +) + +type GetUserInfoRequest struct { + request.CommonBase +} + +type GetUserInfoResponse struct { + response.CommonBase + + // 用户信息返回数组 + DataSet []UserInfo +} + +// NewGetUserInfoRequest will create request of GetUserInfo action. +func (c *UAccountClient) NewGetUserInfoRequest() *GetUserInfoRequest { + cfg := c.client.GetConfig() + + return &GetUserInfoRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// GetUserInfo - 获取用户信息 +func (c *UAccountClient) GetUserInfo(req *GetUserInfoRequest) (*GetUserInfoResponse, error) { + var err error + var res GetUserInfoResponse + + err = c.client.InvokeAction("GetUserInfo", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/types/project_list_info.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/types/project_list_info.go new file mode 100644 index 0000000000..ff7b5a4db8 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/types/project_list_info.go @@ -0,0 +1,29 @@ +package types + +// ProjectListInfo - 项目信息 +type ProjectListInfo struct { + + // 项目ID + ProjectId string + + // 项目名称 + ProjectName string + + // 父项目ID + ParentId string + + // 父项目名称 + ParentName string + + // 创建时间(Unix时间戳) + CreateTime int + + // 是否为默认项目 + IsDefault bool + + // 项目下资源数量 + ResourceCount int + + // 项目下成员数量 + MemberCount int +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/types/region_info.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/types/region_info.go new file mode 100644 index 0000000000..bdd6987e28 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/types/region_info.go @@ -0,0 +1,23 @@ +package types + +// RegionInfo - 数据中心信息 +type RegionInfo struct { + + // 数据中心ID + RegionId int + + // 数据中心名称 + RegionName string + + // 是否用户当前默认数据中心 + IsDefault bool + + // 用户在此数据中心的权限位 + BitMaps string + + // 地域名字,如cn-bj + Region string + + // 可用区名字,如cn-bj-01 + Zone string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/types/user_info.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/types/user_info.go new file mode 100644 index 0000000000..ff4416ce2d --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uaccount/types/user_info.go @@ -0,0 +1,53 @@ +package types + +// UserInfo - 用户信息 +type UserInfo struct { + + // 用户Id + UserId int + + // 用户邮箱 + UserEmail string + + // 用户手机 + UserPhone string + + // 国际号码前缀 + PhonePrefix string + + // 会员类型 + UserType int + + // 称呼 + UserName string + + // 公司名称 + CompanyName string + + // 所属行业 + IndustryType int + + // 省份 + Province string + + // 城市 + City string + + // 公司地址 + UserAddress string + + // 是否超级管理员 0:否 1:是 + Admin int + + // 是否子帐户(大于100为子帐户) + UserVersion int + + // 是否有财务权限 0:否 1:是 + Finance int + + // 管理员 + Administrator string + + // 实名认证状态 + AuthState string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/client.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/client.go new file mode 100644 index 0000000000..34d81e328b --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/client.go @@ -0,0 +1,17 @@ +package uhost + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk" + "github.com/ucloud/ucloud-sdk-go/sdk/auth" +) + +type UHostClient struct { + client *sdk.Client +} + +func NewClient(config *sdk.ClientConfig, credential *auth.Credential) *UHostClient { + client := sdk.NewClient(config, credential) + return &UHostClient{ + client: client, + } +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/create_uhost_instance.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/create_uhost_instance.go new file mode 100644 index 0000000000..60741d1cf1 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/create_uhost_instance.go @@ -0,0 +1,138 @@ +package uhost + +import ( + "encoding/base64" + + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type CreateUHostInstanceRequest struct { + request.CommonBase + + // 地域。 参见 [地域和可用区列表](../summary/regionlist.html) + Region string + + // 可用区。参见 [可用区列表](../summary/regionlist.html) + Zone string + + // 项目ID。不填写为默认项目,子帐号必须填写。 请参考[GetProjectList接口](../summary/get_project_list.html) + ProjectId string + + // 镜像ID。 请通过 [DescribeImage](describe_image.html)获取 + ImageId string + + // UHost密码,LoginMode为Password时此项必须(密码需使用base64进行编码) + Password string + + // UHost实例名称。默认:UHost + Name string + + // 业务组。默认:Default(Default即为未分组) + Tag string + + // 计费模式。枚举值为: Year,按年付费; Month,按月付费; Dynamic,按小时付费(需开启权限)。默认为月付 + ChargeType string + + // 购买时长。默认: 1。按小时购买(Dynamic)时无需此参数。 月付时,此参数传0,代表了购买至月末。 + Quantity int + + // 云主机机型。枚举值:N1:系列1标准型;N2:系列2标准型;I1: 系列1高IO型;I2,系列2高IO型; D1: 系列1大数据机型;G1: 系列1GPU型;G2:系列2GPU型;北京A、北京C、上海二A、香港A可用区默认N1,其他机房默认N2。不同机房的主机类型支持情况不同。详情请参考控制台。 + UHostType string + + // 虚拟CPU核数。 单位:个。可选参数:{1,2,4,8,12,16,24,32}。默认值: 4 + CPU int + + // 内存大小。单位:MB。范围 :[1024, 131072], 取值为2的幂次方。默认值:8192。 + Memory int + + // GPU卡核心数。仅GPU机型支持此字段;系列1可选1,2;系列2可选1,2,3,4。GPU可选数量与CPU有关联,详情请参考控制台。 + GPU int + + // 主机登陆模式。密码(默认选项): Password,key: KeyPair(此项暂不支持) + LoginMode string + + // 磁盘类型,同时设定系统盘和数据盘的磁盘类型。枚举值为:LocalDisk,本地磁盘; UDisk,云硬盘;默认为LocalDisk。仅部分可用区支持云硬盘方式的主机存储方式,具体请查询控制台。 + StorageType string + + // 系统盘大小。 单位:GB, 范围[20,100], 步长:10 + BootDiskSpace int + + // 数据盘大小。 单位:GB, 范围[0,8000], 步长:10, 默认值:20,云盘支持0-8000;本地普通盘支持0-2000;本地SSD盘(包括所有GPU机型)支持100-1000 + DiskSpace int + + // 网络增强。目前仅Normal(不开启) 和Super(开启)可用。默认Normal。 不同机房的网络增强支持情况不同。详情请参考控制台。 + NetCapability string + + // 是否开启方舟特性。Yes为开启方舟,No为关闭方舟。Basic为免费基础快照模式(暂不支持)。 + TimemachineFeature string + + // 是否开启热升级特性。True为开启,False为未开启,默认False。仅系列1云主机需要使用此字段,系列2云主机根据镜像是否支持云主机。 + HotplugFeature bool + + // 加密盘的密码。若输入此字段,自动选择加密盘。加密盘需要权限位。 + DiskPassword string + + // 网络ID(VPC2.0情况下无需填写)。VPC1.0情况下,若不填写,代表选择基础网络; 若填写,代表选择子网。参见DescribeSubnet。 + NetworkId string + + // VPC ID。VPC2.0下需要填写此字段。 + VPCId string + + // 子网ID。VPC2.0下需要填写此字段。 + SubnetId string + + // 【数组】创建云主机时指定内网IP。当前只支持一个内网IP。调用方式举例:PrivateIp.0=x.x.x.x。 + PrivateIp []string + + // 防火墙Id,默认:Web推荐防火墙。如何查询SecurityGroupId请参见 [DescribeSecurityGroup](../unet-api/describe_security_group.html) + SecurityGroupId string + + // 代金券ID。请通过DescribeCoupon接口查询,或登录用户中心查看 + CouponId string +} + +// NewCreateUHostInstanceRequest will create request of CreateUHostInstance action. +func (c *UHostClient) NewCreateUHostInstanceRequest() *CreateUHostInstanceRequest { + cfg := c.client.GetConfig() + + return &CreateUHostInstanceRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +type CreateUHostInstanceResponse struct { + response.CommonBase + + // Message, if an error was occupy, return the error message + Message string + + // 操作返回码 + RetCode int + + // 操作名称 + Action string + + // UHost实例Id集合 + UHostIds []string + + // IP信息 + IPs []string +} + +// CreateUHostInstance - 指定数据中心,根据资源使用量创建指定数量的UHost实例。 +func (c *UHostClient) CreateUHostInstance(req *CreateUHostInstanceRequest) (*CreateUHostInstanceResponse, error) { + var err error + var res CreateUHostInstanceResponse + req.Password = base64.StdEncoding.EncodeToString([]byte(req.Password)) + + err = c.client.InvokeAction("CreateUHostInstance", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/describe_image.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/describe_image.go new file mode 100644 index 0000000000..dd23a65575 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/describe_image.go @@ -0,0 +1,69 @@ +//go:generate go run ../../private/cli/gen-api/main.go uhost DescribeImage + +package uhost + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" + . "github.com/ucloud/ucloud-sdk-go/service/uhost/types" +) + +type DescribeImageRequest struct { + request.CommonBase + + // Optional, 可用区。参见 [可用区列表](../summary/regionlist.html) + Zone string + + // Optional, 镜像类型。标准镜像:Base,镜像市场:Business, 自定义镜像:Custom,默认返回所有类型 + ImageType string + + // Optional, 操作系统类型:Linux, Windows 默认返回所有类型 + OsType string + + // Optional, 镜像Id + ImageId string + + // Optional, 列表起始位置偏移量,默认为0 + Offset int + + // Optional, 返回数据长度,默认为20 + Limit int + + // Optional, 是否返回价格:1返回,0不返回;默认不返回 + PriceSet int +} + +type DescribeImageResponse struct { + response.CommonBase + + // 满足条件的镜像总数 + TotalCount int + + // 镜像列表详见 UHostImageSet + ImageSet []UHostImageSet +} + +// NewDescribeImageRequest will create request of DescribeImage action. +func (c *UHostClient) NewDescribeImageRequest() *DescribeImageRequest { + cfg := c.client.GetConfig() + + return &DescribeImageRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DescribeImage - 获取指定数据中心镜像列表,用户可通过指定操作系统类型,镜像Id进行过滤。 +func (c *UHostClient) DescribeImage(req *DescribeImageRequest) (*DescribeImageResponse, error) { + var err error + var res DescribeImageResponse + + err = c.client.InvokeAction("DescribeImage", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/describe_uhost_instance.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/describe_uhost_instance.go new file mode 100644 index 0000000000..030eb67e8b --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/describe_uhost_instance.go @@ -0,0 +1,63 @@ +//go:generate go run ../../private/cli/gen-api/main.go uhost DescribeUHostInstance + +package uhost + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" + . "github.com/ucloud/ucloud-sdk-go/service/uhost/types" +) + +type DescribeUHostInstanceRequest struct { + request.CommonBase + + // Optional, 可用区。参见 [可用区列表](../summary/regionlist.html) + Zone string + + // Optional, 【数组】UHost主机的资源ID,例如UHostIds.0代表希望获取信息 的主机1,UHostIds.1代表主机2。 如果不传入,则返回当前Region 所有符合条件的UHost实例。 + UHostIds []string + + // Optional, 要查询的业务组名称 + Tag string + + // Optional, 列表起始位置偏移量,默认为0 + Offset int + + // Optional, 返回数据长度,默认为20,最大100 + Limit int +} + +type DescribeUHostInstanceResponse struct { + response.CommonBase + + // UHostInstance总数 + TotalCount int + + // 云主机实例列表,每项参数可见下面 UHostInstanceSet + UHostSet []UHostInstanceSet +} + +// NewDescribeUHostInstanceRequest will create request of DescribeUHostInstance action. +func (c *UHostClient) NewDescribeUHostInstanceRequest() *DescribeUHostInstanceRequest { + cfg := c.client.GetConfig() + + return &DescribeUHostInstanceRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DescribeUHostInstance - 获取主机或主机列表信息,并可根据数据中心,主机ID等参数进行过滤。 +func (c *UHostClient) DescribeUHostInstance(req *DescribeUHostInstanceRequest) (*DescribeUHostInstanceResponse, error) { + var err error + var res DescribeUHostInstanceResponse + + err = c.client.InvokeAction("DescribeUHostInstance", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/doc.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/doc.go new file mode 100644 index 0000000000..8bf244c698 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/doc.go @@ -0,0 +1,11 @@ +/* + Package uhost include resources of ucloud host product + + See also + + - API: https://docs.ucloud.cn/api/uhost-api/index + - Product: https://www.ucloud.cn/site/product/uhost.html + + for detail. +*/ +package uhost diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/enums.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/enums.go new file mode 100644 index 0000000000..7cebbd2018 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/enums.go @@ -0,0 +1,15 @@ +package uhost + +// State is the state of UHost instance +type State = string + +// Enum values for State +const ( + StateInitializing State = "Initializing" + StateStarting State = "Starting" + StateRunning State = "Running" + StateStopping State = "Stopping" + StateStopped State = "Stopped" + StateInstallFail State = "InstallFail" + StateRebooting State = "Rebooting" +) diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/stop_uhost_instance.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/stop_uhost_instance.go new file mode 100644 index 0000000000..eecfc73dbe --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/stop_uhost_instance.go @@ -0,0 +1,50 @@ +//go:generate go run ../../private/cli/gen-api/main.go uhost StopUHostInstance + +package uhost + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type StopUHostInstanceRequest struct { + request.CommonBase + + // Optional, 可用区。参见 [可用区列表](../summary/regionlist.html) + Zone string + + // Required, UHost实例ID 参见 [DescribeUHostInstance](describe_uhost_instance.html) + UHostId string +} + +type StopUHostInstanceResponse struct { + response.CommonBase + + // UHost实例ID + UhostId string +} + +// NewStopUHostInstanceRequest will create request of StopUHostInstance action. +func (c *UHostClient) NewStopUHostInstanceRequest() *StopUHostInstanceRequest { + cfg := c.client.GetConfig() + + return &StopUHostInstanceRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// StopUHostInstance - 指停止处于运行状态的UHost实例,需指定数据中心及UhostID。 +func (c *UHostClient) StopUHostInstance(req *StopUHostInstanceRequest) (*StopUHostInstanceResponse, error) { + var err error + var res StopUHostInstanceResponse + + err = c.client.InvokeAction("StopUHostInstance", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/terminate_uhost_instance.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/terminate_uhost_instance.go new file mode 100644 index 0000000000..473820cb95 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/terminate_uhost_instance.go @@ -0,0 +1,56 @@ +//go:generate go run ../../private/cli/gen-api/main.go uhost TerminateUHostInstance + +package uhost + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type TerminateUHostInstanceRequest struct { + request.CommonBase + + // Optional, 可用区。参见 [可用区列表](../summary/regionlist.html) + Zone string + + // Required, UHost资源Id 参见 [DescribeUHostInstance](describe_uhost_instance.html) + UHostId string + + // Optional, 是否直接删除,0表示按照原来的逻辑(有回收站权限,则进入回收站),1表示直接删除 + Destroy int +} + +type TerminateUHostInstanceResponse struct { + response.CommonBase + + // UHost 实例 Id + UHostIds []string + + // 放入回收站:"Yes", 彻底删除:“No” + InRecycle string +} + +// NewTerminateUHostInstanceRequest will create request of TerminateUHostInstance action. +func (c *UHostClient) NewTerminateUHostInstanceRequest() *TerminateUHostInstanceRequest { + cfg := c.client.GetConfig() + + return &TerminateUHostInstanceRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// TerminateUHostInstance - 删除指定数据中心的UHost实例。 +func (c *UHostClient) TerminateUHostInstance(req *TerminateUHostInstanceRequest) (*TerminateUHostInstanceResponse, error) { + var err error + var res TerminateUHostInstanceResponse + + err = c.client.InvokeAction("TerminateUHostInstance", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_disk_set.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_disk_set.go new file mode 100644 index 0000000000..ba55a67e00 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_disk_set.go @@ -0,0 +1,32 @@ +package types + +// UHostDiskSet - DescribeUHostInstance +type UHostDiskSet struct { + + // 磁盘类型。系统盘: Boot,数据盘: Data,网络盘:Udisk + Type string + + // 磁盘长ID + DiskId string + + // UDisk名字(仅当磁盘是UDisk时返回) + Name int + + // 磁盘盘符 + Drive string + + // 磁盘大小,单位: GB + Size int + + // 备份方案,枚举类型:BASIC_SNAPSHOT,普通快照;DATAARK,方舟。无快照则不返回该字段。 + BackupType string + + // 当前主机的IOPS值 + IOPS int + + // 磁盘短ID + DiskShortId string + + // Yes: 加密 No: 非加密 + Encrypted string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_image_set.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_image_set.go new file mode 100644 index 0000000000..3eb4b74598 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_image_set.go @@ -0,0 +1,50 @@ +package types + +// UHostImageSet - DescribeImage +type UHostImageSet struct { + + // 镜像ID + ImageId string + + // 镜像名称 + ImageName string + + // 可用区,参见 [可用区列表](../summary/regionlist.html) | + Zone string + + // 操作系统类型:Liunx,Windows + OsType string + + // 操作系统名称 + OsName string + + // 镜像类型 标准镜像:Base, 行业镜像:Business,自定义镜像:Custom + ImageType string + + // 特殊状态标识, 目前只有[NetEnhnced](高包量机型) + Features []string + + // 行业镜像类型(仅行业镜像将返回这个值) + FuncType string + + // 集成软件名称(仅行业镜像将返回这个值) + IntegratedSoftware string + + // 供应商(仅行业镜像将返回这个值) + Vendor string + + // 介绍链接(仅行业镜像将返回这个值) + Links string + + // 镜像状态, 可用:Available,制作中:Making, 不可用:Unavailable + State string + + // 镜像描述 + ImageDescription string + + // 创建时间,格式为Unix时间戳 + CreateTime int + + // 镜像大小 + ImageSize int +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_instance_set.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_instance_set.go new file mode 100644 index 0000000000..65dd1eb288 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_instance_set.go @@ -0,0 +1,95 @@ +package types + +// UHostInstanceSet - DescribeUHostInstance +type UHostInstanceSet struct { + + // UHost实例ID + UHostId string + + // UHost类型,枚举为:N1:标准型系列1;N2:标准型系列2 ;I1:高IO型系列1;I2:高IO型系列2;D1:大数据型系列1;G1:GPU型系列1;G2:GPU型系列2 + UHostType string + + // 可用区。参见 [可用区列表](../summary/regionlist.html) + Zone string + + // 系统盘与数据盘的磁盘类型。 枚举值为:LocalDisk,本地磁盘; UDisk,云硬盘 + StorageType string + + // 镜像ID + ImageId string + + // 基础镜像ID(指当前自定义镜像的来源镜像) + BasicImageId string + + // 基础镜像名称(指当前自定义镜像的来源镜像) + BasicImageName string + + // 业务组名称 + Tag string + + // 备注 + Remark string + + // UHost实例名称 + Name string + + // 实例状态, 初始化: Initializing; 启动中: Starting; 运行中: Running; 关机中: Stopping; 关机: Stopped 安装失败: Install Fail; 重启中: Rebooting + State string + + // 创建时间,格式为Unix时间戳 + CreateTime int + + // 计费模式,枚举值为: Year,按年付费; Month,按月付费; Dynamic,按需付费(需开启权限); + ChargeType string + + // 到期时间,格式为Unix时间戳 + ExpireTime int + + // 虚拟CPU核数,单位: 个 + CPU int + + // 内存大小,单位: MB + Memory int + + // 是否自动续费,自动续费:“Yes”,不自动续费:“No” + AutoRenew string + + // 磁盘信息见 UHostDiskSet + DiskSet []UHostDiskSet + + // 详细信息见 UHostIPSet + IPSet []UHostIPSet + + // 网络增强。目前仅支持Normal和Super + NetCapability string + + // 网络状态 连接:Connected, 断开:NotConnected + NetworkState string + + // yes: 开启方舟; no,未开启方舟 + TimemachineFeature string + + // true: 开启热升级; false,未开启热升级 + HotplugFeature bool + + // 基础网络:Default;子网:Private + SubnetType string + + // 内网或者子网的IP地址 + IPs []string + + // Os名称 + OsName string + + // "Linux"或者"Windows" + OsType string + + // 删除时间,格式为Unix时间戳 + DeleteTime int + + // 主机系列:N2,表示系列2;N1,表示系列1 + HostType string + + // 主机的生命周期类型。目前仅支持Normal:普通; + LifeCycle string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_ipset.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_ipset.go new file mode 100644 index 0000000000..92bb5db4ff --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/types/uhost_ipset.go @@ -0,0 +1,20 @@ +package types + +// UHostIPSet - DescribeUHostInstance +type UHostIPSet struct { + + // 电信: China-telecom,联通: China-unicom, 国际: Internation,BGP: Bgp,内网: Private 双线: Duplet + Type string + + // IP资源ID (内网IP无对应的资源ID) + IPId string + + // IP地址 + IP string + + // IP对应的带宽, 单位: Mb (内网IP不显示带宽信息) + Bandwidth int + + // 是否默认的弹性网卡的信息。true: 是默认弹性网卡;其他值:不是。 + Default string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/wait_until_uhost_instance_state.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/wait_until_uhost_instance_state.go new file mode 100644 index 0000000000..0610c03235 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/uhost/wait_until_uhost_instance_state.go @@ -0,0 +1,66 @@ +package uhost + +import ( + "time" + + uerr "github.com/ucloud/ucloud-sdk-go/sdk/error" + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/utils" +) + +type WaitUntilUHostInstanceStateRequest struct { + request.CommonBase + + Interval time.Duration + MaxAttempts int + DescribeRequest *DescribeUHostInstanceRequest + State string + IgnoreError bool +} + +// NewWaitUntilUHostInstanceStateRequest will create request of WaitUntilUHostInstanceState action. +func (c *UHostClient) NewWaitUntilUHostInstanceStateRequest() *WaitUntilUHostInstanceStateRequest { + cfg := c.client.GetConfig() + + return &WaitUntilUHostInstanceStateRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// WaitUntilUHostInstanceState will pending current goroutine until the state has changed to expected state. +func (c *UHostClient) WaitUntilUHostInstanceState(req *WaitUntilUHostInstanceStateRequest) error { + waiter := utils.FuncWaiter{ + Interval: req.Interval, + MaxAttempts: req.MaxAttempts, + IgnoreError: req.IgnoreError, + Checker: func() (bool, error) { + resp, err := c.DescribeUHostInstance(req.DescribeRequest) + if err != nil { + switch err { + case uerr.InvalidRequestError: + return false, err + default: + return false, nil + } + } + + // TODO: Ensure if it is any data consistency problem? + // Such as creating a new uhost, but cannot describe it's correct state immediately ... + for _, uhost := range resp.UHostSet { + if uhost.State != req.State { + return false, nil + } + } + + if len(resp.UHostSet) > 0 { + return true, nil + } else { + return false, nil + } + }, + } + return waiter.WaitForCompletion() +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/allocate_backend.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/allocate_backend.go new file mode 100644 index 0000000000..235a804a34 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/allocate_backend.go @@ -0,0 +1,62 @@ +//go:generate go run ../../private/cli/gen-api/main.go ulb AllocateBackend + +package ulb + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type AllocateBackendRequest struct { + request.CommonBase + + // Required, 负载均衡实例的ID + ULBId string + + // Required, VServer实例的ID + VServerId string + + // Required, 所添加的后端资源的类型 + ResourceType string + + // Required, 所添加的后端资源的资源ID + ResourceId string + + // Optional, 所添加的后端资源服务端口,取值范围[1-65535],默认80 + Port int + + // Optional, 后端实例状态开关,枚举值: 1:启用; 0:禁用 默认为启用 + Enabled int +} + +type AllocateBackendResponse struct { + response.CommonBase + + // 所添加的后端资源在ULB中的对象ID,(为ULB系统中使用,与资源自身ID无关),可用于 UpdateBackendAttribute/UpdateBackendAttributeBatch/ReleaseBackend + BackendId string +} + +// NewAllocateBackendRequest will create request of AllocateBackend action. +func (c *ULBClient) NewAllocateBackendRequest() *AllocateBackendRequest { + cfg := c.client.GetConfig() + + return &AllocateBackendRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// AllocateBackend - 添加ULB后端资源实例 +func (c *ULBClient) AllocateBackend(req *AllocateBackendRequest) (*AllocateBackendResponse, error) { + var err error + var res AllocateBackendResponse + + err = c.client.InvokeAction("AllocateBackend", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/client.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/client.go new file mode 100644 index 0000000000..977e179b29 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/client.go @@ -0,0 +1,17 @@ +package ulb + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk" + "github.com/ucloud/ucloud-sdk-go/sdk/auth" +) + +type ULBClient struct { + client *sdk.Client +} + +func NewClient(config *sdk.ClientConfig, credential *auth.Credential) *ULBClient { + client := sdk.NewClient(config, credential) + return &ULBClient{ + client: client, + } +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/create_policy.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/create_policy.go new file mode 100644 index 0000000000..4b7c9c3a7e --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/create_policy.go @@ -0,0 +1,59 @@ +//go:generate go run ../../private/cli/gen-api/main.go ulb CreatePolicy + +package ulb + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type CreatePolicyRequest struct { + request.CommonBase + + // Required, 需要添加内容转发策略的负载均衡实例ID + ULBId string + + // Required, 需要添加内容转发策略的VServer实例ID + VServerId string + + // Required, 内容转发策略应用的后端资源实例的ID,来源于 AllocateBackend 返回的 BackendId + BackendId []string + + // Required, 内容转发匹配字段 + Match string + + // Optional, 内容转发匹配字段的类型 + Type string +} + +type CreatePolicyResponse struct { + response.CommonBase + + // 内容转发策略ID + PolicyId string +} + +// NewCreatePolicyRequest will create request of CreatePolicy action. +func (c *ULBClient) NewCreatePolicyRequest() *CreatePolicyRequest { + cfg := c.client.GetConfig() + + return &CreatePolicyRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// CreatePolicy - 创建VServer内容转发策略 +func (c *ULBClient) CreatePolicy(req *CreatePolicyRequest) (*CreatePolicyResponse, error) { + var err error + var res CreatePolicyResponse + + err = c.client.InvokeAction("CreatePolicy", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/create_ulb.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/create_ulb.go new file mode 100644 index 0000000000..55e13e5fb5 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/create_ulb.go @@ -0,0 +1,71 @@ +//go:generate go run ../../private/cli/gen-api/main.go ulb CreateULB + +package ulb + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type CreateULBRequest struct { + request.CommonBase + + // Optional, 负载均衡的名字,默认值为“ULB” + ULBName string + + // Optional, 业务组 + Tag string + + // Optional, 备注 + Remark string + + // Optional, 创建的ULB是否为外网模式,默认即为外网模式 + OuterMode string + + // Optional, 创建的ULB是否为内网模式 + InnerMode string + + // Optional, 付费方式 + ChargeType string + + // Optional, ULB所在的VPC的ID, 如果不传则使用默认的VPC + VPCId string + + // Optional, 内网ULB 所属的子网ID,如果不传则使用默认的子网 + SubnetId string + + // Optional, ULB 所属的业务组ID,如果不传则使用默认的业务组 + BusinessId string +} + +type CreateULBResponse struct { + response.CommonBase + + // 负载均衡实例的Id + ULBId string +} + +// NewCreateULBRequest will create request of CreateULB action. +func (c *ULBClient) NewCreateULBRequest() *CreateULBRequest { + cfg := c.client.GetConfig() + + return &CreateULBRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// CreateULB - 创建负载均衡实例,可以选择内网或者外网 +func (c *ULBClient) CreateULB(req *CreateULBRequest) (*CreateULBResponse, error) { + var err error + var res CreateULBResponse + + err = c.client.InvokeAction("CreateULB", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/create_vserver.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/create_vserver.go new file mode 100644 index 0000000000..75439a9bce --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/create_vserver.go @@ -0,0 +1,71 @@ +//go:generate go run ../../private/cli/gen-api/main.go ulb CreateVServer + +package ulb + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type CreateVServerRequest struct { + request.CommonBase + + // Required, 负载均衡实例ID + ULBId string + + // Optional, VServer实例名称,默认为"VServer" + VServerName string + + // Optional, 监听器类型,枚举值为:RequestProxy:请求代理;PacketsTransmit:报文转发;默认为RequestProxy + ListenType string + + // Optional, VServer实例的协议,请求代理模式下有 HTTP、HTTPS、TCP,报文转发下有 TCP,UDP + Protocol string + + // Optional, VServer后端端口,取值范围[1-65535];默认值为80 + FrontendPort int + + // Optional, VServer负载均衡模式, 默认为轮询模式,ConsistentHash,SourcePort,ConsistentHashPort 只在报文转发中使用;Roundrobin和Source在请求代理和报文转发中使用。 + Method string + + // Optional, VServer会话保持方式,默认关闭会话保持。枚举值:None:关闭;ServerInsert:自动生成KEY;UserDefined:用户自定义KEY。 + PersistenceType string + + // Optional, 根据PersistenceType确认; None和ServerInsert:此字段无意义; UserDefined:此字段传入自定义会话保持String + PersistenceInfo string + + // Optional, ListenType为RequestProxy时表示空闲连接的回收时间,单位:秒,取值范围:时(0,86400],默认值为60;ListenType为PacketsTransmit时表示连接保持的时间,单位:秒,取值范围:[60,900],0 表示禁用连接保持 + ClientTimeout int +} + +type CreateVServerResponse struct { + response.CommonBase + + // VServer实例的Id + VServerId string +} + +// NewCreateVServerRequest will create request of CreateVServer action. +func (c *ULBClient) NewCreateVServerRequest() *CreateVServerRequest { + cfg := c.client.GetConfig() + + return &CreateVServerRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// CreateVServer - 创建VServer实例,定义监听的协议和端口以及负载均衡算法 +func (c *ULBClient) CreateVServer(req *CreateVServerRequest) (*CreateVServerResponse, error) { + var err error + var res CreateVServerResponse + + err = c.client.InvokeAction("CreateVServer", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/delete_policy.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/delete_policy.go new file mode 100644 index 0000000000..3b1ec43b1e --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/delete_policy.go @@ -0,0 +1,50 @@ +//go:generate go run ../../private/cli/gen-api/main.go ulb DeletePolicy + +package ulb + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type DeletePolicyRequest struct { + request.CommonBase + + // Required, 内容转发策略ID + PolicyId string + + // Optional, 内容转发策略组ID + GroupId string + + // Optional, VServer 资源ID + VServerId string +} + +type DeletePolicyResponse struct { + response.CommonBase +} + +// NewDeletePolicyRequest will create request of DeletePolicy action. +func (c *ULBClient) NewDeletePolicyRequest() *DeletePolicyRequest { + cfg := c.client.GetConfig() + + return &DeletePolicyRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DeletePolicy - 删除内容转发策略 +func (c *ULBClient) DeletePolicy(req *DeletePolicyRequest) (*DeletePolicyResponse, error) { + var err error + var res DeletePolicyResponse + + err = c.client.InvokeAction("DeletePolicy", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/delete_ulb.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/delete_ulb.go new file mode 100644 index 0000000000..590c9b823a --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/delete_ulb.go @@ -0,0 +1,44 @@ +//go:generate go run ../../private/cli/gen-api/main.go ulb DeleteULB + +package ulb + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type DeleteULBRequest struct { + request.CommonBase + + // Required, 负载均衡实例的ID + ULBId string +} + +type DeleteULBResponse struct { + response.CommonBase +} + +// NewDeleteULBRequest will create request of DeleteULB action. +func (c *ULBClient) NewDeleteULBRequest() *DeleteULBRequest { + cfg := c.client.GetConfig() + + return &DeleteULBRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DeleteULB - 删除负载均衡实例 +func (c *ULBClient) DeleteULB(req *DeleteULBRequest) (*DeleteULBResponse, error) { + var err error + var res DeleteULBResponse + + err = c.client.InvokeAction("DeleteULB", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/delete_vserver.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/delete_vserver.go new file mode 100644 index 0000000000..9d987ca785 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/delete_vserver.go @@ -0,0 +1,47 @@ +//go:generate go run ../../private/cli/gen-api/main.go ulb DeleteVServer + +package ulb + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type DeleteVServerRequest struct { + request.CommonBase + + // Required, 负载均衡实例的ID + ULBId string + + // Required, VServer实例的ID + VServerId string +} + +type DeleteVServerResponse struct { + response.CommonBase +} + +// NewDeleteVServerRequest will create request of DeleteVServer action. +func (c *ULBClient) NewDeleteVServerRequest() *DeleteVServerRequest { + cfg := c.client.GetConfig() + + return &DeleteVServerRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DeleteVServer - 删除VServer实例 +func (c *ULBClient) DeleteVServer(req *DeleteVServerRequest) (*DeleteVServerResponse, error) { + var err error + var res DeleteVServerResponse + + err = c.client.InvokeAction("DeleteVServer", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/describe_ulb.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/describe_ulb.go new file mode 100644 index 0000000000..5e15e7e2b6 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/describe_ulb.go @@ -0,0 +1,66 @@ +//go:generate go run ../../private/cli/gen-api/main.go ulb DescribeULB + +package ulb + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" + . "github.com/ucloud/ucloud-sdk-go/service/ulb/types" +) + +type DescribeULBRequest struct { + request.CommonBase + + // Optional, 数据偏移量,默认为0 + Offset int + + // Optional, 数据分页值,默认为20 + Limit int + + // Optional, 负载均衡实例的Id。 若指定则返回指定的负载均衡实例的信息; 若不指定则返回当前数据中心中所有的负载均衡实例的信息 + ULBId string + + // Optional, ULB所属的VPC + VPCId string + + // Optional, ULB所属的子网ID + SubnetId string + + // Optional, ULB所属的业务组ID + BusinessId string +} + +type DescribeULBResponse struct { + response.CommonBase + + // 满足条件的ULB总数 + TotalCount int + + // ULB列表,每项参数详见 ULBSet + DataSet []ULBSet +} + +// NewDescribeULBRequest will create request of DescribeULB action. +func (c *ULBClient) NewDescribeULBRequest() *DescribeULBRequest { + cfg := c.client.GetConfig() + + return &DescribeULBRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DescribeULB - 获取ULB详细信息 +func (c *ULBClient) DescribeULB(req *DescribeULBRequest) (*DescribeULBResponse, error) { + var err error + var res DescribeULBResponse + + err = c.client.InvokeAction("DescribeULB", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/describe_vserver.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/describe_vserver.go new file mode 100644 index 0000000000..b7f96682b5 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/describe_vserver.go @@ -0,0 +1,54 @@ +//go:generate go run ../../private/cli/gen-api/main.go ulb DescribeVServer + +package ulb + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" + . "github.com/ucloud/ucloud-sdk-go/service/ulb/types" +) + +type DescribeVServerRequest struct { + request.CommonBase + + // Required, 负载均衡实例的Id + ULBId string + + // Optional, VServer实例的Id;若指定则返回指定的VServer实例的信息; 若不指定则返回当前负载均衡实例下所有VServer的信息 + VServerId string +} + +type DescribeVServerResponse struct { + response.CommonBase + + // 满足条件的VServer总数 + TotalCount int + + // VServer列表,每项参数详见 ULBVServerSet + DataSet []ULBVServerSet +} + +// NewDescribeVServerRequest will create request of DescribeVServer action. +func (c *ULBClient) NewDescribeVServerRequest() *DescribeVServerRequest { + cfg := c.client.GetConfig() + + return &DescribeVServerRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DescribeVServer - 获取ULB下的VServer的详细信息 +func (c *ULBClient) DescribeVServer(req *DescribeVServerRequest) (*DescribeVServerResponse, error) { + var err error + var res DescribeVServerResponse + + err = c.client.InvokeAction("DescribeVServer", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/doc.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/doc.go new file mode 100644 index 0000000000..6499e334a0 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/doc.go @@ -0,0 +1,11 @@ +/* + Package ulb include resources of ucloud ulb product + + See also + + - API: https://docs.ucloud.cn/api/ulb-api/index + - Product: https://www.ucloud.cn/site/product/ulb.html + + for detail. +*/ +package ulb diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/release_backend.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/release_backend.go new file mode 100644 index 0000000000..faa2115759 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/release_backend.go @@ -0,0 +1,47 @@ +//go:generate go run ../../private/cli/gen-api/main.go ulb ReleaseBackend + +package ulb + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type ReleaseBackendRequest struct { + request.CommonBase + + // Required, 负载均衡实例的ID + ULBId string + + // Required, 后端资源实例的ID(ULB后端ID,非资源自身ID) + BackendId string +} + +type ReleaseBackendResponse struct { + response.CommonBase +} + +// NewReleaseBackendRequest will create request of ReleaseBackend action. +func (c *ULBClient) NewReleaseBackendRequest() *ReleaseBackendRequest { + cfg := c.client.GetConfig() + + return &ReleaseBackendRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// ReleaseBackend - 从VServer释放后端资源实例 +func (c *ULBClient) ReleaseBackend(req *ReleaseBackendRequest) (*ReleaseBackendResponse, error) { + var err error + var res ReleaseBackendResponse + + err = c.client.InvokeAction("ReleaseBackend", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/sslbinded_target_set.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/sslbinded_target_set.go new file mode 100644 index 0000000000..7c02d902ff --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/sslbinded_target_set.go @@ -0,0 +1,17 @@ +package types + +// SSLBindedTargetSet - DescribeSSL +type SSLBindedTargetSet struct { + + // SSL证书绑定到的VServer的资源ID + VServerId string + + // 对应的VServer的名字 + VServerName string + + // VServer 所属的ULB实例的资源ID + ULBId string + + // ULB实例的名称 + ULBName string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbbackend_set.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbbackend_set.go new file mode 100644 index 0000000000..b265d9cec7 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbbackend_set.go @@ -0,0 +1,32 @@ +package types + +// ULBBackendSet - DescribeULB +type ULBBackendSet struct { + + // 后端资源实例的Id + BackendId string + + // 后端资源实例的类型 + ResourceType string + + // 后端资源实例的资源Id + ResourceId string + + // 后端资源实例的资源名字 + ResourceName string + + // 后端资源实例的内网IP + PrivateIP string + + // 后端资源实例服务的端口 + Port int + + // 后端资源实例的启用与否 + Enabled int + + // 后端资源实例的运行状态 + Status int + + // 后端资源实例的资源所在的子网的ID + SubnetId string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbipset.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbipset.go new file mode 100644 index 0000000000..97435834e1 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbipset.go @@ -0,0 +1,14 @@ +package types + +// ULBIPSet - DescribeULB +type ULBIPSet struct { + + // 弹性IP的运营商信息,枚举值为: Telecom:电信IP Unicom:联通IP Duplet:双线IP(电信+联通) Bgp:BGP IP International:国际IP + OperatorName string + + // 弹性IP地址 + EIP string + + // 弹性IP的ID + EIPId string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbset.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbset.go new file mode 100644 index 0000000000..fe39b9cf29 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbset.go @@ -0,0 +1,56 @@ +package types + +// ULBSet - DescribeULB +type ULBSet struct { + + // 负载均衡的资源ID + ULBId string + + // 负载均衡的资源名称(内部记载,废弃) + ULBName string + + // 负载均衡的资源名称(资源系统中),缺省值“ULB” + Name string + + // 负载均衡的业务组名称,缺省值“Default” + Tag string + + // 负载均衡的备注,缺省值“” + Remark string + + // 带宽类型,枚举值为: 0,非共享带宽; 1,共享带宽 + BandwidthType int + + // 带宽 + Bandwidth int + + // ULB的创建时间,格式为Unix Timestamp + CreateTime int + + // ULB的到期时间,格式为Unix Timestamp + ExpireTime int + + // ULB的详细信息列表(废弃) + Resource []string + + // ULB的详细信息列表,具体结构见下方 ULBIPSet + IPSet []ULBIPSet + + // 负载均衡实例中存在的VServer实例列表,具体结构见下方 ULBVServerSet + VServerSet []ULBVServerSet + + // ULB 的类型 + ULBType string + + // ULB所在的VPC的ID + VPCId string + + // ULB 为 InnerMode 时,ULB 所属的子网ID,默认为空 + SubnetId string + + // ULB 所属的业务组ID + BusinessId string + + // ULB的内网IP,当ULBType为OuterMode时,该值为空 + PrivateIP string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbsslset.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbsslset.go new file mode 100644 index 0000000000..6439d7e3f2 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbsslset.go @@ -0,0 +1,11 @@ +package types + +// ULBSSLSet - DescribeULB +type ULBSSLSet struct { + + // SSL证书的Id + SSLId string + + // SSL证书的名字 + SSLName string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbvserver_set.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbvserver_set.go new file mode 100644 index 0000000000..58506c3218 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/types/ulbvserver_set.go @@ -0,0 +1,41 @@ +package types + +// ULBVServerSet - DescribeULB +type ULBVServerSet struct { + + // VServer实例的Id + VServerId string + + // VServer实例的名字 + VServerName string + + // VServer实例的协议。 枚举值为:HTTP,TCP,UDP,HTTPS。 + Protocol string + + // VServer服务端口 + FrontendPort int + + // VServer负载均衡的模式,具体的值参见 CreateVServer + Method string + + // VServer会话保持方式。枚举值为: None,关闭会话保持; ServerInsert,自动生成; UserDefined,用户自定义。 + PersistenceType string + + // 根据PersistenceType确定: None或ServerInsert,此字段为空; UserDefined,此字段展示用户自定义会话。 + PersistenceInfo string + + // 空闲连接的回收时间,单位:秒。 + ClientTimeout int + + // VServer的运行状态。枚举值: 0:运行正常;1:运行异常。 + Status int + + // VServer绑定的SSL证书信息,具体结构见下方 ULBSSLSet + SSLSet []ULBSSLSet + + // 后端资源信息列表,具体结构见下方 ULBBackendSet + VServerSet []ULBBackendSet + + // 监听器类型,枚举值为:RequestProxy:请求代理;PacketsTransmit:报文转发;默认为RequestProxy + ListenType string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/update_vserver_attribute.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/update_vserver_attribute.go new file mode 100644 index 0000000000..3cd13fa621 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/ulb/update_vserver_attribute.go @@ -0,0 +1,74 @@ +//go:generate go run ../../private/cli/gen-api/main.go ulb UpdateVServerAttribute + +package ulb + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type UpdateVServerAttributeRequest struct { + request.CommonBase + + // Required, 负载均衡实例ID + ULBId string + + // Required, VServer实例ID + VServerId string + + // Optional, VServer实例名称,若无此字段则不做修改 + VServerName string + + // Optional, VServer协议类型,请求代理只支持修改为 HTTP/HTTPS,报文转发VServer只支持修改为 TCP/UDP + Protocol string + + // Optional, VServer负载均衡算法,ConsistentHash,SourcePort,ConsistentHashPort 只在报文转发中使用;Roundrobin和Source在请求代理和报文转发中使用。 + Method string + + // Optional, VServer会话保持模式,若无此字段则不做修改。枚举值:None:关闭;ServerInsert:自动生成KEY;UserDefined:用户自定义KEY。 + PersistenceType string + + // Optional, 根据PersistenceType确定: None或ServerInsert, 此字段无意义; UserDefined, 则此字段传入用户自定义会话保持String. 若无此字段则不做修改 + PersistenceInfo string + + // Optional, 请求代理的VServer下表示空闲连接的回收时间,单位:秒,取值范围:时(0,86400],默认值为60;报文转发的VServer下表示回话保持的时间,单位:秒,取值范围:[60,900],0 表示禁用连接保持 + ClientTimeout string + + // Optional, 健康检查的类型,Port:端口,Path:路径 + MonitorType string + + // Optional, MonitorType 为 Path 时指定健康检查发送请求时HTTP HEADER 里的域名 + Domain string + + // Optional, MonitorType 为 Path 时指定健康检查发送请求时的路径,默认为 / + Path string +} + +type UpdateVServerAttributeResponse struct { + response.CommonBase +} + +// NewUpdateVServerAttributeRequest will create request of UpdateVServerAttribute action. +func (c *ULBClient) NewUpdateVServerAttributeRequest() *UpdateVServerAttributeRequest { + cfg := c.client.GetConfig() + + return &UpdateVServerAttributeRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// UpdateVServerAttribute - 更新VServer实例属性 +func (c *ULBClient) UpdateVServerAttribute(req *UpdateVServerAttributeRequest) (*UpdateVServerAttributeResponse, error) { + var err error + var res UpdateVServerAttributeResponse + + err = c.client.InvokeAction("UpdateVServerAttribute", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/allocate_eip.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/allocate_eip.go new file mode 100644 index 0000000000..0fb134395e --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/allocate_eip.go @@ -0,0 +1,75 @@ +//go:generate go run ../../private/cli/gen-api/main.go unet AllocateEIP + +package unet + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" + . "github.com/ucloud/ucloud-sdk-go/service/unet/types" +) + +type AllocateEIPRequest struct { + request.CommonBase + + // Required, 弹性IP的线路如下: 国际: International BGP: Bgp 各地域允许的线路参数如下: cn-sh1: Bgp cn-sh2: Bgp cn-gd: Bgp cn-bj1: Bgp cn-bj2: Bgp hk: International us-ca: International th-bkk: International kr-seoul:International us-ws:International ge-fra:International sg:International tw-kh:International + OperatorName string + + // Required, 弹性IP的外网带宽, 单位为Mbps. 共享带宽模式必须指定0M带宽, 非共享带宽模式必须指定非0Mbps带宽. 各地域非共享带宽的带宽范围如下: 流量计费[1-200],带宽计费[1-800] + Bandwidth int + + // Optional, 业务组名称, 默认为 "Default" + Tag string + + // Optional, 付费方式, 枚举值为: Year, 按年付费; Month, 按月付费; Dynamic, 按需付费(需开启权限); Trial, 试用(需开启权限) 默认为按月付费 + ChargeType string + + // Optional, 购买时长, 默认: 1 + Quantity int + + // Optional, 弹性IP的计费模式. 枚举值: "Traffic", 流量计费; "Bandwidth", 带宽计费; "ShareBandwidth",共享带宽模式. 默认为 "Bandwidth". + PayMode string + + // Optional, 绑定的共享带宽Id,仅当PayMode为ShareBandwidth时有效 + ShareBandwidthId string + + // Optional, 弹性IP的名称, 默认为 "EIP" + Name string + + // Optional, 弹性IP的备注, 默认为空 + Remark string + + // Optional, 代金券ID, 默认不使用 + CouponId string +} + +type AllocateEIPResponse struct { + response.CommonBase + + // 申请到的EIP资源详情 参见 UnetAllocateEIPSet + EIPSet []UnetAllocateEIPSet +} + +// NewAllocateEIPRequest will create request of AllocateEIP action. +func (c *UNetClient) NewAllocateEIPRequest() *AllocateEIPRequest { + cfg := c.client.GetConfig() + + return &AllocateEIPRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// AllocateEIP - 根据提供信息, 申请弹性IP +func (c *UNetClient) AllocateEIP(req *AllocateEIPRequest) (*AllocateEIPResponse, error) { + var err error + var res AllocateEIPResponse + + err = c.client.InvokeAction("AllocateEIP", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/bind_eip.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/bind_eip.go new file mode 100644 index 0000000000..4741f118ae --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/bind_eip.go @@ -0,0 +1,50 @@ +//go:generate go run ../../private/cli/gen-api/main.go unet BindEIP + +package unet + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type BindEIPRequest struct { + request.CommonBase + + // Required, 弹性IP的资源Id + EIPId string + + // Required, 弹性IP请求绑定的资源类型, 枚举值为: uhost: 云主机; vrouter: 虚拟路由器; ulb, 负载均衡器 upm: 物理机; hadoophost: 大数据集群;fortresshost:堡垒机;udockhost:容器;udhost:私有专区主机;natgw:natgw;udb:udb;vpngw:ipsec vpn;ucdr:云灾备;dbaudit:数据库审计; + ResourceType string + + // Required, 弹性IP请求绑定的资源ID + ResourceId string +} + +type BindEIPResponse struct { + response.CommonBase +} + +// NewBindEIPRequest will create request of BindEIP action. +func (c *UNetClient) NewBindEIPRequest() *BindEIPRequest { + cfg := c.client.GetConfig() + + return &BindEIPRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// BindEIP - 将尚未使用的弹性IP绑定到指定的资源 +func (c *UNetClient) BindEIP(req *BindEIPRequest) (*BindEIPResponse, error) { + var err error + var res BindEIPResponse + + err = c.client.InvokeAction("BindEIP", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/client.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/client.go new file mode 100644 index 0000000000..7617f3f963 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/client.go @@ -0,0 +1,17 @@ +package unet + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk" + "github.com/ucloud/ucloud-sdk-go/sdk/auth" +) + +type UNetClient struct { + client *sdk.Client +} + +func NewClient(config *sdk.ClientConfig, credential *auth.Credential) *UNetClient { + client := sdk.NewClient(config, credential) + return &UNetClient{ + client: client, + } +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/describe_eip.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/describe_eip.go new file mode 100644 index 0000000000..c4abffb9c7 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/describe_eip.go @@ -0,0 +1,60 @@ +//go:generate go run ../../private/cli/gen-api/main.go unet DescribeEIP + +package unet + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" + . "github.com/ucloud/ucloud-sdk-go/service/unet/types" +) + +type DescribeEIPRequest struct { + request.CommonBase + + // Optional, 弹性IP的资源ID如果为空, 则返回当前 Region中符合条件的的所有EIP + EIPIds []string + + // Optional, 数据偏移量, 默认为0 + Offset int + + // Optional, 数据分页值, 默认为20 + Limit int +} + +type DescribeEIPResponse struct { + response.CommonBase + + // 满足条件的弹性IP总数 + TotalCount int + + // 满足条件的弹性IP带宽总和, 单位Mbps + TotalBandwidth int + + // 弹性IP列表, 每项参数详见 UnetEIPSet + EIPSet []UnetEIPSet +} + +// NewDescribeEIPRequest will create request of DescribeEIP action. +func (c *UNetClient) NewDescribeEIPRequest() *DescribeEIPRequest { + cfg := c.client.GetConfig() + + return &DescribeEIPRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DescribeEIP - 获取弹性IP信息 +func (c *UNetClient) DescribeEIP(req *DescribeEIPRequest) (*DescribeEIPResponse, error) { + var err error + var res DescribeEIPResponse + + err = c.client.InvokeAction("DescribeEIP", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/doc.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/doc.go new file mode 100644 index 0000000000..f9caeecaa9 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/doc.go @@ -0,0 +1,11 @@ +/* + Package unet include resources of ucloud unet product + + See also + + - API: https://docs.ucloud.cn/api/unet-api/index + - Product: https://www.ucloud.cn/site/product/unet.html + + for detail. +*/ +package unet diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/release_eip.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/release_eip.go new file mode 100644 index 0000000000..19fc9797f8 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/release_eip.go @@ -0,0 +1,44 @@ +//go:generate go run ../../private/cli/gen-api/main.go unet ReleaseEIP + +package unet + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type ReleaseEIPRequest struct { + request.CommonBase + + // Required, 弹性IP的资源ID + EIPId string +} + +type ReleaseEIPResponse struct { + response.CommonBase +} + +// NewReleaseEIPRequest will create request of ReleaseEIP action. +func (c *UNetClient) NewReleaseEIPRequest() *ReleaseEIPRequest { + cfg := c.client.GetConfig() + + return &ReleaseEIPRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// ReleaseEIP - 释放弹性IP资源, 所释放弹性IP必须为非绑定状态. +func (c *UNetClient) ReleaseEIP(req *ReleaseEIPRequest) (*ReleaseEIPResponse, error) { + var err error + var res ReleaseEIPResponse + + err = c.client.InvokeAction("ReleaseEIP", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/share_bandwidth_set.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/share_bandwidth_set.go new file mode 100644 index 0000000000..01d3500679 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/share_bandwidth_set.go @@ -0,0 +1,14 @@ +package types + +// ShareBandwidthSet - DescribeEIP +type ShareBandwidthSet struct { + + // 共享带宽带宽值 + ShareBandwidth int + + // 共享带宽的资源名称 + ShareBandwidthName string + + // 共享带宽ID + ShareBandwidthId string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_allocate_eipset.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_allocate_eipset.go new file mode 100644 index 0000000000..5c99c7fb67 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_allocate_eipset.go @@ -0,0 +1,11 @@ +package types + +// UnetAllocateEIPSet - AllocateEIP +type UnetAllocateEIPSet struct { + + // 申请到的EIP资源ID + EIPId string + + // 申请到的IPv4地址. 如果在请求参数中OperatorName为Duplet, 则EIPAddr中会含有两个IP地址, 一个为电信IP, 一个为联通IP. 其余情况下, EIPAddr只含有一个IP. 参见 UnetEIPAddrSet + EIPAddr []UnetEIPAddrSet +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_eipaddr_set.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_eipaddr_set.go new file mode 100644 index 0000000000..73f8a3f90c --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_eipaddr_set.go @@ -0,0 +1,11 @@ +package types + +// UnetEIPAddrSet - DescribeEIP +type UnetEIPAddrSet struct { + + // 运营商信息如: 电信: Telecom, 联通: Unicom, 国际: International, Duplet: 双线IP(电信+联通), BGP: Bgp + OperatorName string + + // IP地址 + IP string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_eipresource_set.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_eipresource_set.go new file mode 100644 index 0000000000..df57e70647 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_eipresource_set.go @@ -0,0 +1,17 @@ +package types + +// UnetEIPResourceSet - DescribeEIP +type UnetEIPResourceSet struct { + + // 已绑定的资源类型, 枚举值为: uhost, 云主机;vrouter:虚拟路由器;ulb:负载均衡器 + ResourceType string + + // 已绑定的资源名称 + ResourceName string + + // 已绑定资源的资源ID + ResourceId string + + // 弹性IP的资源ID + EIPId string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_eipset.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_eipset.go new file mode 100644 index 0000000000..cbfc800518 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/types/unet_eipset.go @@ -0,0 +1,53 @@ +package types + +// UnetEIPSet - DescribeEIP +type UnetEIPSet struct { + + // 弹性IP的资源ID + EIPId string + + // 外网出口权重, 默认为50, 范围[0-100] + Weight int + + // 带宽模式, 枚举值为: 0: 非共享带宽模式, 1: 共享带宽模式 + BandwidthType int + + // 弹性IP的带宽, 单位为Mbps, 当BandwidthType=1时, 该处显示为共享带宽值. 当BandwidthType=0时, 该处显示这个弹性IP的带宽. + Bandwidth int + + // 弹性IP的资源绑定状态, 枚举值为: used: 已绑定, free: 未绑定, freeze: 已冻结 + Status string + + // 付费方式, 枚举值为: Year, 按年付费; Month, 按月付费; Dynamic, 按小时付费; Trial, 试用. 按小时付费和试用这两种付费模式需要开通权限. + ChargeType string + + // 弹性IP的创建时间, 格式为Unix Timestamp + CreateTime int + + // 弹性IP的到期时间, 格式为Unix Timestamp + ExpireTime int + + // 弹性IP的详细信息列表, 具体结构见下方 UnetEIPResourceSet + Resource UnetEIPResourceSet + + // 弹性IP的详细信息列表, 具体结构见下方 UnetEIPAddrSet + EIPAddr []UnetEIPAddrSet + + // 弹性IP的名称,缺省值为 "EIP" + Name string + + // 弹性IP的业务组标识, 缺省值为 "Default" + Tag string + + // 弹性IP的备注, 缺省值为 "" + Remark string + + // 弹性IP的计费模式, 枚举值为: "Bandwidth", 带宽计费; "Traffic", 流量计费; "ShareBandwidth",共享带宽模式. 默认为 "Bandwidth". + PayMode string + + // 共享带宽信息 参见 ShareBandwidthSet + ShareBandwidthSet ShareBandwidthSet + + // 弹性IP是否到期 + Expire bool +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/un_bind_eip.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/un_bind_eip.go new file mode 100644 index 0000000000..ecb1342cf3 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/unet/un_bind_eip.go @@ -0,0 +1,50 @@ +//go:generate go run ../../private/cli/gen-api/main.go unet UnBindEIP + +package unet + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type UnBindEIPRequest struct { + request.CommonBase + + // Required, 弹性IP的资源Id + EIPId string + + // Required, 弹性IP请求解绑的资源类型, 枚举值为: uhost: 云主机; vrouter: 虚拟路由器; ulb, 负载均衡器 upm: 物理机; hadoophost: 大数据集群;fortresshost:堡垒机;udockhost:容器;udhost:私有专区主机;natgw:natgw;udb:udb;vpngw:ipsec vpn;ucdr:云灾备;dbaudit:数据库审计; + ResourceType string + + // Required, 弹性IP请求解绑的资源ID + ResourceId string +} + +type UnBindEIPResponse struct { + response.CommonBase +} + +// NewUnBindEIPRequest will create request of UnBindEIP action. +func (c *UNetClient) NewUnBindEIPRequest() *UnBindEIPRequest { + cfg := c.client.GetConfig() + + return &UnBindEIPRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// UnBindEIP - 将弹性IP从资源上解绑 +func (c *UNetClient) UnBindEIP(req *UnBindEIPRequest) (*UnBindEIPResponse, error) { + var err error + var res UnBindEIPResponse + + err = c.client.InvokeAction("UnBindEIP", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/add_vpcnetwork.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/add_vpcnetwork.go new file mode 100644 index 0000000000..ed2041d9ab --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/add_vpcnetwork.go @@ -0,0 +1,47 @@ +//go:generate go run ../../private/cli/gen-api/main.go vpc AddVPCNetwork + +package vpc + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type AddVPCNetworkRequest struct { + request.CommonBase + + // Required, 源VPC短ID + VPCId string + + // Required, 增加网段 + Network []string +} + +type AddVPCNetworkResponse struct { + response.CommonBase +} + +// NewAddVPCNetworkRequest will create request of AddVPCNetwork action. +func (c *VPCClient) NewAddVPCNetworkRequest() *AddVPCNetworkRequest { + cfg := c.client.GetConfig() + + return &AddVPCNetworkRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// AddVPCNetwork - 添加VPC网段 +func (c *VPCClient) AddVPCNetwork(req *AddVPCNetworkRequest) (*AddVPCNetworkResponse, error) { + var err error + var res AddVPCNetworkResponse + + err = c.client.InvokeAction("AddVPCNetwork", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/client.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/client.go new file mode 100644 index 0000000000..555deea89a --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/client.go @@ -0,0 +1,17 @@ +package vpc + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk" + "github.com/ucloud/ucloud-sdk-go/sdk/auth" +) + +type VPCClient struct { + client *sdk.Client +} + +func NewClient(config *sdk.ClientConfig, credential *auth.Credential) *VPCClient { + client := sdk.NewClient(config, credential) + return &VPCClient{ + client: client, + } +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/create_subnet.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/create_subnet.go new file mode 100644 index 0000000000..67289bddc5 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/create_subnet.go @@ -0,0 +1,62 @@ +//go:generate go run ../../private/cli/gen-api/main.go vpc CreateSubnet + +package vpc + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type CreateSubnetRequest struct { + request.CommonBase + + // Required, VPC资源ID + VPCId string + + // Required, 子网网络地址,例如192.168.0.0 + Subnet string + + // Optional, 子网网络号位数,默认为24 + Netmask int + + // Optional, 子网名称,默认为Subnet + SubnetName string + + // Optional, 业务组名称,默认为Default + Tag string + + // Optional, 备注 + Remark string +} + +type CreateSubnetResponse struct { + response.CommonBase + + // 子网ID + SubnetId string +} + +// NewCreateSubnetRequest will create request of CreateSubnet action. +func (c *VPCClient) NewCreateSubnetRequest() *CreateSubnetRequest { + cfg := c.client.GetConfig() + + return &CreateSubnetRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// CreateSubnet - 创建子网 +func (c *VPCClient) CreateSubnet(req *CreateSubnetRequest) (*CreateSubnetResponse, error) { + var err error + var res CreateSubnetResponse + + err = c.client.InvokeAction("CreateSubnet", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/create_vpc.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/create_vpc.go new file mode 100644 index 0000000000..bcf7b6dfff --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/create_vpc.go @@ -0,0 +1,56 @@ +//go:generate go run ../../private/cli/gen-api/main.go vpc CreateVPC + +package vpc + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type CreateVPCRequest struct { + request.CommonBase + + // Required, VPC名称 + Name string + + // Required, VPC网段 + Network []string + + // Optional, 业务组名称 + Tag string + + // Optional, 备注 + Remark string +} + +type CreateVPCResponse struct { + response.CommonBase + + // VPC资源Id + VPCId string +} + +// NewCreateVPCRequest will create request of CreateVPC action. +func (c *VPCClient) NewCreateVPCRequest() *CreateVPCRequest { + cfg := c.client.GetConfig() + + return &CreateVPCRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// CreateVPC - 创建VPC +func (c *VPCClient) CreateVPC(req *CreateVPCRequest) (*CreateVPCResponse, error) { + var err error + var res CreateVPCResponse + + err = c.client.InvokeAction("CreateVPC", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/create_vpcintercom.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/create_vpcintercom.go new file mode 100644 index 0000000000..2dad2a694f --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/create_vpcintercom.go @@ -0,0 +1,53 @@ +//go:generate go run ../../private/cli/gen-api/main.go vpc CreateVPCIntercom + +package vpc + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type CreateVPCIntercomRequest struct { + request.CommonBase + + // Required, 源VPC短ID + VPCId string + + // Required, 目的VPC短ID + DstVPCId string + + // Optional, 目的所在地域(如果目的VPC和源VPC不在同一个地域,两个地域需要建立跨域通道,且该字段必选) + DstRegion string + + // Optional, 目的项目ID + DstProjectId string +} + +type CreateVPCIntercomResponse struct { + response.CommonBase +} + +// NewCreateVPCIntercomRequest will create request of CreateVPCIntercom action. +func (c *VPCClient) NewCreateVPCIntercomRequest() *CreateVPCIntercomRequest { + cfg := c.client.GetConfig() + + return &CreateVPCIntercomRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// CreateVPCIntercom - 新建VPC互通关系 +func (c *VPCClient) CreateVPCIntercom(req *CreateVPCIntercomRequest) (*CreateVPCIntercomResponse, error) { + var err error + var res CreateVPCIntercomResponse + + err = c.client.InvokeAction("CreateVPCIntercom", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/delete_subnet.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/delete_subnet.go new file mode 100644 index 0000000000..4155f7c5f0 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/delete_subnet.go @@ -0,0 +1,44 @@ +//go:generate go run ../../private/cli/gen-api/main.go vpc DeleteSubnet + +package vpc + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type DeleteSubnetRequest struct { + request.CommonBase + + // Required, 子网ID + SubnetId string +} + +type DeleteSubnetResponse struct { + response.CommonBase +} + +// NewDeleteSubnetRequest will create request of DeleteSubnet action. +func (c *VPCClient) NewDeleteSubnetRequest() *DeleteSubnetRequest { + cfg := c.client.GetConfig() + + return &DeleteSubnetRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DeleteSubnet - 删除子网 +func (c *VPCClient) DeleteSubnet(req *DeleteSubnetRequest) (*DeleteSubnetResponse, error) { + var err error + var res DeleteSubnetResponse + + err = c.client.InvokeAction("DeleteSubnet", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/delete_vpc.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/delete_vpc.go new file mode 100644 index 0000000000..1cb2df40e2 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/delete_vpc.go @@ -0,0 +1,44 @@ +//go:generate go run ../../private/cli/gen-api/main.go vpc DeleteVPC + +package vpc + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type DeleteVPCRequest struct { + request.CommonBase + + // Required, VPC资源Id + VPCId string +} + +type DeleteVPCResponse struct { + response.CommonBase +} + +// NewDeleteVPCRequest will create request of DeleteVPC action. +func (c *VPCClient) NewDeleteVPCRequest() *DeleteVPCRequest { + cfg := c.client.GetConfig() + + return &DeleteVPCRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DeleteVPC - 删除VPC +func (c *VPCClient) DeleteVPC(req *DeleteVPCRequest) (*DeleteVPCResponse, error) { + var err error + var res DeleteVPCResponse + + err = c.client.InvokeAction("DeleteVPC", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/delete_vpcintercom.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/delete_vpcintercom.go new file mode 100644 index 0000000000..380869ce79 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/delete_vpcintercom.go @@ -0,0 +1,53 @@ +//go:generate go run ../../private/cli/gen-api/main.go vpc DeleteVPCIntercom + +package vpc + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type DeleteVPCIntercomRequest struct { + request.CommonBase + + // Required, 源VPC短ID + VPCId string + + // Required, 目的VPC短ID + DstVPCId string + + // Optional, 目的所在地域 + DstRegion string + + // Optional, 目的项目ID(如果目的VPC和源VPC不在同一个地域,两个地域需要建立跨域通道,且该字段必选) + DstProjectId string +} + +type DeleteVPCIntercomResponse struct { + response.CommonBase +} + +// NewDeleteVPCIntercomRequest will create request of DeleteVPCIntercom action. +func (c *VPCClient) NewDeleteVPCIntercomRequest() *DeleteVPCIntercomRequest { + cfg := c.client.GetConfig() + + return &DeleteVPCIntercomRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DeleteVPCIntercom - 删除VPC互通关系 +func (c *VPCClient) DeleteVPCIntercom(req *DeleteVPCIntercomRequest) (*DeleteVPCIntercomResponse, error) { + var err error + var res DeleteVPCIntercomResponse + + err = c.client.InvokeAction("DeleteVPCIntercom", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_subnet.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_subnet.go new file mode 100644 index 0000000000..20f079e7e2 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_subnet.go @@ -0,0 +1,69 @@ +//go:generate go run ../../private/cli/gen-api/main.go vpc DescribeSubnet + +package vpc + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" + . "github.com/ucloud/ucloud-sdk-go/service/vpc/types" +) + +type DescribeSubnetRequest struct { + request.CommonBase + + // Optional, 子网id数组,适用于一次查询多个子网信息 + SubnetIds []string + + // Optional, 子网id,适用于一次查询一个子网信息 + SubnetId string + + // Optional, VPC资源id + VPCId string + + // Optional, 业务组名称,默认为Default + Tag string + + // Optional, 业务组 + BusinessId string + + // Optional, 默认为0 + Offset int + + // Optional, 默认为20 + Limit int +} + +type DescribeSubnetResponse struct { + response.CommonBase + + // 子网总数量 + TotalCount int + + // 子网信息数组 + DataSet []VPCSubnetInfoSet +} + +// NewDescribeSubnetRequest will create request of DescribeSubnet action. +func (c *VPCClient) NewDescribeSubnetRequest() *DescribeSubnetRequest { + cfg := c.client.GetConfig() + + return &DescribeSubnetRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DescribeSubnet - 获取子网信息 +func (c *VPCClient) DescribeSubnet(req *DescribeSubnetRequest) (*DescribeSubnetResponse, error) { + var err error + var res DescribeSubnetResponse + + err = c.client.InvokeAction("DescribeSubnet", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_subnet_resource.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_subnet_resource.go new file mode 100644 index 0000000000..750be23dec --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_subnet_resource.go @@ -0,0 +1,60 @@ +//go:generate go run ../../private/cli/gen-api/main.go vpc DescribeSubnetResource + +package vpc + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" + . "github.com/ucloud/ucloud-sdk-go/service/vpc/types" +) + +type DescribeSubnetResourceRequest struct { + request.CommonBase + + // Required, 子网id + SubnetId string + + // Optional, 资源类型 + ResourceType string + + // Optional, 分页号 + Offset int + + // Optional, 单页limit + Limit int +} + +type DescribeSubnetResourceResponse struct { + response.CommonBase + + // 总数 + TotalCount int + + // 返回数据集 + DataSet []ResourceInfo +} + +// NewDescribeSubnetResourceRequest will create request of DescribeSubnetResource action. +func (c *VPCClient) NewDescribeSubnetResourceRequest() *DescribeSubnetResourceRequest { + cfg := c.client.GetConfig() + + return &DescribeSubnetResourceRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DescribeSubnetResource - 展示子网资源 +func (c *VPCClient) DescribeSubnetResource(req *DescribeSubnetResourceRequest) (*DescribeSubnetResourceResponse, error) { + var err error + var res DescribeSubnetResourceResponse + + err = c.client.InvokeAction("DescribeSubnetResource", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_vpc.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_vpc.go new file mode 100644 index 0000000000..74c1222df6 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_vpc.go @@ -0,0 +1,51 @@ +//go:generate go run ../../private/cli/gen-api/main.go vpc DescribeVPC + +package vpc + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" + . "github.com/ucloud/ucloud-sdk-go/service/vpc/types" +) + +type DescribeVPCRequest struct { + request.CommonBase + + // Optional, VPCId + VPCIds []string + + // Optional, 业务组名称 + Tag string +} + +type DescribeVPCResponse struct { + response.CommonBase + + // + DataSet []VPCInfoSet +} + +// NewDescribeVPCRequest will create request of DescribeVPC action. +func (c *VPCClient) NewDescribeVPCRequest() *DescribeVPCRequest { + cfg := c.client.GetConfig() + + return &DescribeVPCRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DescribeVPC - 获取VPC信息 +func (c *VPCClient) DescribeVPC(req *DescribeVPCRequest) (*DescribeVPCResponse, error) { + var err error + var res DescribeVPCResponse + + err = c.client.InvokeAction("DescribeVPC", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_vpcintercom.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_vpcintercom.go new file mode 100644 index 0000000000..8909a69538 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/describe_vpcintercom.go @@ -0,0 +1,68 @@ +//go:generate go run ../../private/cli/gen-api/main.go vpc DescribeVPCIntercom + +package vpc + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type DescribeVPCIntercomRequest struct { + request.CommonBase + + // Required, VPC短ID + VPCId string + + // Optional, 目的地域 + DstRegion string + + // Optional, 目的项目ID + DstProjectId string +} + +type DescribeVPCIntercomResponse struct { + response.CommonBase + + // VPC的地址空间 + Network []string + + // 所属地域 + DstRegion string + + // VPC名字 + Name string + + // 项目Id + ProjectId string + + // vpc_id + VPCId string + + // 业务组(未分组显示为 Default) + Tag string +} + +// NewDescribeVPCIntercomRequest will create request of DescribeVPCIntercom action. +func (c *VPCClient) NewDescribeVPCIntercomRequest() *DescribeVPCIntercomRequest { + cfg := c.client.GetConfig() + + return &DescribeVPCIntercomRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// DescribeVPCIntercom - 获取VPC互通信息 +func (c *VPCClient) DescribeVPCIntercom(req *DescribeVPCIntercomRequest) (*DescribeVPCIntercomResponse, error) { + var err error + var res DescribeVPCIntercomResponse + + err = c.client.InvokeAction("DescribeVPCIntercom", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/types/resource_info.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/types/resource_info.go new file mode 100644 index 0000000000..1522e8141b --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/types/resource_info.go @@ -0,0 +1,17 @@ +package types + +// ResourceInfo - 资源信息 +type ResourceInfo struct { + + // 资源名称 + Name string + + // 资源id + ResourceId string + + // 资源类型 + ResourceType int + + // ip地址 + IP string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/types/vpcinfo_set.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/types/vpcinfo_set.go new file mode 100644 index 0000000000..8d366216f5 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/types/vpcinfo_set.go @@ -0,0 +1,29 @@ +package types + +// VPCInfoSet - VPC信息 +type VPCInfoSet struct { + + // + VPCId string + + // + Network []string + + // + SubnetCount int + + // + CreateTime int // uxiao is string + + // + UpdateTime int // uxiao is string + + // + Tag string + + // + Remark string + + // + Name string +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/types/vpcsubnet_info_set.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/types/vpcsubnet_info_set.go new file mode 100644 index 0000000000..76e9ec3bb1 --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/types/vpcsubnet_info_set.go @@ -0,0 +1,50 @@ +package types + +// VPCSubnetInfoSet - DescribeSubnet +type VPCSubnetInfoSet struct { + + // VPC id + VPCId string + + // VPC名称 + VPCName string + + // 子网id + SubnetId string + + // 子网名称 + SubnetName string + + // 地址 + Zone string + + // 名称 + Name string + + // 备注 + Remark string + + // Tag + Tag string + + // 子网类型 + SubnetType int // uxiao is string + + // 子网网段 + Subnet string + + // 子网掩码 + Netmask string + + // 子网网关 + Gateway string + + // 创建时间 + CreateTime int + + // 虚拟路由 id + VRouterId string + + // 是否关联NATGW + HasNATGW bool +} diff --git a/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/update_subnet_attribute.go b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/update_subnet_attribute.go new file mode 100644 index 0000000000..a4580a5f9f --- /dev/null +++ b/vendor/github.com/ucloud/ucloud-sdk-go/service/vpc/update_subnet_attribute.go @@ -0,0 +1,50 @@ +//go:generate go run ../../private/cli/gen-api/main.go vpc UpdateSubnetAttribute + +package vpc + +import ( + "github.com/ucloud/ucloud-sdk-go/sdk/request" + "github.com/ucloud/ucloud-sdk-go/sdk/response" +) + +type UpdateSubnetAttributeRequest struct { + request.CommonBase + + // Required, 子网ID + SubnetId string + + // Optional, 子网名称(如果Name不填写,Tag必须填写) + Name string + + // Optional, 业务组名称(如果Tag不填写,Name必须填写) + Tag string +} + +type UpdateSubnetAttributeResponse struct { + response.CommonBase +} + +// NewUpdateSubnetAttributeRequest will create request of UpdateSubnetAttribute action. +func (c *VPCClient) NewUpdateSubnetAttributeRequest() *UpdateSubnetAttributeRequest { + cfg := c.client.GetConfig() + + return &UpdateSubnetAttributeRequest{ + CommonBase: request.CommonBase{ + Region: cfg.Region, + ProjectId: cfg.ProjectId, + }, + } +} + +// UpdateSubnetAttribute - 更新子网信息 +func (c *VPCClient) UpdateSubnetAttribute(req *UpdateSubnetAttributeRequest) (*UpdateSubnetAttributeResponse, error) { + var err error + var res UpdateSubnetAttributeResponse + + err = c.client.InvokeAction("UpdateSubnetAttribute", req, &res) + if err != nil { + return nil, err + } + + return &res, nil +} diff --git a/vendor/golang.org/x/crypto/LICENSE b/vendor/golang.org/x/crypto/LICENSE new file mode 100644 index 0000000000..6a66aea5ea --- /dev/null +++ b/vendor/golang.org/x/crypto/LICENSE @@ -0,0 +1,27 @@ +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. diff --git a/vendor/golang.org/x/crypto/PATENTS b/vendor/golang.org/x/crypto/PATENTS new file mode 100644 index 0000000000..733099041f --- /dev/null +++ b/vendor/golang.org/x/crypto/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go new file mode 100644 index 0000000000..9a887598ff --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go @@ -0,0 +1,951 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package terminal + +import ( + "bytes" + "io" + "sync" + "unicode/utf8" +) + +// EscapeCodes contains escape sequences that can be written to the terminal in +// order to achieve different styles of text. +type EscapeCodes struct { + // Foreground colors + Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte + + // Reset all attributes + Reset []byte +} + +var vt100EscapeCodes = EscapeCodes{ + Black: []byte{keyEscape, '[', '3', '0', 'm'}, + Red: []byte{keyEscape, '[', '3', '1', 'm'}, + Green: []byte{keyEscape, '[', '3', '2', 'm'}, + Yellow: []byte{keyEscape, '[', '3', '3', 'm'}, + Blue: []byte{keyEscape, '[', '3', '4', 'm'}, + Magenta: []byte{keyEscape, '[', '3', '5', 'm'}, + Cyan: []byte{keyEscape, '[', '3', '6', 'm'}, + White: []byte{keyEscape, '[', '3', '7', 'm'}, + + Reset: []byte{keyEscape, '[', '0', 'm'}, +} + +// Terminal contains the state for running a VT100 terminal that is capable of +// reading lines of input. +type Terminal struct { + // AutoCompleteCallback, if non-null, is called for each keypress with + // the full input line and the current position of the cursor (in + // bytes, as an index into |line|). If it returns ok=false, the key + // press is processed normally. Otherwise it returns a replacement line + // and the new cursor position. + AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool) + + // Escape contains a pointer to the escape codes for this terminal. + // It's always a valid pointer, although the escape codes themselves + // may be empty if the terminal doesn't support them. + Escape *EscapeCodes + + // lock protects the terminal and the state in this object from + // concurrent processing of a key press and a Write() call. + lock sync.Mutex + + c io.ReadWriter + prompt []rune + + // line is the current line being entered. + line []rune + // pos is the logical position of the cursor in line + pos int + // echo is true if local echo is enabled + echo bool + // pasteActive is true iff there is a bracketed paste operation in + // progress. + pasteActive bool + + // cursorX contains the current X value of the cursor where the left + // edge is 0. cursorY contains the row number where the first row of + // the current line is 0. + cursorX, cursorY int + // maxLine is the greatest value of cursorY so far. + maxLine int + + termWidth, termHeight int + + // outBuf contains the terminal data to be sent. + outBuf []byte + // remainder contains the remainder of any partial key sequences after + // a read. It aliases into inBuf. + remainder []byte + inBuf [256]byte + + // history contains previously entered commands so that they can be + // accessed with the up and down keys. + history stRingBuffer + // historyIndex stores the currently accessed history entry, where zero + // means the immediately previous entry. + historyIndex int + // When navigating up and down the history it's possible to return to + // the incomplete, initial line. That value is stored in + // historyPending. + historyPending string +} + +// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is +// a local terminal, that terminal must first have been put into raw mode. +// prompt is a string that is written at the start of each input line (i.e. +// "> "). +func NewTerminal(c io.ReadWriter, prompt string) *Terminal { + return &Terminal{ + Escape: &vt100EscapeCodes, + c: c, + prompt: []rune(prompt), + termWidth: 80, + termHeight: 24, + echo: true, + historyIndex: -1, + } +} + +const ( + keyCtrlD = 4 + keyCtrlU = 21 + keyEnter = '\r' + keyEscape = 27 + keyBackspace = 127 + keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota + keyUp + keyDown + keyLeft + keyRight + keyAltLeft + keyAltRight + keyHome + keyEnd + keyDeleteWord + keyDeleteLine + keyClearScreen + keyPasteStart + keyPasteEnd +) + +var ( + crlf = []byte{'\r', '\n'} + pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'} + pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'} +) + +// bytesToKey tries to parse a key sequence from b. If successful, it returns +// the key and the remainder of the input. Otherwise it returns utf8.RuneError. +func bytesToKey(b []byte, pasteActive bool) (rune, []byte) { + if len(b) == 0 { + return utf8.RuneError, nil + } + + if !pasteActive { + switch b[0] { + case 1: // ^A + return keyHome, b[1:] + case 5: // ^E + return keyEnd, b[1:] + case 8: // ^H + return keyBackspace, b[1:] + case 11: // ^K + return keyDeleteLine, b[1:] + case 12: // ^L + return keyClearScreen, b[1:] + case 23: // ^W + return keyDeleteWord, b[1:] + } + } + + if b[0] != keyEscape { + if !utf8.FullRune(b) { + return utf8.RuneError, b + } + r, l := utf8.DecodeRune(b) + return r, b[l:] + } + + if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' { + switch b[2] { + case 'A': + return keyUp, b[3:] + case 'B': + return keyDown, b[3:] + case 'C': + return keyRight, b[3:] + case 'D': + return keyLeft, b[3:] + case 'H': + return keyHome, b[3:] + case 'F': + return keyEnd, b[3:] + } + } + + if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' { + switch b[5] { + case 'C': + return keyAltRight, b[6:] + case 'D': + return keyAltLeft, b[6:] + } + } + + if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) { + return keyPasteStart, b[6:] + } + + if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) { + return keyPasteEnd, b[6:] + } + + // If we get here then we have a key that we don't recognise, or a + // partial sequence. It's not clear how one should find the end of a + // sequence without knowing them all, but it seems that [a-zA-Z~] only + // appears at the end of a sequence. + for i, c := range b[0:] { + if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' { + return keyUnknown, b[i+1:] + } + } + + return utf8.RuneError, b +} + +// queue appends data to the end of t.outBuf +func (t *Terminal) queue(data []rune) { + t.outBuf = append(t.outBuf, []byte(string(data))...) +} + +var eraseUnderCursor = []rune{' ', keyEscape, '[', 'D'} +var space = []rune{' '} + +func isPrintable(key rune) bool { + isInSurrogateArea := key >= 0xd800 && key <= 0xdbff + return key >= 32 && !isInSurrogateArea +} + +// moveCursorToPos appends data to t.outBuf which will move the cursor to the +// given, logical position in the text. +func (t *Terminal) moveCursorToPos(pos int) { + if !t.echo { + return + } + + x := visualLength(t.prompt) + pos + y := x / t.termWidth + x = x % t.termWidth + + up := 0 + if y < t.cursorY { + up = t.cursorY - y + } + + down := 0 + if y > t.cursorY { + down = y - t.cursorY + } + + left := 0 + if x < t.cursorX { + left = t.cursorX - x + } + + right := 0 + if x > t.cursorX { + right = x - t.cursorX + } + + t.cursorX = x + t.cursorY = y + t.move(up, down, left, right) +} + +func (t *Terminal) move(up, down, left, right int) { + movement := make([]rune, 3*(up+down+left+right)) + m := movement + for i := 0; i < up; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'A' + m = m[3:] + } + for i := 0; i < down; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'B' + m = m[3:] + } + for i := 0; i < left; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'D' + m = m[3:] + } + for i := 0; i < right; i++ { + m[0] = keyEscape + m[1] = '[' + m[2] = 'C' + m = m[3:] + } + + t.queue(movement) +} + +func (t *Terminal) clearLineToRight() { + op := []rune{keyEscape, '[', 'K'} + t.queue(op) +} + +const maxLineLength = 4096 + +func (t *Terminal) setLine(newLine []rune, newPos int) { + if t.echo { + t.moveCursorToPos(0) + t.writeLine(newLine) + for i := len(newLine); i < len(t.line); i++ { + t.writeLine(space) + } + t.moveCursorToPos(newPos) + } + t.line = newLine + t.pos = newPos +} + +func (t *Terminal) advanceCursor(places int) { + t.cursorX += places + t.cursorY += t.cursorX / t.termWidth + if t.cursorY > t.maxLine { + t.maxLine = t.cursorY + } + t.cursorX = t.cursorX % t.termWidth + + if places > 0 && t.cursorX == 0 { + // Normally terminals will advance the current position + // when writing a character. But that doesn't happen + // for the last character in a line. However, when + // writing a character (except a new line) that causes + // a line wrap, the position will be advanced two + // places. + // + // So, if we are stopping at the end of a line, we + // need to write a newline so that our cursor can be + // advanced to the next line. + t.outBuf = append(t.outBuf, '\r', '\n') + } +} + +func (t *Terminal) eraseNPreviousChars(n int) { + if n == 0 { + return + } + + if t.pos < n { + n = t.pos + } + t.pos -= n + t.moveCursorToPos(t.pos) + + copy(t.line[t.pos:], t.line[n+t.pos:]) + t.line = t.line[:len(t.line)-n] + if t.echo { + t.writeLine(t.line[t.pos:]) + for i := 0; i < n; i++ { + t.queue(space) + } + t.advanceCursor(n) + t.moveCursorToPos(t.pos) + } +} + +// countToLeftWord returns then number of characters from the cursor to the +// start of the previous word. +func (t *Terminal) countToLeftWord() int { + if t.pos == 0 { + return 0 + } + + pos := t.pos - 1 + for pos > 0 { + if t.line[pos] != ' ' { + break + } + pos-- + } + for pos > 0 { + if t.line[pos] == ' ' { + pos++ + break + } + pos-- + } + + return t.pos - pos +} + +// countToRightWord returns then number of characters from the cursor to the +// start of the next word. +func (t *Terminal) countToRightWord() int { + pos := t.pos + for pos < len(t.line) { + if t.line[pos] == ' ' { + break + } + pos++ + } + for pos < len(t.line) { + if t.line[pos] != ' ' { + break + } + pos++ + } + return pos - t.pos +} + +// visualLength returns the number of visible glyphs in s. +func visualLength(runes []rune) int { + inEscapeSeq := false + length := 0 + + for _, r := range runes { + switch { + case inEscapeSeq: + if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') { + inEscapeSeq = false + } + case r == '\x1b': + inEscapeSeq = true + default: + length++ + } + } + + return length +} + +// handleKey processes the given key and, optionally, returns a line of text +// that the user has entered. +func (t *Terminal) handleKey(key rune) (line string, ok bool) { + if t.pasteActive && key != keyEnter { + t.addKeyToLine(key) + return + } + + switch key { + case keyBackspace: + if t.pos == 0 { + return + } + t.eraseNPreviousChars(1) + case keyAltLeft: + // move left by a word. + t.pos -= t.countToLeftWord() + t.moveCursorToPos(t.pos) + case keyAltRight: + // move right by a word. + t.pos += t.countToRightWord() + t.moveCursorToPos(t.pos) + case keyLeft: + if t.pos == 0 { + return + } + t.pos-- + t.moveCursorToPos(t.pos) + case keyRight: + if t.pos == len(t.line) { + return + } + t.pos++ + t.moveCursorToPos(t.pos) + case keyHome: + if t.pos == 0 { + return + } + t.pos = 0 + t.moveCursorToPos(t.pos) + case keyEnd: + if t.pos == len(t.line) { + return + } + t.pos = len(t.line) + t.moveCursorToPos(t.pos) + case keyUp: + entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1) + if !ok { + return "", false + } + if t.historyIndex == -1 { + t.historyPending = string(t.line) + } + t.historyIndex++ + runes := []rune(entry) + t.setLine(runes, len(runes)) + case keyDown: + switch t.historyIndex { + case -1: + return + case 0: + runes := []rune(t.historyPending) + t.setLine(runes, len(runes)) + t.historyIndex-- + default: + entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1) + if ok { + t.historyIndex-- + runes := []rune(entry) + t.setLine(runes, len(runes)) + } + } + case keyEnter: + t.moveCursorToPos(len(t.line)) + t.queue([]rune("\r\n")) + line = string(t.line) + ok = true + t.line = t.line[:0] + t.pos = 0 + t.cursorX = 0 + t.cursorY = 0 + t.maxLine = 0 + case keyDeleteWord: + // Delete zero or more spaces and then one or more characters. + t.eraseNPreviousChars(t.countToLeftWord()) + case keyDeleteLine: + // Delete everything from the current cursor position to the + // end of line. + for i := t.pos; i < len(t.line); i++ { + t.queue(space) + t.advanceCursor(1) + } + t.line = t.line[:t.pos] + t.moveCursorToPos(t.pos) + case keyCtrlD: + // Erase the character under the current position. + // The EOF case when the line is empty is handled in + // readLine(). + if t.pos < len(t.line) { + t.pos++ + t.eraseNPreviousChars(1) + } + case keyCtrlU: + t.eraseNPreviousChars(t.pos) + case keyClearScreen: + // Erases the screen and moves the cursor to the home position. + t.queue([]rune("\x1b[2J\x1b[H")) + t.queue(t.prompt) + t.cursorX, t.cursorY = 0, 0 + t.advanceCursor(visualLength(t.prompt)) + t.setLine(t.line, t.pos) + default: + if t.AutoCompleteCallback != nil { + prefix := string(t.line[:t.pos]) + suffix := string(t.line[t.pos:]) + + t.lock.Unlock() + newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key) + t.lock.Lock() + + if completeOk { + t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos])) + return + } + } + if !isPrintable(key) { + return + } + if len(t.line) == maxLineLength { + return + } + t.addKeyToLine(key) + } + return +} + +// addKeyToLine inserts the given key at the current position in the current +// line. +func (t *Terminal) addKeyToLine(key rune) { + if len(t.line) == cap(t.line) { + newLine := make([]rune, len(t.line), 2*(1+len(t.line))) + copy(newLine, t.line) + t.line = newLine + } + t.line = t.line[:len(t.line)+1] + copy(t.line[t.pos+1:], t.line[t.pos:]) + t.line[t.pos] = key + if t.echo { + t.writeLine(t.line[t.pos:]) + } + t.pos++ + t.moveCursorToPos(t.pos) +} + +func (t *Terminal) writeLine(line []rune) { + for len(line) != 0 { + remainingOnLine := t.termWidth - t.cursorX + todo := len(line) + if todo > remainingOnLine { + todo = remainingOnLine + } + t.queue(line[:todo]) + t.advanceCursor(visualLength(line[:todo])) + line = line[todo:] + } +} + +// writeWithCRLF writes buf to w but replaces all occurrences of \n with \r\n. +func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) { + for len(buf) > 0 { + i := bytes.IndexByte(buf, '\n') + todo := len(buf) + if i >= 0 { + todo = i + } + + var nn int + nn, err = w.Write(buf[:todo]) + n += nn + if err != nil { + return n, err + } + buf = buf[todo:] + + if i >= 0 { + if _, err = w.Write(crlf); err != nil { + return n, err + } + n++ + buf = buf[1:] + } + } + + return n, nil +} + +func (t *Terminal) Write(buf []byte) (n int, err error) { + t.lock.Lock() + defer t.lock.Unlock() + + if t.cursorX == 0 && t.cursorY == 0 { + // This is the easy case: there's nothing on the screen that we + // have to move out of the way. + return writeWithCRLF(t.c, buf) + } + + // We have a prompt and possibly user input on the screen. We + // have to clear it first. + t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */) + t.cursorX = 0 + t.clearLineToRight() + + for t.cursorY > 0 { + t.move(1 /* up */, 0, 0, 0) + t.cursorY-- + t.clearLineToRight() + } + + if _, err = t.c.Write(t.outBuf); err != nil { + return + } + t.outBuf = t.outBuf[:0] + + if n, err = writeWithCRLF(t.c, buf); err != nil { + return + } + + t.writeLine(t.prompt) + if t.echo { + t.writeLine(t.line) + } + + t.moveCursorToPos(t.pos) + + if _, err = t.c.Write(t.outBuf); err != nil { + return + } + t.outBuf = t.outBuf[:0] + return +} + +// ReadPassword temporarily changes the prompt and reads a password, without +// echo, from the terminal. +func (t *Terminal) ReadPassword(prompt string) (line string, err error) { + t.lock.Lock() + defer t.lock.Unlock() + + oldPrompt := t.prompt + t.prompt = []rune(prompt) + t.echo = false + + line, err = t.readLine() + + t.prompt = oldPrompt + t.echo = true + + return +} + +// ReadLine returns a line of input from the terminal. +func (t *Terminal) ReadLine() (line string, err error) { + t.lock.Lock() + defer t.lock.Unlock() + + return t.readLine() +} + +func (t *Terminal) readLine() (line string, err error) { + // t.lock must be held at this point + + if t.cursorX == 0 && t.cursorY == 0 { + t.writeLine(t.prompt) + t.c.Write(t.outBuf) + t.outBuf = t.outBuf[:0] + } + + lineIsPasted := t.pasteActive + + for { + rest := t.remainder + lineOk := false + for !lineOk { + var key rune + key, rest = bytesToKey(rest, t.pasteActive) + if key == utf8.RuneError { + break + } + if !t.pasteActive { + if key == keyCtrlD { + if len(t.line) == 0 { + return "", io.EOF + } + } + if key == keyPasteStart { + t.pasteActive = true + if len(t.line) == 0 { + lineIsPasted = true + } + continue + } + } else if key == keyPasteEnd { + t.pasteActive = false + continue + } + if !t.pasteActive { + lineIsPasted = false + } + line, lineOk = t.handleKey(key) + } + if len(rest) > 0 { + n := copy(t.inBuf[:], rest) + t.remainder = t.inBuf[:n] + } else { + t.remainder = nil + } + t.c.Write(t.outBuf) + t.outBuf = t.outBuf[:0] + if lineOk { + if t.echo { + t.historyIndex = -1 + t.history.Add(line) + } + if lineIsPasted { + err = ErrPasteIndicator + } + return + } + + // t.remainder is a slice at the beginning of t.inBuf + // containing a partial key sequence + readBuf := t.inBuf[len(t.remainder):] + var n int + + t.lock.Unlock() + n, err = t.c.Read(readBuf) + t.lock.Lock() + + if err != nil { + return + } + + t.remainder = t.inBuf[:n+len(t.remainder)] + } +} + +// SetPrompt sets the prompt to be used when reading subsequent lines. +func (t *Terminal) SetPrompt(prompt string) { + t.lock.Lock() + defer t.lock.Unlock() + + t.prompt = []rune(prompt) +} + +func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) { + // Move cursor to column zero at the start of the line. + t.move(t.cursorY, 0, t.cursorX, 0) + t.cursorX, t.cursorY = 0, 0 + t.clearLineToRight() + for t.cursorY < numPrevLines { + // Move down a line + t.move(0, 1, 0, 0) + t.cursorY++ + t.clearLineToRight() + } + // Move back to beginning. + t.move(t.cursorY, 0, 0, 0) + t.cursorX, t.cursorY = 0, 0 + + t.queue(t.prompt) + t.advanceCursor(visualLength(t.prompt)) + t.writeLine(t.line) + t.moveCursorToPos(t.pos) +} + +func (t *Terminal) SetSize(width, height int) error { + t.lock.Lock() + defer t.lock.Unlock() + + if width == 0 { + width = 1 + } + + oldWidth := t.termWidth + t.termWidth, t.termHeight = width, height + + switch { + case width == oldWidth: + // If the width didn't change then nothing else needs to be + // done. + return nil + case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0: + // If there is nothing on current line and no prompt printed, + // just do nothing + return nil + case width < oldWidth: + // Some terminals (e.g. xterm) will truncate lines that were + // too long when shinking. Others, (e.g. gnome-terminal) will + // attempt to wrap them. For the former, repainting t.maxLine + // works great, but that behaviour goes badly wrong in the case + // of the latter because they have doubled every full line. + + // We assume that we are working on a terminal that wraps lines + // and adjust the cursor position based on every previous line + // wrapping and turning into two. This causes the prompt on + // xterms to move upwards, which isn't great, but it avoids a + // huge mess with gnome-terminal. + if t.cursorX >= t.termWidth { + t.cursorX = t.termWidth - 1 + } + t.cursorY *= 2 + t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2) + case width > oldWidth: + // If the terminal expands then our position calculations will + // be wrong in the future because we think the cursor is + // |t.pos| chars into the string, but there will be a gap at + // the end of any wrapped line. + // + // But the position will actually be correct until we move, so + // we can move back to the beginning and repaint everything. + t.clearAndRepaintLinePlusNPrevious(t.maxLine) + } + + _, err := t.c.Write(t.outBuf) + t.outBuf = t.outBuf[:0] + return err +} + +type pasteIndicatorError struct{} + +func (pasteIndicatorError) Error() string { + return "terminal: ErrPasteIndicator not correctly handled" +} + +// ErrPasteIndicator may be returned from ReadLine as the error, in addition +// to valid line data. It indicates that bracketed paste mode is enabled and +// that the returned line consists only of pasted data. Programs may wish to +// interpret pasted data more literally than typed data. +var ErrPasteIndicator = pasteIndicatorError{} + +// SetBracketedPasteMode requests that the terminal bracket paste operations +// with markers. Not all terminals support this but, if it is supported, then +// enabling this mode will stop any autocomplete callback from running due to +// pastes. Additionally, any lines that are completely pasted will be returned +// from ReadLine with the error set to ErrPasteIndicator. +func (t *Terminal) SetBracketedPasteMode(on bool) { + if on { + io.WriteString(t.c, "\x1b[?2004h") + } else { + io.WriteString(t.c, "\x1b[?2004l") + } +} + +// stRingBuffer is a ring buffer of strings. +type stRingBuffer struct { + // entries contains max elements. + entries []string + max int + // head contains the index of the element most recently added to the ring. + head int + // size contains the number of elements in the ring. + size int +} + +func (s *stRingBuffer) Add(a string) { + if s.entries == nil { + const defaultNumEntries = 100 + s.entries = make([]string, defaultNumEntries) + s.max = defaultNumEntries + } + + s.head = (s.head + 1) % s.max + s.entries[s.head] = a + if s.size < s.max { + s.size++ + } +} + +// NthPreviousEntry returns the value passed to the nth previous call to Add. +// If n is zero then the immediately prior value is returned, if one, then the +// next most recent, and so on. If such an element doesn't exist then ok is +// false. +func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) { + if n >= s.size { + return "", false + } + index := s.head - n + if index < 0 { + index += s.max + } + return s.entries[index], true +} + +// readPasswordLine reads from reader until it finds \n or io.EOF. +// The slice returned does not include the \n. +// readPasswordLine also ignores any \r it finds. +func readPasswordLine(reader io.Reader) ([]byte, error) { + var buf [1]byte + var ret []byte + + for { + n, err := reader.Read(buf[:]) + if n > 0 { + switch buf[0] { + case '\n': + return ret, nil + case '\r': + // remove \r from passwords on Windows + default: + ret = append(ret, buf[0]) + } + continue + } + if err != nil { + if err == io.EOF && len(ret) > 0 { + return ret, nil + } + return ret, err + } + } +} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util.go b/vendor/golang.org/x/crypto/ssh/terminal/util.go new file mode 100644 index 0000000000..731c89a284 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util.go @@ -0,0 +1,114 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd + +// Package terminal provides support functions for dealing with terminals, as +// commonly found on UNIX systems. +// +// Putting a terminal into raw mode is the most common requirement: +// +// oldState, err := terminal.MakeRaw(0) +// if err != nil { +// panic(err) +// } +// defer terminal.Restore(0, oldState) +package terminal // import "golang.org/x/crypto/ssh/terminal" + +import ( + "golang.org/x/sys/unix" +) + +// State contains the state of a terminal. +type State struct { + termios unix.Termios +} + +// IsTerminal returns true if the given file descriptor is a terminal. +func IsTerminal(fd int) bool { + _, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + return err == nil +} + +// MakeRaw put the terminal connected to the given file descriptor into raw +// mode and returns the previous state of the terminal so that it can be +// restored. +func MakeRaw(fd int) (*State, error) { + termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + if err != nil { + return nil, err + } + + oldState := State{termios: *termios} + + // This attempts to replicate the behaviour documented for cfmakeraw in + // the termios(3) manpage. + termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON + termios.Oflag &^= unix.OPOST + termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN + termios.Cflag &^= unix.CSIZE | unix.PARENB + termios.Cflag |= unix.CS8 + termios.Cc[unix.VMIN] = 1 + termios.Cc[unix.VTIME] = 0 + if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil { + return nil, err + } + + return &oldState, nil +} + +// GetState returns the current state of a terminal which may be useful to +// restore the terminal after a signal. +func GetState(fd int) (*State, error) { + termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + if err != nil { + return nil, err + } + + return &State{termios: *termios}, nil +} + +// Restore restores the terminal connected to the given file descriptor to a +// previous state. +func Restore(fd int, state *State) error { + return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios) +} + +// GetSize returns the dimensions of the given terminal. +func GetSize(fd int) (width, height int, err error) { + ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ) + if err != nil { + return -1, -1, err + } + return int(ws.Col), int(ws.Row), nil +} + +// passwordReader is an io.Reader that reads from a specific file descriptor. +type passwordReader int + +func (r passwordReader) Read(buf []byte) (int, error) { + return unix.Read(int(r), buf) +} + +// ReadPassword reads a line of input from a terminal without local echo. This +// is commonly used for inputting passwords and other sensitive data. The slice +// returned does not include the \n. +func ReadPassword(fd int) ([]byte, error) { + termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + if err != nil { + return nil, err + } + + newState := *termios + newState.Lflag &^= unix.ECHO + newState.Lflag |= unix.ICANON | unix.ISIG + newState.Iflag |= unix.ICRNL + if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil { + return nil, err + } + + defer unix.IoctlSetTermios(fd, ioctlWriteTermios, termios) + + return readPasswordLine(passwordReader(fd)) +} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go b/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go new file mode 100644 index 0000000000..cb23a59049 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go @@ -0,0 +1,12 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin dragonfly freebsd netbsd openbsd + +package terminal + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TIOCGETA +const ioctlWriteTermios = unix.TIOCSETA diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go b/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go new file mode 100644 index 0000000000..5fadfe8a1d --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go @@ -0,0 +1,10 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package terminal + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TCGETS +const ioctlWriteTermios = unix.TCSETS diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go b/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go new file mode 100644 index 0000000000..799f049f04 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go @@ -0,0 +1,58 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package terminal provides support functions for dealing with terminals, as +// commonly found on UNIX systems. +// +// Putting a terminal into raw mode is the most common requirement: +// +// oldState, err := terminal.MakeRaw(0) +// if err != nil { +// panic(err) +// } +// defer terminal.Restore(0, oldState) +package terminal + +import ( + "fmt" + "runtime" +) + +type State struct{} + +// IsTerminal returns true if the given file descriptor is a terminal. +func IsTerminal(fd int) bool { + return false +} + +// MakeRaw put the terminal connected to the given file descriptor into raw +// mode and returns the previous state of the terminal so that it can be +// restored. +func MakeRaw(fd int) (*State, error) { + return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +// GetState returns the current state of a terminal which may be useful to +// restore the terminal after a signal. +func GetState(fd int) (*State, error) { + return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +// Restore restores the terminal connected to the given file descriptor to a +// previous state. +func Restore(fd int, state *State) error { + return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +// GetSize returns the dimensions of the given terminal. +func GetSize(fd int) (width, height int, err error) { + return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +// ReadPassword reads a line of input from a terminal without local echo. This +// is commonly used for inputting passwords and other sensitive data. The slice +// returned does not include the \n. +func ReadPassword(fd int) ([]byte, error) { + return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go b/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go new file mode 100644 index 0000000000..9e41b9f43f --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go @@ -0,0 +1,124 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build solaris + +package terminal // import "golang.org/x/crypto/ssh/terminal" + +import ( + "golang.org/x/sys/unix" + "io" + "syscall" +) + +// State contains the state of a terminal. +type State struct { + termios unix.Termios +} + +// IsTerminal returns true if the given file descriptor is a terminal. +func IsTerminal(fd int) bool { + _, err := unix.IoctlGetTermio(fd, unix.TCGETA) + return err == nil +} + +// ReadPassword reads a line of input from a terminal without local echo. This +// is commonly used for inputting passwords and other sensitive data. The slice +// returned does not include the \n. +func ReadPassword(fd int) ([]byte, error) { + // see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c + val, err := unix.IoctlGetTermios(fd, unix.TCGETS) + if err != nil { + return nil, err + } + oldState := *val + + newState := oldState + newState.Lflag &^= syscall.ECHO + newState.Lflag |= syscall.ICANON | syscall.ISIG + newState.Iflag |= syscall.ICRNL + err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState) + if err != nil { + return nil, err + } + + defer unix.IoctlSetTermios(fd, unix.TCSETS, &oldState) + + var buf [16]byte + var ret []byte + for { + n, err := syscall.Read(fd, buf[:]) + if err != nil { + return nil, err + } + if n == 0 { + if len(ret) == 0 { + return nil, io.EOF + } + break + } + if buf[n-1] == '\n' { + n-- + } + ret = append(ret, buf[:n]...) + if n < len(buf) { + break + } + } + + return ret, nil +} + +// MakeRaw puts the terminal connected to the given file descriptor into raw +// mode and returns the previous state of the terminal so that it can be +// restored. +// see http://cr.illumos.org/~webrev/andy_js/1060/ +func MakeRaw(fd int) (*State, error) { + termios, err := unix.IoctlGetTermios(fd, unix.TCGETS) + if err != nil { + return nil, err + } + + oldState := State{termios: *termios} + + termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON + termios.Oflag &^= unix.OPOST + termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN + termios.Cflag &^= unix.CSIZE | unix.PARENB + termios.Cflag |= unix.CS8 + termios.Cc[unix.VMIN] = 1 + termios.Cc[unix.VTIME] = 0 + + if err := unix.IoctlSetTermios(fd, unix.TCSETS, termios); err != nil { + return nil, err + } + + return &oldState, nil +} + +// Restore restores the terminal connected to the given file descriptor to a +// previous state. +func Restore(fd int, oldState *State) error { + return unix.IoctlSetTermios(fd, unix.TCSETS, &oldState.termios) +} + +// GetState returns the current state of a terminal which may be useful to +// restore the terminal after a signal. +func GetState(fd int) (*State, error) { + termios, err := unix.IoctlGetTermios(fd, unix.TCGETS) + if err != nil { + return nil, err + } + + return &State{termios: *termios}, nil +} + +// GetSize returns the dimensions of the given terminal. +func GetSize(fd int) (width, height int, err error) { + ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ) + if err != nil { + return 0, 0, err + } + return int(ws.Col), int(ws.Row), nil +} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go new file mode 100644 index 0000000000..8618955df7 --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go @@ -0,0 +1,103 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build windows + +// Package terminal provides support functions for dealing with terminals, as +// commonly found on UNIX systems. +// +// Putting a terminal into raw mode is the most common requirement: +// +// oldState, err := terminal.MakeRaw(0) +// if err != nil { +// panic(err) +// } +// defer terminal.Restore(0, oldState) +package terminal + +import ( + "os" + + "golang.org/x/sys/windows" +) + +type State struct { + mode uint32 +} + +// IsTerminal returns true if the given file descriptor is a terminal. +func IsTerminal(fd int) bool { + var st uint32 + err := windows.GetConsoleMode(windows.Handle(fd), &st) + return err == nil +} + +// MakeRaw put the terminal connected to the given file descriptor into raw +// mode and returns the previous state of the terminal so that it can be +// restored. +func MakeRaw(fd int) (*State, error) { + var st uint32 + if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { + return nil, err + } + raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) + if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil { + return nil, err + } + return &State{st}, nil +} + +// GetState returns the current state of a terminal which may be useful to +// restore the terminal after a signal. +func GetState(fd int) (*State, error) { + var st uint32 + if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { + return nil, err + } + return &State{st}, nil +} + +// Restore restores the terminal connected to the given file descriptor to a +// previous state. +func Restore(fd int, state *State) error { + return windows.SetConsoleMode(windows.Handle(fd), state.mode) +} + +// GetSize returns the dimensions of the given terminal. +func GetSize(fd int) (width, height int, err error) { + var info windows.ConsoleScreenBufferInfo + if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { + return 0, 0, err + } + return int(info.Size.X), int(info.Size.Y), nil +} + +// ReadPassword reads a line of input from a terminal without local echo. This +// is commonly used for inputting passwords and other sensitive data. The slice +// returned does not include the \n. +func ReadPassword(fd int) ([]byte, error) { + var st uint32 + if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { + return nil, err + } + old := st + + st &^= (windows.ENABLE_ECHO_INPUT) + st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) + if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil { + return nil, err + } + + defer windows.SetConsoleMode(windows.Handle(fd), old) + + var h windows.Handle + p, _ := windows.GetCurrentProcess() + if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil { + return nil, err + } + + f := os.NewFile(uintptr(h), "stdin") + defer f.Close() + return readPasswordLine(f) +} diff --git a/vendor/golang.org/x/net/LICENSE b/vendor/golang.org/x/net/LICENSE new file mode 100644 index 0000000000..6a66aea5ea --- /dev/null +++ b/vendor/golang.org/x/net/LICENSE @@ -0,0 +1,27 @@ +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. diff --git a/vendor/golang.org/x/net/PATENTS b/vendor/golang.org/x/net/PATENTS new file mode 100644 index 0000000000..733099041f --- /dev/null +++ b/vendor/golang.org/x/net/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/net/publicsuffix/list.go b/vendor/golang.org/x/net/publicsuffix/list.go new file mode 100644 index 0000000000..fea98a8fd7 --- /dev/null +++ b/vendor/golang.org/x/net/publicsuffix/list.go @@ -0,0 +1,170 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run gen.go + +// Package publicsuffix provides a public suffix list based on data from +// https://publicsuffix.org/ +// +// A public suffix is one under which Internet users can directly register +// names. It is related to, but different from, a TLD (top level domain). +// +// "com" is a TLD (top level domain). Top level means it has no dots. +// +// "com" is also a public suffix. Amazon and Google have registered different +// siblings under that domain: "amazon.com" and "google.com". +// +// "au" is another TLD, again because it has no dots. But it's not "amazon.au". +// Instead, it's "amazon.com.au". +// +// "com.au" isn't an actual TLD, because it's not at the top level (it has +// dots). But it is an eTLD (effective TLD), because that's the branching point +// for domain name registrars. +// +// Another name for "an eTLD" is "a public suffix". Often, what's more of +// interest is the eTLD+1, or one more label than the public suffix. For +// example, browsers partition read/write access to HTTP cookies according to +// the eTLD+1. Web pages served from "amazon.com.au" can't read cookies from +// "google.com.au", but web pages served from "maps.google.com" can share +// cookies from "www.google.com", so you don't have to sign into Google Maps +// separately from signing into Google Web Search. Note that all four of those +// domains have 3 labels and 2 dots. The first two domains are each an eTLD+1, +// the last two are not (but share the same eTLD+1: "google.com"). +// +// All of these domains have the same eTLD+1: +// - "www.books.amazon.co.uk" +// - "books.amazon.co.uk" +// - "amazon.co.uk" +// Specifically, the eTLD+1 is "amazon.co.uk", because the eTLD is "co.uk". +// +// There is no closed form algorithm to calculate the eTLD of a domain. +// Instead, the calculation is data driven. This package provides a +// pre-compiled snapshot of Mozilla's PSL (Public Suffix List) data at +// https://publicsuffix.org/ +package publicsuffix // import "golang.org/x/net/publicsuffix" + +// TODO: specify case sensitivity and leading/trailing dot behavior for +// func PublicSuffix and func EffectiveTLDPlusOne. + +import ( + "fmt" + "net/http/cookiejar" + "strings" +) + +// List implements the cookiejar.PublicSuffixList interface by calling the +// PublicSuffix function. +var List cookiejar.PublicSuffixList = list{} + +type list struct{} + +func (list) PublicSuffix(domain string) string { + ps, _ := PublicSuffix(domain) + return ps +} + +func (list) String() string { + return version +} + +// PublicSuffix returns the public suffix of the domain using a copy of the +// publicsuffix.org database compiled into the library. +// +// icann is whether the public suffix is managed by the Internet Corporation +// for Assigned Names and Numbers. If not, the public suffix is privately +// managed. For example, foo.org and foo.co.uk are ICANN domains, +// foo.dyndns.org and foo.blogspot.co.uk are private domains. +// +// Use cases for distinguishing ICANN domains like foo.com from private +// domains like foo.appspot.com can be found at +// https://wiki.mozilla.org/Public_Suffix_List/Use_Cases +func PublicSuffix(domain string) (publicSuffix string, icann bool) { + lo, hi := uint32(0), uint32(numTLD) + s, suffix, wildcard := domain, len(domain), false +loop: + for { + dot := strings.LastIndex(s, ".") + if wildcard { + suffix = 1 + dot + } + if lo == hi { + break + } + f := find(s[1+dot:], lo, hi) + if f == notFound { + break + } + + u := nodes[f] >> (nodesBitsTextOffset + nodesBitsTextLength) + icann = u&(1<>= nodesBitsICANN + u = children[u&(1<>= childrenBitsLo + hi = u & (1<>= childrenBitsHi + switch u & (1<>= childrenBitsNodeType + wildcard = u&(1<>= nodesBitsTextLength + offset := x & (1<