mirror of
https://github.com/openziti/ziti.git
synced 2026-10-11 23:12:35 +00:00
Refactor tutorial code. Add initial demo commands
This commit is contained in:
@@ -34,6 +34,7 @@ import (
|
||||
|
||||
// global state used by all subcommands are located here for easy discovery
|
||||
var verbose bool
|
||||
var removeJwt bool
|
||||
var keyAlg config.KeyAlgVar
|
||||
var jwtpath, outpath, keyPath, certPath, idname, caOverride, username, password string
|
||||
|
||||
@@ -85,6 +86,7 @@ func NewEnrollCommand() *cobra.Command {
|
||||
enrollSubCmd.Flags().StringVarP(&caOverride, "ca", "", "", "Additional trusted certificates")
|
||||
enrollSubCmd.Flags().StringVarP(&username, "username", "u", "", "Username for updb enrollment, prompted if not provided and necessary")
|
||||
enrollSubCmd.Flags().StringVarP(&password, "password", "p", "", "Password for updb enrollment, prompted if not provided and necessary")
|
||||
enrollSubCmd.Flags().BoolVar(&removeJwt, "rm", false, "Remove the JWT on success")
|
||||
|
||||
keyAlg.Set("RSA") // set default
|
||||
enrollSubCmd.Flags().VarP(&keyAlg, "keyAlg", "a", "Crypto algorithm to use when generating private key")
|
||||
@@ -170,7 +172,13 @@ func processEnrollment() error {
|
||||
flags.Password = password
|
||||
}
|
||||
|
||||
return enroll.EnrollUpdb(flags)
|
||||
err = enroll.EnrollUpdb(flags)
|
||||
if err == nil {
|
||||
if rmErr := os.Remove(jwtpath); rmErr != nil {
|
||||
pfxlog.Logger().WithError(rmErr).Warnf("unable to remove JWT file as requested: %v", jwtpath)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
conf, err := enroll.Enroll(flags)
|
||||
@@ -188,6 +196,10 @@ func processEnrollment() error {
|
||||
enc.SetEscapeHTML(false)
|
||||
encErr := enc.Encode(&conf)
|
||||
|
||||
if err = os.Remove(jwtpath); err != nil {
|
||||
pfxlog.Logger().WithError(err).Warnf("unable to remove JWT file as requested: %v", jwtpath)
|
||||
}
|
||||
|
||||
if encErr == nil {
|
||||
pfxlog.Logger().Infof("enrolled successfully. identity file written to: %s", outpath)
|
||||
return nil
|
||||
|
||||
@@ -23,9 +23,9 @@ import (
|
||||
"github.com/openziti/foundation/agent"
|
||||
"github.com/openziti/foundation/identity/dotziti"
|
||||
"github.com/openziti/foundation/identity/identity"
|
||||
"github.com/openziti/transport"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/config"
|
||||
"github.com/openziti/transport"
|
||||
"github.com/spf13/cobra"
|
||||
"net"
|
||||
"strings"
|
||||
@@ -180,9 +180,11 @@ func (cmd *dialerCmd) connect() net.Conn {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, id, err := dotziti.LoadIdentity(cmd.identity)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
id := &identity.TokenId{Token: "test"}
|
||||
if endpoint.Type() != "tcp" || !cmd.direct {
|
||||
if _, id, err = dotziti.LoadIdentity(cmd.identity); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.direct {
|
||||
|
||||
@@ -22,9 +22,9 @@ import (
|
||||
"github.com/openziti/foundation/agent"
|
||||
"github.com/openziti/foundation/identity/dotziti"
|
||||
"github.com/openziti/foundation/identity/identity"
|
||||
"github.com/openziti/transport"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/config"
|
||||
"github.com/openziti/transport"
|
||||
loop3_pb "github.com/openziti/ziti/ziti-fabric-test/subcmd/loop3/pb"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -70,7 +70,7 @@ func (cmd *listenerCmd) run(_ *cobra.Command, args []string) {
|
||||
var err error
|
||||
shutdownClean := false
|
||||
if err = agent.Listen(agent.Options{ShutdownCleanup: &shutdownClean}); err != nil {
|
||||
pfxlog.Logger().WithError(err).Error("unable to start CLI agent")
|
||||
log.WithError(err).Error("unable to start CLI agent")
|
||||
}
|
||||
|
||||
var scenario *Scenario
|
||||
@@ -96,17 +96,21 @@ func (cmd *listenerCmd) run(_ *cobra.Command, args []string) {
|
||||
defer close(closer)
|
||||
}
|
||||
|
||||
log.Infof("binding to address '%v'", cmd.bindAddress)
|
||||
if strings.HasPrefix(cmd.bindAddress, "edge") {
|
||||
cmd.listenEdge()
|
||||
} else {
|
||||
_, id, err := dotziti.LoadIdentity(cmd.identity)
|
||||
bindAddress, err := transport.ParseAddress(cmd.bindAddress)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
bindAddress, err := transport.ParseAddress(cmd.bindAddress)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
id := &identity.TokenId{Token: "test"}
|
||||
if bindAddress.Type() != "tcp" {
|
||||
_, id, err = dotziti.LoadIdentity(cmd.identity)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
cmd.listen(bindAddress, id)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
//go:generate protoc -I ./ ./loop3.proto --go_out=paths=source_relative:./
|
||||
|
||||
package loop3_pb
|
||||
|
||||
// Here to provide the go:generate line above
|
||||
@@ -1,177 +1,277 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.19.1
|
||||
// source: loop3.proto
|
||||
|
||||
package loop3_pb
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Test struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
TxRequests int32 `protobuf:"varint,2,opt,name=txRequests,proto3" json:"txRequests,omitempty"`
|
||||
TxPacing int32 `protobuf:"varint,3,opt,name=txPacing,proto3" json:"txPacing,omitempty"`
|
||||
TxMaxJitter int32 `protobuf:"varint,4,opt,name=txMaxJitter,proto3" json:"txMaxJitter,omitempty"`
|
||||
RxRequests int32 `protobuf:"varint,5,opt,name=rxRequests,proto3" json:"rxRequests,omitempty"`
|
||||
RxTimeout int32 `protobuf:"varint,6,opt,name=rxTimeout,proto3" json:"rxTimeout,omitempty"`
|
||||
PayloadMinBytes int32 `protobuf:"varint,7,opt,name=payloadMinBytes,proto3" json:"payloadMinBytes,omitempty"`
|
||||
PayloadMaxBytes int32 `protobuf:"varint,8,opt,name=payloadMaxBytes,proto3" json:"payloadMaxBytes,omitempty"`
|
||||
LatencyFrequency int32 `protobuf:"varint,9,opt,name=latencyFrequency,proto3" json:"latencyFrequency,omitempty"`
|
||||
TxBlockType string `protobuf:"bytes,10,opt,name=txBlockType,proto3" json:"txBlockType,omitempty"`
|
||||
RxBlockType string `protobuf:"bytes,11,opt,name=rxBlockType,proto3" json:"rxBlockType,omitempty"`
|
||||
RxSeqBlockSize int32 `protobuf:"varint,12,opt,name=rxSeqBlockSize,proto3" json:"rxSeqBlockSize,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
TxRequests int32 `protobuf:"varint,2,opt,name=txRequests,proto3" json:"txRequests,omitempty"`
|
||||
TxPacing int32 `protobuf:"varint,3,opt,name=txPacing,proto3" json:"txPacing,omitempty"`
|
||||
TxMaxJitter int32 `protobuf:"varint,4,opt,name=txMaxJitter,proto3" json:"txMaxJitter,omitempty"`
|
||||
RxRequests int32 `protobuf:"varint,5,opt,name=rxRequests,proto3" json:"rxRequests,omitempty"`
|
||||
RxTimeout int32 `protobuf:"varint,6,opt,name=rxTimeout,proto3" json:"rxTimeout,omitempty"`
|
||||
PayloadMinBytes int32 `protobuf:"varint,7,opt,name=payloadMinBytes,proto3" json:"payloadMinBytes,omitempty"`
|
||||
PayloadMaxBytes int32 `protobuf:"varint,8,opt,name=payloadMaxBytes,proto3" json:"payloadMaxBytes,omitempty"`
|
||||
LatencyFrequency int32 `protobuf:"varint,9,opt,name=latencyFrequency,proto3" json:"latencyFrequency,omitempty"`
|
||||
TxBlockType string `protobuf:"bytes,10,opt,name=txBlockType,proto3" json:"txBlockType,omitempty"`
|
||||
RxBlockType string `protobuf:"bytes,11,opt,name=rxBlockType,proto3" json:"rxBlockType,omitempty"`
|
||||
RxSeqBlockSize int32 `protobuf:"varint,12,opt,name=rxSeqBlockSize,proto3" json:"rxSeqBlockSize,omitempty"`
|
||||
RxPacing string `protobuf:"bytes,13,opt,name=rxPacing,proto3" json:"rxPacing,omitempty"`
|
||||
RxMaxJitter string `protobuf:"bytes,14,opt,name=rxMaxJitter,proto3" json:"rxMaxJitter,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Test) Reset() { *m = Test{} }
|
||||
func (m *Test) String() string { return proto.CompactTextString(m) }
|
||||
func (*Test) ProtoMessage() {}
|
||||
func (x *Test) Reset() {
|
||||
*x = Test{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_loop3_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Test) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Test) ProtoMessage() {}
|
||||
|
||||
func (x *Test) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_loop3_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Test.ProtoReflect.Descriptor instead.
|
||||
func (*Test) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_fb557b01f1ee4776, []int{0}
|
||||
return file_loop3_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (m *Test) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Test.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Test) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Test.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Test) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Test.Merge(m, src)
|
||||
}
|
||||
func (m *Test) XXX_Size() int {
|
||||
return xxx_messageInfo_Test.Size(m)
|
||||
}
|
||||
func (m *Test) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Test.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Test proto.InternalMessageInfo
|
||||
|
||||
func (m *Test) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
func (x *Test) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Test) GetTxRequests() int32 {
|
||||
if m != nil {
|
||||
return m.TxRequests
|
||||
func (x *Test) GetTxRequests() int32 {
|
||||
if x != nil {
|
||||
return x.TxRequests
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Test) GetTxPacing() int32 {
|
||||
if m != nil {
|
||||
return m.TxPacing
|
||||
func (x *Test) GetTxPacing() int32 {
|
||||
if x != nil {
|
||||
return x.TxPacing
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Test) GetTxMaxJitter() int32 {
|
||||
if m != nil {
|
||||
return m.TxMaxJitter
|
||||
func (x *Test) GetTxMaxJitter() int32 {
|
||||
if x != nil {
|
||||
return x.TxMaxJitter
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Test) GetRxRequests() int32 {
|
||||
if m != nil {
|
||||
return m.RxRequests
|
||||
func (x *Test) GetRxRequests() int32 {
|
||||
if x != nil {
|
||||
return x.RxRequests
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Test) GetRxTimeout() int32 {
|
||||
if m != nil {
|
||||
return m.RxTimeout
|
||||
func (x *Test) GetRxTimeout() int32 {
|
||||
if x != nil {
|
||||
return x.RxTimeout
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Test) GetPayloadMinBytes() int32 {
|
||||
if m != nil {
|
||||
return m.PayloadMinBytes
|
||||
func (x *Test) GetPayloadMinBytes() int32 {
|
||||
if x != nil {
|
||||
return x.PayloadMinBytes
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Test) GetPayloadMaxBytes() int32 {
|
||||
if m != nil {
|
||||
return m.PayloadMaxBytes
|
||||
func (x *Test) GetPayloadMaxBytes() int32 {
|
||||
if x != nil {
|
||||
return x.PayloadMaxBytes
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Test) GetLatencyFrequency() int32 {
|
||||
if m != nil {
|
||||
return m.LatencyFrequency
|
||||
func (x *Test) GetLatencyFrequency() int32 {
|
||||
if x != nil {
|
||||
return x.LatencyFrequency
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *Test) GetTxBlockType() string {
|
||||
if m != nil {
|
||||
return m.TxBlockType
|
||||
func (x *Test) GetTxBlockType() string {
|
||||
if x != nil {
|
||||
return x.TxBlockType
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Test) GetRxBlockType() string {
|
||||
if m != nil {
|
||||
return m.RxBlockType
|
||||
func (x *Test) GetRxBlockType() string {
|
||||
if x != nil {
|
||||
return x.RxBlockType
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Test) GetRxSeqBlockSize() int32 {
|
||||
if m != nil {
|
||||
return m.RxSeqBlockSize
|
||||
func (x *Test) GetRxSeqBlockSize() int32 {
|
||||
if x != nil {
|
||||
return x.RxSeqBlockSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Test)(nil), "loop3.pb.Test")
|
||||
func (x *Test) GetRxPacing() string {
|
||||
if x != nil {
|
||||
return x.RxPacing
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("loop3.proto", fileDescriptor_fb557b01f1ee4776)
|
||||
func (x *Test) GetRxMaxJitter() string {
|
||||
if x != nil {
|
||||
return x.RxMaxJitter
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var fileDescriptor_fb557b01f1ee4776 = []byte{
|
||||
// 261 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x64, 0x91, 0xc1, 0x4a, 0xf3, 0x40,
|
||||
0x10, 0xc7, 0xe9, 0xd7, 0xb4, 0x5f, 0x32, 0x11, 0x95, 0x39, 0x2d, 0x22, 0x52, 0x3c, 0x48, 0xf1,
|
||||
0xe0, 0xa5, 0x6f, 0xd0, 0x83, 0x07, 0xa1, 0x20, 0x69, 0x5e, 0x60, 0x1b, 0x07, 0x59, 0x4c, 0xb3,
|
||||
0xe9, 0x66, 0x0a, 0x1b, 0x1f, 0xc7, 0x27, 0x35, 0x99, 0x14, 0xb3, 0xd6, 0xdb, 0xcc, 0xef, 0xff,
|
||||
0xe3, 0x9f, 0xec, 0x2e, 0xa4, 0xa5, 0xb5, 0xf5, 0xea, 0xa9, 0x76, 0x96, 0x2d, 0xc6, 0xa7, 0x65,
|
||||
0x77, 0xff, 0x35, 0x85, 0x28, 0xa7, 0x86, 0x11, 0x21, 0xaa, 0xf4, 0x9e, 0xd4, 0x64, 0x31, 0x59,
|
||||
0x26, 0x99, 0xcc, 0x78, 0x07, 0xc0, 0x3e, 0xa3, 0xc3, 0xb1, 0x13, 0x1a, 0xf5, 0xaf, 0x4b, 0x66,
|
||||
0x59, 0x40, 0xf0, 0x06, 0x62, 0xf6, 0xaf, 0xba, 0x30, 0xd5, 0xbb, 0x9a, 0x4a, 0xfa, 0xb3, 0xe3,
|
||||
0x02, 0x52, 0xf6, 0x1b, 0xed, 0x5f, 0x0c, 0x33, 0x39, 0x15, 0x49, 0x1c, 0xa2, 0xbe, 0xdd, 0x8d,
|
||||
0xed, 0xb3, 0xa1, 0x7d, 0x24, 0x78, 0x0b, 0x89, 0xf3, 0xb9, 0xd9, 0x93, 0x3d, 0xb2, 0x9a, 0x4b,
|
||||
0x3c, 0x02, 0x5c, 0xc2, 0x55, 0xad, 0xdb, 0xd2, 0xea, 0xb7, 0x8d, 0xa9, 0xd6, 0x2d, 0x53, 0xa3,
|
||||
0xfe, 0x8b, 0x73, 0x8e, 0x43, 0x53, 0xfb, 0xc1, 0x8c, 0x7f, 0x9b, 0x27, 0x8c, 0x8f, 0x70, 0x5d,
|
||||
0x6a, 0xa6, 0xaa, 0x68, 0x9f, 0x5d, 0xff, 0x17, 0xdd, 0xa0, 0x12, 0x51, 0xff, 0xf0, 0xe1, 0x7c,
|
||||
0xeb, 0xd2, 0x16, 0x1f, 0x79, 0x5b, 0x93, 0x02, 0xb9, 0xb6, 0x10, 0xf5, 0x86, 0x0b, 0x8c, 0x74,
|
||||
0x30, 0x02, 0x84, 0x0f, 0x70, 0xe9, 0xfc, 0x96, 0x0e, 0x42, 0xb6, 0xe6, 0x93, 0xd4, 0x85, 0x7c,
|
||||
0xed, 0x8c, 0xee, 0xe6, 0xf2, 0x6a, 0xab, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5a, 0x01, 0xaf,
|
||||
0xf2, 0xc4, 0x01, 0x00, 0x00,
|
||||
var File_loop3_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_loop3_proto_rawDesc = []byte{
|
||||
0x0a, 0x0b, 0x6c, 0x6f, 0x6f, 0x70, 0x33, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x7a,
|
||||
0x69, 0x74, 0x69, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x33, 0x2e, 0x70, 0x62, 0x22, 0xe0, 0x03, 0x0a,
|
||||
0x04, 0x54, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x78, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x74,
|
||||
0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x78, 0x50,
|
||||
0x61, 0x63, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x74, 0x78, 0x50,
|
||||
0x61, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x74, 0x78, 0x4d, 0x61, 0x78, 0x4a, 0x69,
|
||||
0x74, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x74, 0x78, 0x4d, 0x61,
|
||||
0x78, 0x4a, 0x69, 0x74, 0x74, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x78, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x72, 0x78, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x78, 0x54, 0x69, 0x6d,
|
||||
0x65, 0x6f, 0x75, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x72, 0x78, 0x54, 0x69,
|
||||
0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
|
||||
0x4d, 0x69, 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f,
|
||||
0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4d, 0x69, 0x6e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12,
|
||||
0x28, 0x0a, 0x0f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x4d, 0x61, 0x78, 0x42, 0x79, 0x74,
|
||||
0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61,
|
||||
0x64, 0x4d, 0x61, 0x78, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x6c, 0x61, 0x74,
|
||||
0x65, 0x6e, 0x63, 0x79, 0x46, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x09, 0x20,
|
||||
0x01, 0x28, 0x05, 0x52, 0x10, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x46, 0x72, 0x65, 0x71,
|
||||
0x75, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x74, 0x78, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
|
||||
0x54, 0x79, 0x70, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x78, 0x42, 0x6c,
|
||||
0x6f, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x78, 0x42, 0x6c, 0x6f,
|
||||
0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x78,
|
||||
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x78, 0x53,
|
||||
0x65, 0x71, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28,
|
||||
0x05, 0x52, 0x0e, 0x72, 0x78, 0x53, 0x65, 0x71, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x69, 0x7a,
|
||||
0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x78, 0x50, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x18, 0x0d, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x78, 0x50, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x12, 0x20, 0x0a,
|
||||
0x0b, 0x72, 0x78, 0x4d, 0x61, 0x78, 0x4a, 0x69, 0x74, 0x74, 0x65, 0x72, 0x18, 0x0e, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x0b, 0x72, 0x78, 0x4d, 0x61, 0x78, 0x4a, 0x69, 0x74, 0x74, 0x65, 0x72, 0x42,
|
||||
0x44, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70,
|
||||
0x65, 0x6e, 0x7a, 0x69, 0x74, 0x69, 0x2f, 0x7a, 0x69, 0x74, 0x69, 0x2f, 0x7a, 0x69, 0x74, 0x69,
|
||||
0x2d, 0x66, 0x61, 0x62, 0x72, 0x69, 0x63, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x73, 0x75, 0x62,
|
||||
0x63, 0x6d, 0x64, 0x2f, 0x6c, 0x6f, 0x6f, 0x70, 0x33, 0x2f, 0x70, 0x62, 0x2f, 0x6c, 0x6f, 0x6f,
|
||||
0x70, 0x33, 0x5f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_loop3_proto_rawDescOnce sync.Once
|
||||
file_loop3_proto_rawDescData = file_loop3_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_loop3_proto_rawDescGZIP() []byte {
|
||||
file_loop3_proto_rawDescOnce.Do(func() {
|
||||
file_loop3_proto_rawDescData = protoimpl.X.CompressGZIP(file_loop3_proto_rawDescData)
|
||||
})
|
||||
return file_loop3_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_loop3_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||
var file_loop3_proto_goTypes = []interface{}{
|
||||
(*Test)(nil), // 0: ziti.loop3.pb.Test
|
||||
}
|
||||
var file_loop3_proto_depIdxs = []int32{
|
||||
0, // [0:0] is the sub-list for method output_type
|
||||
0, // [0:0] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_loop3_proto_init() }
|
||||
func file_loop3_proto_init() {
|
||||
if File_loop3_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_loop3_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Test); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_loop3_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 1,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_loop3_proto_goTypes,
|
||||
DependencyIndexes: file_loop3_proto_depIdxs,
|
||||
MessageInfos: file_loop3_proto_msgTypes,
|
||||
}.Build()
|
||||
File_loop3_proto = out.File
|
||||
file_loop3_proto_rawDesc = nil
|
||||
file_loop3_proto_goTypes = nil
|
||||
file_loop3_proto_depIdxs = nil
|
||||
}
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package loop3.pb;
|
||||
package ziti.loop3.pb;
|
||||
option go_package = "github.com/openziti/ziti/ziti-fabric-test/subcmd/loop3/pb/loop3_pb";
|
||||
|
||||
message Test {
|
||||
string name = 1;
|
||||
int32 txRequests = 2;
|
||||
int32 txPacing = 3;
|
||||
int32 txMaxJitter = 4;
|
||||
int32 rxRequests = 5;
|
||||
int32 rxTimeout = 6;
|
||||
int32 payloadMinBytes = 7;
|
||||
int32 payloadMaxBytes = 8;
|
||||
int32 latencyFrequency = 9;
|
||||
string txBlockType = 10;
|
||||
string rxBlockType = 11;
|
||||
int32 rxSeqBlockSize = 12;
|
||||
string name = 1;
|
||||
int32 txRequests = 2;
|
||||
int32 txPacing = 3;
|
||||
int32 txMaxJitter = 4;
|
||||
int32 rxRequests = 5;
|
||||
int32 rxTimeout = 6;
|
||||
int32 payloadMinBytes = 7;
|
||||
int32 payloadMaxBytes = 8;
|
||||
int32 latencyFrequency = 9;
|
||||
string txBlockType = 10;
|
||||
string rxBlockType = 11;
|
||||
int32 rxSeqBlockSize = 12;
|
||||
string rxPacing = 13;
|
||||
string rxMaxJitter = 14;
|
||||
}
|
||||
@@ -32,16 +32,18 @@ import (
|
||||
)
|
||||
|
||||
type protocol struct {
|
||||
test *loop3_pb.Test
|
||||
blocks chan Block
|
||||
rxSequence uint64
|
||||
peer io.ReadWriteCloser
|
||||
rxBlocks chan Block
|
||||
txCount int32
|
||||
rxCount int32
|
||||
lastRx int64
|
||||
latencies chan *time.Time
|
||||
errors chan error
|
||||
test *loop3_pb.Test
|
||||
blocks chan Block
|
||||
rxSequence uint64
|
||||
rxPacing time.Duration
|
||||
rxMaxJitter time.Duration
|
||||
peer io.ReadWriteCloser
|
||||
rxBlocks chan Block
|
||||
txCount int32
|
||||
rxCount int32
|
||||
lastRx int64
|
||||
latencies chan *time.Time
|
||||
errors chan error
|
||||
}
|
||||
|
||||
var MagicHeader = []byte{0xCA, 0xFE, 0xF0, 0x0D}
|
||||
@@ -84,6 +86,18 @@ func (p *protocol) run(test *loop3_pb.Test) error {
|
||||
panic(errors.Errorf("unknown rx block type %v", test.RxBlockType))
|
||||
}
|
||||
|
||||
rxPacing, err := time.ParseDuration(p.test.RxPacing)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
p.rxPacing = rxPacing
|
||||
|
||||
rxMaxJitter, err := time.ParseDuration(p.test.RxMaxJitter)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
p.rxMaxJitter = rxMaxJitter
|
||||
|
||||
rxerDone := make(chan bool)
|
||||
go p.rxer(rxerDone, rxBlock)
|
||||
if p.test.RxRequests > 0 {
|
||||
@@ -155,6 +169,7 @@ func (p *protocol) rxer(done chan bool, rxBlock func() (Block, error)) {
|
||||
defer func() { done <- true }()
|
||||
defer log.Debug("complete")
|
||||
|
||||
lastRx := time.Now()
|
||||
for p.rxCount < p.test.RxRequests {
|
||||
block, err := rxBlock()
|
||||
if err != nil {
|
||||
@@ -166,6 +181,22 @@ func (p *protocol) rxer(done chan bool, rxBlock func() (Block, error)) {
|
||||
atomic.AddInt32(&p.rxCount, 1)
|
||||
atomic.StoreInt64(&p.lastRx, info.NowInMilliseconds())
|
||||
p.rxBlocks <- block
|
||||
|
||||
if p.rxPacing > 0 {
|
||||
jitter := time.Duration(0)
|
||||
if p.rxMaxJitter > 0 {
|
||||
jitter = time.Duration(rand.Intn(int(p.rxMaxJitter)))
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
nextRx := lastRx.Add(p.rxPacing + jitter)
|
||||
if nextRx.After(now) {
|
||||
time.Sleep(nextRx.Sub(now))
|
||||
lastRx = nextRx
|
||||
} else {
|
||||
lastRx = now
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(p.rxBlocks)
|
||||
|
||||
@@ -37,14 +37,16 @@ type Workload struct {
|
||||
}
|
||||
|
||||
type Test struct {
|
||||
TxRequests int32 `yaml:"txRequests"`
|
||||
TxPacing int32 `yaml:"txPacing"`
|
||||
TxMaxJitter int32 `yaml:"txMaxJitter"`
|
||||
RxTimeout int32 `yaml:"rxTimeout"`
|
||||
PayloadMinBytes int32 `yaml:"payloadMinBytes"`
|
||||
PayloadMaxBytes int32 `yaml:"payloadMaxBytes"`
|
||||
LatencyFrequency int32 `yaml:"latencyFrequency"`
|
||||
BlockType string `yaml:"blockType"`
|
||||
TxRequests int32 `yaml:"txRequests"`
|
||||
TxPacing int32 `yaml:"txPacing"`
|
||||
TxMaxJitter int32 `yaml:"txMaxJitter"`
|
||||
RxTimeout int32 `yaml:"rxTimeout"`
|
||||
RxPacing time.Duration `yaml:"rxPacing"`
|
||||
RxMaxJitter time.Duration `yaml:"rxMaxJitter"`
|
||||
PayloadMinBytes int32 `yaml:"payloadMinBytes"`
|
||||
PayloadMaxBytes int32 `yaml:"payloadMaxBytes"`
|
||||
LatencyFrequency int32 `yaml:"latencyFrequency"`
|
||||
BlockType string `yaml:"blockType"`
|
||||
}
|
||||
|
||||
func (workload *Workload) GetTests() (*loop3_pb.Test, *loop3_pb.Test) {
|
||||
@@ -54,6 +56,8 @@ func (workload *Workload) GetTests() (*loop3_pb.Test, *loop3_pb.Test) {
|
||||
TxPacing: workload.Dialer.TxPacing,
|
||||
TxMaxJitter: workload.Dialer.TxMaxJitter,
|
||||
RxRequests: workload.Listener.TxRequests,
|
||||
RxPacing: workload.Dialer.RxPacing.String(),
|
||||
RxMaxJitter: workload.Dialer.RxMaxJitter.String(),
|
||||
RxTimeout: workload.Dialer.RxTimeout,
|
||||
RxSeqBlockSize: workload.Listener.PayloadMinBytes,
|
||||
PayloadMinBytes: workload.Dialer.PayloadMinBytes,
|
||||
@@ -69,6 +73,8 @@ func (workload *Workload) GetTests() (*loop3_pb.Test, *loop3_pb.Test) {
|
||||
TxPacing: workload.Listener.TxPacing,
|
||||
TxMaxJitter: workload.Listener.TxMaxJitter,
|
||||
RxRequests: workload.Dialer.TxRequests,
|
||||
RxPacing: workload.Listener.RxPacing.String(),
|
||||
RxMaxJitter: workload.Listener.RxMaxJitter.String(),
|
||||
RxTimeout: workload.Listener.RxTimeout,
|
||||
RxSeqBlockSize: workload.Dialer.PayloadMinBytes,
|
||||
PayloadMinBytes: workload.Listener.PayloadMinBytes,
|
||||
|
||||
@@ -20,7 +20,9 @@ import (
|
||||
goflag "flag"
|
||||
"fmt"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/demo"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/fabric"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -136,6 +138,8 @@ func NewCmdRoot(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Comm
|
||||
pkiCommands := NewCmdPKI(f, out, err)
|
||||
fabricCommand := fabric.NewFabricCmd(p)
|
||||
edgeCommand := edge.NewCmdEdge(f, out, err)
|
||||
tutorialCmd := tutorial.NewTutorialCmd(p)
|
||||
demoCmd := demo.NewDemoCmd(p)
|
||||
logFilter := NewCmdLogFormat(f, out, err)
|
||||
unwrapIdentityFileCommand := NewUnwrapIdentityFileCommand(f, out, err)
|
||||
|
||||
@@ -181,6 +185,13 @@ func NewCmdRoot(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Comm
|
||||
logFilter,
|
||||
},
|
||||
},
|
||||
{
|
||||
Message: "Learning Ziti",
|
||||
Commands: []*cobra.Command{
|
||||
demoCmd,
|
||||
tutorialCmd,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
groups.Add(cmd)
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 demo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/michaelquigley/pfxlog"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/config"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
"net"
|
||||
)
|
||||
|
||||
type echoServer struct {
|
||||
port uint16
|
||||
verbose bool
|
||||
logFormatter string
|
||||
configFile string
|
||||
service string
|
||||
}
|
||||
|
||||
func newEchoServerCmd(common.OptionsProvider) *cobra.Command {
|
||||
server := &echoServer{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "echo-server",
|
||||
Short: "Runs a simple network echo service",
|
||||
Args: cobra.ExactArgs(0),
|
||||
Run: server.run,
|
||||
}
|
||||
|
||||
// allow interspersing positional args and flags
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
cmd.Flags().Uint16VarP(&server.port, "port", "p", 0, "Specify the port to listen on. If not specified the TCP listener won't be started")
|
||||
cmd.Flags().BoolVarP(&server.verbose, "verbose", "v", false, "Enable verbose logging")
|
||||
cmd.Flags().StringVar(&server.logFormatter, "log-formatter", "", "Specify log formatter [json|pfxlog|text]")
|
||||
cmd.Flags().StringVarP(&server.configFile, "identity", "i", "", "Specify the Ziti identity to use. If not specified the Ziti listener won't be started")
|
||||
cmd.Flags().StringVarP(&server.service, "service", "s", "echo", "Ziti service to bind. Defaults to 'echo'")
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (self *echoServer) initLogging() {
|
||||
logLevel := logrus.InfoLevel
|
||||
if self.verbose {
|
||||
logLevel = logrus.DebugLevel
|
||||
}
|
||||
|
||||
options := pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").NoColor()
|
||||
pfxlog.GlobalInit(logLevel, options)
|
||||
|
||||
switch self.logFormatter {
|
||||
case "pfxlog":
|
||||
pfxlog.SetFormatter(pfxlog.NewFormatter(pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").StartingToday()))
|
||||
case "json":
|
||||
pfxlog.SetFormatter(&logrus.JSONFormatter{TimestampFormat: "2006-01-02T15:04:05.000Z"})
|
||||
case "text":
|
||||
pfxlog.SetFormatter(&logrus.TextFormatter{})
|
||||
default:
|
||||
// let logrus do its own thing
|
||||
}
|
||||
}
|
||||
|
||||
func (self *echoServer) run(*cobra.Command, []string) {
|
||||
self.initLogging()
|
||||
|
||||
log := pfxlog.Logger()
|
||||
|
||||
if self.port == 0 && self.configFile == "" {
|
||||
log.Fatalf("No port specified and no ziti identity specified. Not starting either listener, so nothing to do. exiting.")
|
||||
}
|
||||
|
||||
if self.port > 0 {
|
||||
addr := fmt.Sprintf("0.0.0.0:%v", self.port)
|
||||
log.Infof("tcp: starting listener on address [%v]", addr)
|
||||
listener, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
log.WithError(err).Fatalf("unable to start TCP listener on addr [%v]", addr)
|
||||
}
|
||||
|
||||
go self.accept("tcp", listener)
|
||||
}
|
||||
|
||||
if self.configFile != "" {
|
||||
zitiConfig, err := config.NewFromFile(self.configFile)
|
||||
if err != nil {
|
||||
log.WithError(err).Fatalf("ziti: unable to load ziti identity from [%v]", self.configFile)
|
||||
}
|
||||
|
||||
zitiContext := ziti.NewContextWithConfig(zitiConfig)
|
||||
|
||||
log.Infof("ziti: starting listener for service (%v)", self.service)
|
||||
listener, err := zitiContext.Listen(self.service)
|
||||
if err != nil {
|
||||
log.WithError(err).Fatalf("ziti: failed to host service [%v]", self.service)
|
||||
}
|
||||
|
||||
go self.accept("ziti", listener)
|
||||
}
|
||||
|
||||
waitC := make(chan struct{})
|
||||
<-waitC
|
||||
}
|
||||
|
||||
func (self *echoServer) accept(connType string, listener net.Listener) {
|
||||
log := pfxlog.Logger()
|
||||
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Infof("%v: connection received: %v", connType, conn)
|
||||
go self.echo(connType, conn)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *echoServer) echo(connType string, conn io.ReadWriteCloser) {
|
||||
log := pfxlog.Logger()
|
||||
|
||||
defer func() {
|
||||
if err := conn.Close(); err != nil {
|
||||
log.WithError(err).Errorf("%v: Error while closing connection", connType)
|
||||
}
|
||||
log.Infof("%v: connection closed", connType)
|
||||
}()
|
||||
|
||||
for {
|
||||
buf := make([]byte, 1024)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
log.Infof("%v: received eof, closing connection", connType)
|
||||
} else {
|
||||
log.WithError(err).Errorf("%v: error while reading", connType)
|
||||
}
|
||||
break
|
||||
}
|
||||
log.Infof("%v: read %v bytes", connType, n)
|
||||
writeBuf := buf[:n]
|
||||
if _, err := conn.Write(writeBuf); err != nil {
|
||||
log.WithError(err).Errorf("%v: error while writing", connType)
|
||||
break
|
||||
}
|
||||
log.Infof("%v: wrote %v bytes", connType, n)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 demo
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func NewDemoCmd(p common.OptionsProvider) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "demo",
|
||||
Short: "Demos and examples for learning about Ziti",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := cmd.Help()
|
||||
helpers.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(newEchoServerCmd(p))
|
||||
cmd.AddCommand(newZcatCmd(p))
|
||||
cmd.AddCommand(newSimpleEchoSdkHostedCmd(p))
|
||||
cmd.AddCommand(newSimpleEchoRouterTunnelerHostedCmd(p))
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
# Purpose
|
||||
|
||||
This script sets up an echo service which is hosted by a router-embedded tunneler and
|
||||
is accessed by another sdk application.
|
||||
|
||||
# Prerequisites
|
||||
|
||||
You need at least one controller and an edge router running. for this to work.
|
||||
You can use the quick-start script found [here](https://github.com/openziti/ziti/tree/release-next/quickstart).
|
||||
|
||||
# Setup
|
||||
|
||||
First, ensure we're logged into the controller.
|
||||
|
||||
```action:ziti-login allowRetry=true
|
||||
ziti edge login
|
||||
```
|
||||
|
||||
```action:keep-session-alive interval=1m
|
||||
If your session times out you can run ziti edge login again.
|
||||
```
|
||||
|
||||
Remove any entities from previous runs.
|
||||
|
||||
```action:ziti
|
||||
ziti edge delete service echo
|
||||
ziti edge delete config echo-host
|
||||
ziti edge delete identities zcat echo-host
|
||||
ziti edge delete service-policies echo-dial echo-bind
|
||||
ziti edge delete edge-router-policies echo
|
||||
ziti edge delete service-edge-router-policies echo
|
||||
```
|
||||
|
||||
Create the echo-host config
|
||||
|
||||
```action:ziti-create-config name=echo-host type=host.v2
|
||||
{
|
||||
"terminators" : [
|
||||
{
|
||||
"address" : "localhost",
|
||||
"port" : 1234,
|
||||
"protocol" : "tcp"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Create the echo service
|
||||
|
||||
```action:ziti
|
||||
ziti edge create service echo -c echo-host
|
||||
```
|
||||
|
||||
Select an edge router to host this service on
|
||||
|
||||
```action:select-edge-router
|
||||
Pick the name of an edge router to use. It will be referenced in this tutorial as ${edgeRouterName}
|
||||
```
|
||||
|
||||
Update the select edge router with the `echo-host` attribute so it gets tied into the policies
|
||||
|
||||
```action:ziti templatize=true
|
||||
ziti edge update identity ${edgeRouterName} -a echo-host
|
||||
```
|
||||
|
||||
Create and enroll the client app identity
|
||||
|
||||
```action:ziti
|
||||
ziti edge create identity service zcat -a echo,echo-client -o zcat.jwt
|
||||
ziti edge enroll --rm zcat.jwt
|
||||
```
|
||||
|
||||
Configure policies
|
||||
|
||||
```action:ziti
|
||||
ziti edge create service-policy echo-dial Dial --service-roles @echo --identity-roles #echo-client
|
||||
ziti edge create service-policy echo-bind Bind --service-roles @echo --identity-roles #echo-host
|
||||
ziti edge create edge-router-policy echo --identity-roles #echo --edge-router-roles #all
|
||||
ziti edge create service-edge-router-policy echo --service-roles @echo --edge-router-roles #all
|
||||
```
|
||||
|
||||
You should now be to run the echo server with
|
||||
|
||||
```
|
||||
ziti demo echo-server -p 1234
|
||||
```
|
||||
|
||||
and
|
||||
the zcat client using
|
||||
|
||||
```
|
||||
ziti demo zcat -i zcat.json ziti:echo
|
||||
```
|
||||
@@ -0,0 +1,74 @@
|
||||
# Purpose
|
||||
|
||||
This script sets up an echo service which is hosted by an SDK application and
|
||||
is accessed by another sdk application.
|
||||
|
||||
# Prerequisites
|
||||
|
||||
You need at least one controller and an edge router running. for this to work.
|
||||
You can use the quick-start script found [here](https://github.com/openziti/ziti/tree/release-next/quickstart).
|
||||
|
||||
# Setup
|
||||
|
||||
First, ensure we're logged into the controller.
|
||||
|
||||
```action:ziti-login allowRetry=true
|
||||
ziti edge login
|
||||
```
|
||||
|
||||
```action:keep-session-alive interval=1m
|
||||
If your session times out you can run ziti edge login again.
|
||||
```
|
||||
|
||||
Remove any entities from previous runs.
|
||||
|
||||
```action:ziti
|
||||
ziti edge delete service echo
|
||||
ziti edge delete config echo-host
|
||||
ziti edge delete identities zcat echo-host
|
||||
ziti edge delete service-policies echo-dial echo-bind
|
||||
ziti edge delete edge-router-policies echo
|
||||
ziti edge delete service-edge-router-policies echo
|
||||
```
|
||||
|
||||
Create the echo service
|
||||
|
||||
```action:ziti
|
||||
ziti edge create service echo
|
||||
```
|
||||
|
||||
Create and enroll the hosting identity
|
||||
|
||||
```action:ziti
|
||||
ziti edge create identity service echo-host -a echo,echo-host -o echo-host.jwt
|
||||
ziti edge enroll --rm echo-host.jwt
|
||||
```
|
||||
|
||||
Create and enroll the client app identity
|
||||
|
||||
```action:ziti
|
||||
ziti edge create identity service zcat -a echo,echo-client -o zcat.jwt
|
||||
ziti edge enroll --rm zcat.jwt
|
||||
```
|
||||
|
||||
Configure policies
|
||||
|
||||
```action:ziti
|
||||
ziti edge create service-policy echo-dial Dial --service-roles @echo --identity-roles #echo-client
|
||||
ziti edge create service-policy echo-bind Bind --service-roles @echo --identity-roles #echo-host
|
||||
ziti edge create edge-router-policy echo --identity-roles #echo --edge-router-roles #all
|
||||
ziti edge create service-edge-router-policy echo --service-roles @echo --edge-router-roles #all
|
||||
```
|
||||
|
||||
You should now be to run the echo server with
|
||||
|
||||
```
|
||||
ziti demo echo-server -i echo-host.json
|
||||
```
|
||||
|
||||
and
|
||||
the zcat client using
|
||||
|
||||
```
|
||||
ziti demo zcat -i zcat.json ziti:echo
|
||||
```
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 demo
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/api"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
tutorial2 "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial/actions"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/tutorial"
|
||||
"github.com/spf13/cobra"
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:embed setup-scripts/simple-echo-router-tunneler-hosted.md
|
||||
var simpleEchoRouterTunnelerHostedScriptSource []byte
|
||||
|
||||
type simpleEchoRouterTunnelerHosted struct {
|
||||
api.Options
|
||||
tutorial2.TutorialOptions
|
||||
interactive bool
|
||||
}
|
||||
|
||||
func newSimpleEchoRouterTunnelerHostedCmd(p common.OptionsProvider) *cobra.Command {
|
||||
options := &simpleEchoRouterTunnelerHosted{
|
||||
Options: api.Options{
|
||||
CommonOptions: p(),
|
||||
},
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "setup-simple-echo-router-tunneler-hosted",
|
||||
Short: "Walks you through configuration for a simple echo service, hosted by a router-embedded tunneler",
|
||||
Args: cobra.ExactArgs(0),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.run()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
// allow interspersing positional args and flags
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
cmd.Flags().StringVar(&options.ControllerUrl, "controller-url", "", "The Ziti controller URL to use")
|
||||
cmd.Flags().StringVarP(&options.Username, "username", "u", "", "The Ziti controller username to use")
|
||||
cmd.Flags().StringVarP(&options.Password, "password", "p", "", "The Ziti controller password to use")
|
||||
cmd.Flags().DurationVar(&options.NewlinePause, "newline-pause", time.Millisecond*10, "How long to pause between lines when scrolling")
|
||||
cmd.Flags().BoolVar(&options.interactive, "interactive", false, "Interactive mode, waiting for user input")
|
||||
options.AddCommonFlags(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (self *simpleEchoRouterTunnelerHosted) run() error {
|
||||
t := tutorial.NewRunner()
|
||||
t.NewLinePause = self.NewlinePause
|
||||
t.AssumeDefault = !self.interactive
|
||||
|
||||
t.RegisterActionHandler("ziti", &actions.ZitiRunnerAction{})
|
||||
t.RegisterActionHandler("ziti-login", &actions.ZitiEnsureLoggedIn{
|
||||
LoginParams: &self.TutorialOptions,
|
||||
})
|
||||
t.RegisterActionHandler("keep-session-alive", &actions.KeepSessionAliveAction{})
|
||||
t.RegisterActionHandler("ziti-create-config", &actions.ZitiCreateConfigAction{})
|
||||
t.RegisterActionHandler("select-edge-router", &actions.SelectEdgeRouterAction{})
|
||||
|
||||
return t.Run(simpleEchoRouterTunnelerHostedScriptSource)
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 demo
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/api"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
tutorial2 "github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial/actions"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/tutorial"
|
||||
"github.com/spf13/cobra"
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:embed setup-scripts/simple-echo-sdk-hosted.md
|
||||
var simpleEchoSdkHostedScriptSource []byte
|
||||
|
||||
type simpleEchoSdkHosted struct {
|
||||
api.Options
|
||||
tutorial2.TutorialOptions
|
||||
interactive bool
|
||||
}
|
||||
|
||||
func newSimpleEchoSdkHostedCmd(p common.OptionsProvider) *cobra.Command {
|
||||
options := &simpleEchoSdkHosted{
|
||||
Options: api.Options{
|
||||
CommonOptions: p(),
|
||||
},
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "setup-simple-echo-sdk-hosted",
|
||||
Short: "Walks you through configuration for a simple sdk hosted sdk service",
|
||||
Args: cobra.ExactArgs(0),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.run()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
// allow interspersing positional args and flags
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
cmd.Flags().StringVar(&options.ControllerUrl, "controller-url", "", "The Ziti controller URL to use")
|
||||
cmd.Flags().StringVarP(&options.Username, "username", "u", "", "The Ziti controller username to use")
|
||||
cmd.Flags().StringVarP(&options.Password, "password", "p", "", "The Ziti controller password to use")
|
||||
cmd.Flags().DurationVar(&options.NewlinePause, "newline-pause", time.Millisecond*10, "How long to pause between lines when scrolling")
|
||||
cmd.Flags().BoolVar(&options.interactive, "interactive", false, "Interactive mode, waiting for user input")
|
||||
options.AddCommonFlags(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (self *simpleEchoSdkHosted) run() error {
|
||||
t := tutorial.NewRunner()
|
||||
t.NewLinePause = self.NewlinePause
|
||||
t.AssumeDefault = !self.interactive
|
||||
|
||||
t.RegisterActionHandler("ziti", &actions.ZitiRunnerAction{})
|
||||
t.RegisterActionHandler("ziti-login", &actions.ZitiEnsureLoggedIn{
|
||||
LoginParams: &self.TutorialOptions,
|
||||
})
|
||||
t.RegisterActionHandler("keep-session-alive", &actions.KeepSessionAliveAction{})
|
||||
t.RegisterActionHandler("select-edge-router", &actions.SelectEdgeRouterAction{})
|
||||
|
||||
return t.Run(simpleEchoSdkHostedScriptSource)
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 demo
|
||||
|
||||
import (
|
||||
"github.com/michaelquigley/pfxlog"
|
||||
"github.com/openziti/foundation/util/info"
|
||||
"github.com/openziti/sdk-golang/ziti"
|
||||
"github.com/openziti/sdk-golang/ziti/config"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type zcat struct {
|
||||
verbose bool
|
||||
logFormatter string
|
||||
configFile string
|
||||
}
|
||||
|
||||
func newZcatCmd(common.OptionsProvider) *cobra.Command {
|
||||
server := &zcat{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "zcat <destination>",
|
||||
Example: "ziti demo zcat tcp:localhost:1234 or ziti demo zcat -i zcat.json ziti:echo",
|
||||
Short: "A simple network cat facility which can run over tcp or ziti",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: server.run,
|
||||
}
|
||||
|
||||
// allow interspersing positional args and flags
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
cmd.Flags().BoolVarP(&server.verbose, "verbose", "v", false, "Enable verbose logging")
|
||||
cmd.Flags().StringVar(&server.logFormatter, "log-formatter", "", "Specify log formatter [json|pfxlog|text]")
|
||||
cmd.Flags().StringVarP(&server.configFile, "identity", "i", "", "Specify the Ziti identity to use. If not specified the Ziti listener won't be started")
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (self *zcat) initLogging() {
|
||||
logLevel := logrus.InfoLevel
|
||||
if self.verbose {
|
||||
logLevel = logrus.DebugLevel
|
||||
}
|
||||
|
||||
options := pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").NoColor()
|
||||
pfxlog.GlobalInit(logLevel, options)
|
||||
|
||||
switch self.logFormatter {
|
||||
case "pfxlog":
|
||||
pfxlog.SetFormatter(pfxlog.NewFormatter(pfxlog.DefaultOptions().SetTrimPrefix("github.com/openziti/").StartingToday()))
|
||||
case "json":
|
||||
pfxlog.SetFormatter(&logrus.JSONFormatter{TimestampFormat: "2006-01-02T15:04:05.000Z"})
|
||||
case "text":
|
||||
pfxlog.SetFormatter(&logrus.TextFormatter{})
|
||||
default:
|
||||
// let logrus do its own thing
|
||||
}
|
||||
}
|
||||
|
||||
func (self *zcat) run(_ *cobra.Command, args []string) {
|
||||
self.initLogging()
|
||||
|
||||
log := pfxlog.Logger()
|
||||
|
||||
parts := strings.Split(args[0], ":")
|
||||
if len(parts) < 2 {
|
||||
log.Fatalf("destination %v is invalid. destination must be of the form network:address", args[0])
|
||||
}
|
||||
network := parts[0]
|
||||
addr := strings.Join(parts[1:], ":")
|
||||
|
||||
var conn net.Conn
|
||||
var err error
|
||||
|
||||
log.Debugf("dialing %v:%v", network, addr)
|
||||
if network == "tcp" || network == "udp" {
|
||||
conn, err = net.Dial(network, addr)
|
||||
} else if network == "ziti" {
|
||||
zitiConfig, cfgErr := config.NewFromFile(self.configFile)
|
||||
if cfgErr != nil {
|
||||
log.WithError(cfgErr).Fatalf("unable to load ziti identity from [%v]", self.configFile)
|
||||
}
|
||||
|
||||
zitiContext := ziti.NewContextWithConfig(zitiConfig)
|
||||
conn, err = zitiContext.Dial(addr)
|
||||
} else {
|
||||
log.Fatalf("invalid network '%v'. valid values are ['ziti', 'tcp', 'udp']", network)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.WithError(err).Fatalf("unable to dial %v:%v", network, addr)
|
||||
}
|
||||
|
||||
log.Debugf("connected to %v:%v", network, addr)
|
||||
|
||||
go self.copy(conn, os.Stdin)
|
||||
self.copy(os.Stdout, conn)
|
||||
}
|
||||
|
||||
func (self *zcat) copy(writer io.Writer, reader io.Reader) {
|
||||
buf := make([]byte, info.MaxUdpPacketSize)
|
||||
bytesCopied, err := io.CopyBuffer(writer, reader, buf)
|
||||
pfxlog.Logger().Debugf("Copied %v bytes", bytesCopied)
|
||||
if err != nil {
|
||||
pfxlog.Logger().WithError(err).Error("error while copying bytes")
|
||||
}
|
||||
}
|
||||
@@ -147,7 +147,7 @@ func runDeleteEntityOfTypeWhere(options *api.Options, entityType string) error {
|
||||
params := url.Values{}
|
||||
params.Add("filter", filter)
|
||||
|
||||
children, pageInfo, err := listEntitiesOfType(entityType, params, options.OutputJSONResponse, options.Out, options.Timeout, options.Verbose)
|
||||
children, pageInfo, err := ListEntitiesOfType(entityType, params, options.OutputJSONResponse, options.Out, options.Timeout, options.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -318,30 +318,30 @@ func newSubListCmdForEntityType(entityType string, subType string, outputF outpu
|
||||
return cmd
|
||||
}
|
||||
|
||||
// listEntitiesOfType queries the Ziti Controller for entities of the given type
|
||||
// ListEntitiesOfType queries the Ziti Controller for entities of the given type
|
||||
func listEntitiesWithOptions(entityType string, options *api.Options) ([]*gabs.Container, *paging, error) {
|
||||
params := url.Values{}
|
||||
if len(options.Args) > 0 {
|
||||
params.Add("filter", options.Args[0])
|
||||
}
|
||||
|
||||
return listEntitiesOfType(entityType, params, options.OutputJSONResponse, options.Out, options.Timeout, options.Verbose)
|
||||
return ListEntitiesOfType(entityType, params, options.OutputJSONResponse, options.Out, options.Timeout, options.Verbose)
|
||||
}
|
||||
|
||||
func listEntitiesWithFilter(entityType string, filter string) ([]*gabs.Container, *paging, error) {
|
||||
func ListEntitiesWithFilter(entityType string, filter string) ([]*gabs.Container, *paging, error) {
|
||||
params := url.Values{}
|
||||
params.Add("filter", filter)
|
||||
return listEntitiesOfType(entityType, params, false, nil, 5, false)
|
||||
return ListEntitiesOfType(entityType, params, false, nil, 5, false)
|
||||
}
|
||||
|
||||
func filterEntitiesOfType(entityType string, filter string, logJSON bool, out io.Writer, timeout int, verbose bool) ([]*gabs.Container, *paging, error) {
|
||||
params := url.Values{}
|
||||
params.Add("filter", filter)
|
||||
return listEntitiesOfType(entityType, params, logJSON, out, timeout, verbose)
|
||||
return ListEntitiesOfType(entityType, params, logJSON, out, timeout, verbose)
|
||||
}
|
||||
|
||||
// listEntitiesOfType queries the Ziti Controller for entities of the given type
|
||||
func listEntitiesOfType(entityType string, params url.Values, logJSON bool, out io.Writer, timeout int, verbose bool) ([]*gabs.Container, *paging, error) {
|
||||
// ListEntitiesOfType queries the Ziti Controller for entities of the given type
|
||||
func ListEntitiesOfType(entityType string, params url.Values, logJSON bool, out io.Writer, timeout int, verbose bool) ([]*gabs.Container, *paging, error) {
|
||||
jsonParsed, err := util.EdgeControllerList(entityType, params, logJSON, out, timeout, verbose)
|
||||
|
||||
if err != nil {
|
||||
@@ -379,7 +379,7 @@ func getPaging(c *gabs.Container) *paging {
|
||||
return pagingInfo
|
||||
}
|
||||
|
||||
// listEntitiesOfType queries the Ziti Controller for entities of the given type
|
||||
// ListEntitiesOfType queries the Ziti Controller for entities of the given type
|
||||
func filterSubEntitiesOfType(entityType, subType, entityId, filter string, o *api.Options) ([]*gabs.Container, *paging, error) {
|
||||
jsonParsed, err := util.EdgeControllerListSubEntities(entityType, subType, entityId, filter, o.OutputJSONResponse, o.Out, o.Timeout, o.Verbose)
|
||||
|
||||
@@ -405,7 +405,7 @@ func runListEdgeRouters(roleFilters []string, roleSemantic string, options *api.
|
||||
if roleSemantic != "" {
|
||||
params.Add("roleSemantic", roleSemantic)
|
||||
}
|
||||
children, paging, err := listEntitiesOfType("edge-routers", params, options.OutputJSONResponse, options.Out, options.Timeout, options.Verbose)
|
||||
children, paging, err := ListEntitiesOfType("edge-routers", params, options.OutputJSONResponse, options.Out, options.Timeout, options.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -528,7 +528,7 @@ func runListServices(asIdentity string, configTypes []string, roleFilters []stri
|
||||
if roleSemantic != "" {
|
||||
params.Add("roleSemantic", roleSemantic)
|
||||
}
|
||||
children, pagingInfo, err := listEntitiesOfType("services", params, options.OutputJSONResponse, options.Out, options.Timeout, options.Verbose)
|
||||
children, pagingInfo, err := ListEntitiesOfType("services", params, options.OutputJSONResponse, options.Out, options.Timeout, options.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -697,7 +697,7 @@ func runListIdentities(roleFilters []string, roleSemantic string, options *api.O
|
||||
if roleSemantic != "" {
|
||||
params.Add("roleSemantic", roleSemantic)
|
||||
}
|
||||
children, pagingInfo, err := listEntitiesOfType("identities", params, options.OutputJSONResponse, options.Out, options.Timeout, options.Verbose)
|
||||
children, pagingInfo, err := ListEntitiesOfType("identities", params, options.OutputJSONResponse, options.Out, options.Timeout, options.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -18,14 +18,16 @@ package edge
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/common/enrollment"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
"io"
|
||||
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdutil "github.com/openziti/ziti/ziti/cmd/ziti/cmd/factory"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var ExtraEdgeCommands []func(p common.OptionsProvider) *cobra.Command
|
||||
|
||||
// NewCmdEdge creates a command object for the "controller" command
|
||||
func NewCmdEdge(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
|
||||
cmd := util.NewEmptyParentCmd("edge", "Interact with Ziti Edge Components")
|
||||
@@ -34,7 +36,6 @@ func NewCmdEdge(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comma
|
||||
}
|
||||
|
||||
func populateEdgeCommands(f cmdutil.Factory, out io.Writer, errOut io.Writer, cmd *cobra.Command) *cobra.Command {
|
||||
p := common.NewOptionsProvider(out, errOut)
|
||||
cmd.AddCommand(newCreateCmd(f, out, errOut))
|
||||
cmd.AddCommand(newDeleteCmd(out, errOut))
|
||||
cmd.AddCommand(newLoginCmd(out, errOut))
|
||||
@@ -48,7 +49,12 @@ func populateEdgeCommands(f cmdutil.Factory, out io.Writer, errOut io.Writer, cm
|
||||
cmd.AddCommand(newDbCmd(out, errOut))
|
||||
cmd.AddCommand(enrollment.NewEnrollCommand())
|
||||
cmd.AddCommand(newTraceCmd(out, errOut))
|
||||
cmd.AddCommand(newTutorialCmd(p))
|
||||
cmd.AddCommand(newTraceRouteCmd(out, errOut))
|
||||
|
||||
p := common.NewOptionsProvider(out, errOut)
|
||||
for _, cmdF := range ExtraEdgeCommands {
|
||||
cmd.AddCommand(cmdF(p))
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -1,426 +0,0 @@
|
||||
package edge
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"github.com/openziti/foundation/util/term"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/api"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/tutorial"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:embed tutorials/first-service.md
|
||||
var firstServiceTutorialSource []byte
|
||||
|
||||
//go:embed tutorial_plain_echo_server.go
|
||||
var plainEchoServerSource string
|
||||
|
||||
//go:embed tutorial_plain_echo_client.go
|
||||
var plainEchoClientSource string
|
||||
|
||||
//go:embed tutorial_ziti_echo_client.go
|
||||
var zitiEchoClientSource string
|
||||
|
||||
//go:embed tutorial_ziti_echo_server.go
|
||||
var zitiEchoServerSource string
|
||||
|
||||
func newTutorialCmd(p common.OptionsProvider) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "tutorial",
|
||||
Short: "Interactive tutorials for learning about Ziti",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := cmd.Help()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(newFirstServiceTutorialCmd(p))
|
||||
cmd.AddCommand(newPlainEchoServerCmd(p))
|
||||
cmd.AddCommand(newPlainEchoClientCmd(p))
|
||||
cmd.AddCommand(newZitiEchoClientCmd(p))
|
||||
cmd.AddCommand(newZitiEchoServerCmd(p))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
type tutorialOptions struct {
|
||||
controllerUrl string
|
||||
username string
|
||||
password string
|
||||
newlinePause time.Duration
|
||||
assumeDefault bool
|
||||
}
|
||||
|
||||
type firstServiceTutorialOptions struct {
|
||||
api.Options
|
||||
tutorialOptions
|
||||
}
|
||||
|
||||
func newFirstServiceTutorialCmd(p common.OptionsProvider) *cobra.Command {
|
||||
options := &firstServiceTutorialOptions{
|
||||
Options: api.Options{
|
||||
CommonOptions: p(),
|
||||
},
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "first-service",
|
||||
Short: "Walks you through creating a service, identity and policies",
|
||||
Args: cobra.ExactArgs(0),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.run()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
// allow interspersing positional args and flags
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
cmd.Flags().StringVar(&options.controllerUrl, "controller-url", "", "The Ziti controller URL to use")
|
||||
cmd.Flags().StringVarP(&options.username, "username", "u", "", "The Ziti controller username to use")
|
||||
cmd.Flags().StringVarP(&options.password, "password", "p", "", "The Ziti controller password to use")
|
||||
cmd.Flags().DurationVar(&options.newlinePause, "newline-pause", time.Millisecond*10, "How long to pause between lines when scrolling")
|
||||
cmd.Flags().BoolVar(&options.assumeDefault, "assume-default", false, "Non-interactive mode, assuming default input when user input is required")
|
||||
options.AddCommonFlags(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (self *firstServiceTutorialOptions) run() error {
|
||||
t := tutorial.NewRunner()
|
||||
t.NewLinePause = self.newlinePause
|
||||
t.AssumeDefault = self.assumeDefault
|
||||
|
||||
t.RegisterActionHandler("ziti", &ZitiRunnerAction{})
|
||||
t.RegisterActionHandler("ziti-login", &ZitiLoginAction{
|
||||
options: &self.tutorialOptions,
|
||||
})
|
||||
t.RegisterActionHandler("keep-session-alive", &KeepSessionAliveAction{})
|
||||
t.RegisterActionHandler("select-edge-router", &SelectEdgeRouterAction{})
|
||||
|
||||
plainEchoServerActions := &PlainEchoServerActions{}
|
||||
t.RegisterActionHandlerF("run-plain-echo-server", plainEchoServerActions.Start)
|
||||
t.RegisterActionHandlerF("stop-plain-echo-server", plainEchoServerActions.Stop)
|
||||
|
||||
zitiEchoServerActions := &ZitiEchoServerActions{}
|
||||
t.RegisterActionHandlerF("run-ziti-echo-server", zitiEchoServerActions.Start)
|
||||
t.RegisterActionHandlerF("stop-ziti-echo-server", zitiEchoServerActions.Stop)
|
||||
|
||||
showActionHandler := tutorial.NewShowActionHandler()
|
||||
showActionHandler.Add("tutorial_plain_echo_server.go", plainEchoServerSource)
|
||||
showActionHandler.Add("tutorial_plain_echo_client.go", plainEchoClientSource)
|
||||
showActionHandler.Add("tutorial_ziti_echo_client.go", zitiEchoClientSource)
|
||||
showActionHandler.Add("tutorial_ziti_echo_server.go", zitiEchoServerSource)
|
||||
t.RegisterActionHandler("show", showActionHandler)
|
||||
|
||||
return t.Run(firstServiceTutorialSource)
|
||||
}
|
||||
|
||||
type ZitiLoginAction struct {
|
||||
options *tutorialOptions
|
||||
}
|
||||
|
||||
func (self *ZitiLoginAction) Execute(ctx *tutorial.ActionContext) error {
|
||||
cmd := "ziti edge login --ignore-config"
|
||||
if self.options.controllerUrl != "" {
|
||||
cmd += " " + self.options.controllerUrl
|
||||
}
|
||||
if self.options.username != "" {
|
||||
cmd += " --username " + self.options.username
|
||||
}
|
||||
if self.options.password != "" {
|
||||
cmd += " --password " + self.options.password
|
||||
}
|
||||
ctx.Body = cmd
|
||||
return (&ZitiRunnerAction{}).Execute(ctx)
|
||||
}
|
||||
|
||||
type ZitiRunnerAction struct{}
|
||||
|
||||
func (self *ZitiRunnerAction) Execute(ctx *tutorial.ActionContext) error {
|
||||
if strings.EqualFold("true", ctx.Headers["templatize"]) {
|
||||
body, err := ctx.Runner.Template(ctx.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctx.Body = body
|
||||
}
|
||||
lines := strings.Split(ctx.Body, "\n")
|
||||
var cmds [][]string
|
||||
buf := &strings.Builder{}
|
||||
buf.WriteString("About to execute:\n\n")
|
||||
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if len(line) > 0 {
|
||||
params := tutorial.ParseArgumentsWithStrings(line)
|
||||
if params[0] != "ziti" {
|
||||
return errors.Errorf("invalid parameter for ziti action, must start with 'ziti': %v", ctx.Body)
|
||||
}
|
||||
params[0] = line
|
||||
cmds = append(cmds, params)
|
||||
ctx.Runner.LeftPadBuilder(buf)
|
||||
buf.WriteString(" ")
|
||||
buf.WriteString(color.New(color.Bold).Sprintf(line))
|
||||
buf.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
buf.WriteRune('\n')
|
||||
ctx.Runner.LeftPadBuilder(buf)
|
||||
buf.WriteString("Continue [Y/N] (default Y): ")
|
||||
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
tutorial.Continue(buf.String(), true)
|
||||
}
|
||||
|
||||
fmt.Println("")
|
||||
c := color.New(color.FgBlue, color.Bold)
|
||||
|
||||
colorStdOut := !strings.EqualFold("false", ctx.Headers["colorStdOut"])
|
||||
|
||||
allowRetry := strings.EqualFold("true", ctx.Headers["allowRetry"])
|
||||
failOk := strings.EqualFold("true", ctx.Headers["failOk"])
|
||||
for _, cmd := range cmds {
|
||||
_, _ = c.Printf("$ %v\n", cmd[0])
|
||||
done := false
|
||||
for !done {
|
||||
if err := tutorial.Exec(os.Args[0], colorStdOut, cmd[1:]...); err != nil {
|
||||
if failOk {
|
||||
return nil
|
||||
}
|
||||
if allowRetry {
|
||||
retry, err2 := tutorial.AskYesNoWithDefault(fmt.Sprintf("operation failed with err: %v. Retry [Y/N] (default Y):", err), true)
|
||||
if err2 != nil {
|
||||
fmt.Printf("error while asking about retry: %v\n", err2)
|
||||
return err
|
||||
}
|
||||
if !retry {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
done = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type KeepSessionAliveAction struct{}
|
||||
|
||||
func (self *KeepSessionAliveAction) Execute(ctx *tutorial.ActionContext) error {
|
||||
interval := time.Minute
|
||||
if val, ok := ctx.Headers["interval"]; ok {
|
||||
if d, err := time.ParseDuration(val); err != nil {
|
||||
return err
|
||||
} else {
|
||||
interval = d
|
||||
}
|
||||
}
|
||||
fmt.Printf("Running session refresh every %v\n", interval)
|
||||
go func() {
|
||||
ticker := time.NewTicker(interval)
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
_, _, _ = listEntitiesOfType("edge-routers", url.Values{}, false, nil, 10, false)
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
type edgeRouter struct {
|
||||
id string
|
||||
name string
|
||||
}
|
||||
|
||||
type SelectEdgeRouterAction struct{}
|
||||
|
||||
func (self *SelectEdgeRouterAction) Execute(ctx *tutorial.ActionContext) error {
|
||||
for {
|
||||
err := self.SelectEdgeRouter(ctx)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
retry, err2 := tutorial.AskYesNoWithDefault(fmt.Sprintf("Error getting edge router (err=%v). Try again? [Y/N] (default Y): ", err), true)
|
||||
if err2 != nil {
|
||||
fmt.Printf("encountered error prompting for input: %v\n", err2)
|
||||
return err
|
||||
}
|
||||
|
||||
if !retry {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SelectEdgeRouterAction) SelectEdgeRouter(ctx *tutorial.ActionContext) error {
|
||||
fmt.Println("")
|
||||
|
||||
valid := false
|
||||
var edgeRouterName string
|
||||
|
||||
for !valid {
|
||||
children, _, err := listEntitiesWithFilter("edge-routers", "limit none")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to list edge routers")
|
||||
}
|
||||
|
||||
var ers []*edgeRouter
|
||||
|
||||
if len(children) == 0 {
|
||||
return errors.New("no edge routers found")
|
||||
}
|
||||
|
||||
for _, child := range children {
|
||||
isOnline := child.S("isOnline").Data().(bool)
|
||||
if isOnline {
|
||||
id := child.S("id").Data().(string)
|
||||
name := child.S("name").Data().(string)
|
||||
ers = append(ers, &edgeRouter{id: id, name: name})
|
||||
}
|
||||
}
|
||||
|
||||
if len(ers) == 0 {
|
||||
fmt.Println("Error: no online edge routers found. Found these offline edge routers: ")
|
||||
for _, child := range children {
|
||||
id := child.S("id").Data().(string)
|
||||
name := child.S("name").Data().(string)
|
||||
fmt.Printf("id: %10v name: %10v\n", id, name)
|
||||
}
|
||||
return errors.New("no on-line edge routers")
|
||||
}
|
||||
|
||||
fmt.Printf("Available edge routers: \n\n")
|
||||
for idx, er := range ers {
|
||||
fmt.Printf(" %v: %v\n", idx+1, er.name)
|
||||
}
|
||||
fmt.Print(" R: Refresh list from controller\n")
|
||||
var val string
|
||||
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
val, err = term.Prompt("\nSelect edge router, by number or name (default 1): ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if val == "" {
|
||||
edgeRouterName = ers[0].name
|
||||
valid = true
|
||||
} else {
|
||||
if idx, err := strconv.Atoi(val); err == nil {
|
||||
if idx > 0 && idx <= len(ers) {
|
||||
edgeRouterName = ers[idx-1].name
|
||||
valid = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
for _, er := range ers {
|
||||
if val == er.name {
|
||||
edgeRouterName = val
|
||||
valid = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
if strings.EqualFold("r", val) {
|
||||
fmt.Println("Refreshing edge router list")
|
||||
} else {
|
||||
fmt.Printf("Invalid input %v\n", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Runner.AddVariable("edgeRouterName", edgeRouterName)
|
||||
return nil
|
||||
}
|
||||
|
||||
type PlainEchoServerActions struct {
|
||||
server plainEchoServer
|
||||
}
|
||||
|
||||
func (self *PlainEchoServerActions) Start(ctx *tutorial.ActionContext) error {
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
start, err := tutorial.AskYesNoWithDefault("Start plain-echo-server? [Y/N] (default Y): ", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !start {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := self.server.run(); err != nil {
|
||||
return err
|
||||
}
|
||||
ctx.Runner.AddVariable("port", self.server.Port)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PlainEchoServerActions) Stop(ctx *tutorial.ActionContext) error {
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
start, err := tutorial.AskYesNoWithDefault("Stop plain-echo-server? [Y/N] (default Y): ", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !start {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if self.server.listener != nil {
|
||||
return self.server.stop()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ZitiEchoServerActions struct {
|
||||
server zitiEchoServer
|
||||
}
|
||||
|
||||
func (self *ZitiEchoServerActions) Start(ctx *tutorial.ActionContext) error {
|
||||
logrus.SetLevel(logrus.WarnLevel)
|
||||
|
||||
self.server.identityJson = "echo-server.json"
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
start, err := tutorial.AskYesNoWithDefault("Start ziti-echo-server? [Y/N] (default Y): ", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !start {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := self.server.run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ZitiEchoServerActions) Stop(*tutorial.ActionContext) error {
|
||||
if self.server.listener != nil {
|
||||
return self.server.stop()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package edge
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
)
|
||||
|
||||
type plainEchoClient struct {
|
||||
host string
|
||||
port uint16
|
||||
}
|
||||
|
||||
func (self *plainEchoClient) echo(input string) error {
|
||||
input = url.QueryEscape(input)
|
||||
u := fmt.Sprintf("http://%v:%v?input=%v", self.host, self.port, input)
|
||||
resp, err := (&http.Client{}).Get(u)
|
||||
if err == nil {
|
||||
c := color.New(color.FgBlue, color.Bold)
|
||||
c.Print("\nplain-http-echo-client: ")
|
||||
_, err = io.Copy(os.Stdout, resp.Body)
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 actions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/edge"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/tutorial"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
type KeepSessionAliveAction struct{}
|
||||
|
||||
func (self *KeepSessionAliveAction) Execute(ctx *tutorial.ActionContext) error {
|
||||
interval := time.Minute
|
||||
if val, ok := ctx.Headers["interval"]; ok {
|
||||
if d, err := time.ParseDuration(val); err != nil {
|
||||
return err
|
||||
} else {
|
||||
interval = d
|
||||
}
|
||||
}
|
||||
fmt.Printf("Running session refresh every %v\n", interval)
|
||||
go func() {
|
||||
ticker := time.NewTicker(interval)
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
_, _, _ = edge.ListEntitiesOfType("edge-routers", url.Values{}, false, nil, 10, false)
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 actions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/foundation/util/term"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/edge"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/tutorial"
|
||||
"github.com/pkg/errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type edgeRouter struct {
|
||||
id string
|
||||
name string
|
||||
}
|
||||
|
||||
type SelectEdgeRouterAction struct{}
|
||||
|
||||
func (self *SelectEdgeRouterAction) Execute(ctx *tutorial.ActionContext) error {
|
||||
for {
|
||||
err := self.SelectEdgeRouter(ctx)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
retry, err2 := tutorial.AskYesNoWithDefault(fmt.Sprintf("Error getting edge router (err=%v). Try again? [Y/N] (default Y): ", err), true)
|
||||
if err2 != nil {
|
||||
fmt.Printf("encountered error prompting for input: %v\n", err2)
|
||||
return err
|
||||
}
|
||||
|
||||
if !retry {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SelectEdgeRouterAction) SelectEdgeRouter(ctx *tutorial.ActionContext) error {
|
||||
fmt.Println("")
|
||||
|
||||
valid := false
|
||||
var edgeRouterName string
|
||||
|
||||
for !valid {
|
||||
children, _, err := edge.ListEntitiesWithFilter("edge-routers", "limit none")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to list edge routers")
|
||||
}
|
||||
|
||||
var ers []*edgeRouter
|
||||
|
||||
if len(children) == 0 {
|
||||
return errors.New("no edge routers found")
|
||||
}
|
||||
|
||||
for _, child := range children {
|
||||
isOnline := child.S("isOnline").Data().(bool)
|
||||
if isOnline {
|
||||
id := child.S("id").Data().(string)
|
||||
name := child.S("name").Data().(string)
|
||||
ers = append(ers, &edgeRouter{id: id, name: name})
|
||||
}
|
||||
}
|
||||
|
||||
if len(ers) == 0 {
|
||||
fmt.Println("Error: no online edge routers found. Found these offline edge routers: ")
|
||||
for _, child := range children {
|
||||
id := child.S("id").Data().(string)
|
||||
name := child.S("name").Data().(string)
|
||||
fmt.Printf("id: %10v name: %10v\n", id, name)
|
||||
}
|
||||
return errors.New("no on-line edge routers")
|
||||
}
|
||||
|
||||
fmt.Printf("Available edge routers: \n\n")
|
||||
for idx, er := range ers {
|
||||
fmt.Printf(" %v: %v\n", idx+1, er.name)
|
||||
}
|
||||
fmt.Print(" R: Refresh list from controller\n")
|
||||
var val string
|
||||
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
val, err = term.Prompt("\nSelect edge router, by number or name (default 1): ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if val == "" {
|
||||
edgeRouterName = ers[0].name
|
||||
valid = true
|
||||
} else {
|
||||
if idx, err := strconv.Atoi(val); err == nil {
|
||||
if idx > 0 && idx <= len(ers) {
|
||||
edgeRouterName = ers[idx-1].name
|
||||
valid = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
for _, er := range ers {
|
||||
if val == er.name {
|
||||
edgeRouterName = val
|
||||
valid = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
if strings.EqualFold("r", val) {
|
||||
fmt.Println("Refreshing edge router list")
|
||||
} else {
|
||||
fmt.Printf("Invalid input %v\n", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Runner.AddVariable("edgeRouterName", edgeRouterName)
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 actions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/tutorial"
|
||||
"github.com/pkg/errors"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ZitiCreateConfigAction struct{}
|
||||
|
||||
func (self *ZitiCreateConfigAction) Execute(ctx *tutorial.ActionContext) error {
|
||||
if strings.EqualFold("true", ctx.Headers["templatize"]) {
|
||||
body, err := ctx.Runner.Template(ctx.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctx.Body = body
|
||||
}
|
||||
name := ctx.Headers["name"]
|
||||
configType := ctx.Headers["type"]
|
||||
|
||||
buf := &strings.Builder{}
|
||||
buf.WriteString("About to execute:\n\n")
|
||||
|
||||
line := fmt.Sprintf("ziti edge create config %v %v '%v'", name, configType, ctx.Body)
|
||||
params := tutorial.ParseArgumentsWithStrings(line)
|
||||
if params[0] != "ziti" {
|
||||
return errors.Errorf("invalid parameter for ziti action, must start with 'ziti': %v", ctx.Body)
|
||||
}
|
||||
params[0] = line
|
||||
ctx.Runner.LeftPadBuilder(buf)
|
||||
buf.WriteString(" ")
|
||||
buf.WriteString(color.New(color.Bold).Sprintf(line))
|
||||
buf.WriteRune('\n')
|
||||
buf.WriteRune('\n')
|
||||
ctx.Runner.LeftPadBuilder(buf)
|
||||
buf.WriteString("Continue [Y/N] (default Y): ")
|
||||
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
tutorial.Continue(buf.String(), true)
|
||||
}
|
||||
|
||||
fmt.Println("")
|
||||
c := color.New(color.FgBlue, color.Bold)
|
||||
|
||||
colorStdOut := !strings.EqualFold("false", ctx.Headers["colorStdOut"])
|
||||
|
||||
allowRetry := strings.EqualFold("true", ctx.Headers["allowRetry"])
|
||||
failOk := strings.EqualFold("true", ctx.Headers["failOk"])
|
||||
_, _ = c.Printf("$ %v\n", line)
|
||||
done := false
|
||||
for !done {
|
||||
if err := tutorial.Exec(os.Args[0], colorStdOut, "edge", "create", "config", name, configType, ctx.Body); err != nil {
|
||||
if failOk {
|
||||
return nil
|
||||
}
|
||||
if allowRetry {
|
||||
retry, err2 := tutorial.AskYesNoWithDefault(fmt.Sprintf("operation failed with err: %v. Retry [Y/N] (default Y):", err), true)
|
||||
if err2 != nil {
|
||||
fmt.Printf("error while asking about retry: %v\n", err2)
|
||||
return err
|
||||
}
|
||||
if !retry {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
done = true
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 actions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/edge"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/tutorial"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type ZitiEnsureLoggedIn struct {
|
||||
LoginParams LoginParams
|
||||
}
|
||||
|
||||
func (self *ZitiEnsureLoggedIn) Execute(ctx *tutorial.ActionContext) error {
|
||||
_, _, err := edge.ListEntitiesOfType("edge-routers", url.Values{}, false, nil, 10, false)
|
||||
if err == nil {
|
||||
fmt.Println("Already authenticated to Ziti Controller")
|
||||
return nil
|
||||
}
|
||||
loginAction := &ZitiLoginAction{LoginParams: self.LoginParams}
|
||||
return loginAction.Execute(ctx)
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 actions
|
||||
|
||||
import "github.com/openziti/ziti/ziti/cmd/ziti/tutorial"
|
||||
|
||||
type LoginParams interface {
|
||||
GetControllerUrl() string
|
||||
GetUsername() string
|
||||
GetPassword() string
|
||||
}
|
||||
|
||||
type ZitiLoginAction struct {
|
||||
LoginParams LoginParams
|
||||
}
|
||||
|
||||
func (self *ZitiLoginAction) Execute(ctx *tutorial.ActionContext) error {
|
||||
cmd := "ziti edge login --ignore-config"
|
||||
if self.LoginParams.GetControllerUrl() != "" {
|
||||
cmd += " " + self.LoginParams.GetControllerUrl()
|
||||
}
|
||||
if self.LoginParams.GetUsername() != "" {
|
||||
cmd += " --username " + self.LoginParams.GetUsername()
|
||||
}
|
||||
if self.LoginParams.GetPassword() != "" {
|
||||
cmd += " --password " + self.LoginParams.GetPassword()
|
||||
}
|
||||
ctx.Body = cmd
|
||||
return (&ZitiRunnerAction{}).Execute(ctx)
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 actions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/tutorial"
|
||||
"github.com/pkg/errors"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ZitiRunnerAction struct{}
|
||||
|
||||
func (self *ZitiRunnerAction) Execute(ctx *tutorial.ActionContext) error {
|
||||
if strings.EqualFold("true", ctx.Headers["templatize"]) {
|
||||
body, err := ctx.Runner.Template(ctx.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctx.Body = body
|
||||
}
|
||||
lines := strings.Split(ctx.Body, "\n")
|
||||
var cmds [][]string
|
||||
buf := &strings.Builder{}
|
||||
buf.WriteString("About to execute:\n\n")
|
||||
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if len(line) > 0 {
|
||||
params := tutorial.ParseArgumentsWithStrings(line)
|
||||
if params[0] != "ziti" {
|
||||
return errors.Errorf("invalid parameter for ziti action, must start with 'ziti': %v", ctx.Body)
|
||||
}
|
||||
params[0] = line
|
||||
cmds = append(cmds, params)
|
||||
ctx.Runner.LeftPadBuilder(buf)
|
||||
buf.WriteString(" ")
|
||||
buf.WriteString(color.New(color.Bold).Sprintf(line))
|
||||
buf.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
buf.WriteRune('\n')
|
||||
ctx.Runner.LeftPadBuilder(buf)
|
||||
buf.WriteString("Continue [Y/N] (default Y): ")
|
||||
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
tutorial.Continue(buf.String(), true)
|
||||
}
|
||||
|
||||
fmt.Println("")
|
||||
c := color.New(color.FgBlue, color.Bold)
|
||||
|
||||
colorStdOut := !strings.EqualFold("false", ctx.Headers["colorStdOut"])
|
||||
|
||||
allowRetry := strings.EqualFold("true", ctx.Headers["allowRetry"])
|
||||
failOk := strings.EqualFold("true", ctx.Headers["failOk"])
|
||||
for _, cmd := range cmds {
|
||||
_, _ = c.Printf("$ %v\n", cmd[0])
|
||||
done := false
|
||||
for !done {
|
||||
if err := tutorial.Exec(os.Args[0], colorStdOut, cmd[1:]...); err != nil {
|
||||
if failOk {
|
||||
return nil
|
||||
}
|
||||
if allowRetry {
|
||||
retry, err2 := tutorial.AskYesNoWithDefault(fmt.Sprintf("operation failed with err: %v. Retry [Y/N] (default Y):", err), true)
|
||||
if err2 != nil {
|
||||
fmt.Printf("error while asking about retry: %v\n", err2)
|
||||
return err
|
||||
}
|
||||
if !retry {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
done = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 tutorial
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/api"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/tutorial/actions"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/tutorial"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:embed tutorials/first-service.md
|
||||
var firstServiceTutorialSource []byte
|
||||
|
||||
//go:embed plain_echo_server.go
|
||||
var plainEchoServerSource string
|
||||
|
||||
//go:embed plain_echo_client.go
|
||||
var plainEchoClientSource string
|
||||
|
||||
//go:embed ziti_echo_client.go
|
||||
var zitiEchoClientSource string
|
||||
|
||||
//go:embed ziti_echo_server.go
|
||||
var zitiEchoServerSource string
|
||||
|
||||
type firstServiceTutorialOptions struct {
|
||||
api.Options
|
||||
TutorialOptions
|
||||
}
|
||||
|
||||
func newFirstServiceTutorialCmd(p common.OptionsProvider) *cobra.Command {
|
||||
options := &firstServiceTutorialOptions{
|
||||
Options: api.Options{
|
||||
CommonOptions: p(),
|
||||
},
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "first-service",
|
||||
Short: "Walks you through creating a service, identity and policies",
|
||||
Args: cobra.ExactArgs(0),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Cmd = cmd
|
||||
options.Args = args
|
||||
err := options.run()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
SuggestFor: []string{},
|
||||
}
|
||||
|
||||
// allow interspersing positional args and flags
|
||||
cmd.Flags().SetInterspersed(true)
|
||||
cmd.Flags().StringVar(&options.ControllerUrl, "controller-url", "", "The Ziti controller URL to use")
|
||||
cmd.Flags().StringVarP(&options.Username, "username", "u", "", "The Ziti controller username to use")
|
||||
cmd.Flags().StringVarP(&options.Password, "password", "p", "", "The Ziti controller password to use")
|
||||
cmd.Flags().DurationVar(&options.NewlinePause, "newline-pause", time.Millisecond*10, "How long to pause between lines when scrolling")
|
||||
cmd.Flags().BoolVar(&options.AssumeDefault, "assume-default", false, "Non-interactive mode, assuming default input when user input is required")
|
||||
options.AddCommonFlags(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (self *firstServiceTutorialOptions) run() error {
|
||||
t := tutorial.NewRunner()
|
||||
t.NewLinePause = self.NewlinePause
|
||||
t.AssumeDefault = self.AssumeDefault
|
||||
|
||||
t.RegisterActionHandler("ziti", &actions.ZitiRunnerAction{})
|
||||
t.RegisterActionHandler("ziti-login", &actions.ZitiLoginAction{
|
||||
LoginParams: &self.TutorialOptions,
|
||||
})
|
||||
t.RegisterActionHandler("keep-session-alive", &actions.KeepSessionAliveAction{})
|
||||
t.RegisterActionHandler("select-edge-router", &actions.SelectEdgeRouterAction{})
|
||||
|
||||
plainEchoServerActions := &PlainEchoServerActions{}
|
||||
t.RegisterActionHandlerF("run-plain-echo-server", plainEchoServerActions.Start)
|
||||
t.RegisterActionHandlerF("stop-plain-echo-server", plainEchoServerActions.Stop)
|
||||
|
||||
zitiEchoServerActions := &ZitiEchoServerActions{}
|
||||
t.RegisterActionHandlerF("run-ziti-echo-server", zitiEchoServerActions.Start)
|
||||
t.RegisterActionHandlerF("stop-ziti-echo-server", zitiEchoServerActions.Stop)
|
||||
|
||||
showActionHandler := tutorial.NewShowActionHandler()
|
||||
showActionHandler.Add("echo_server_plain.go", plainEchoServerSource)
|
||||
showActionHandler.Add("plain_echo_client.go", plainEchoClientSource)
|
||||
showActionHandler.Add("echo_client_ziti.go", zitiEchoClientSource)
|
||||
showActionHandler.Add("echo_server_ziti.go", zitiEchoServerSource)
|
||||
t.RegisterActionHandler("show", showActionHandler)
|
||||
|
||||
return t.Run(firstServiceTutorialSource)
|
||||
}
|
||||
|
||||
type PlainEchoServerActions struct {
|
||||
server plainEchoServer
|
||||
}
|
||||
|
||||
func (self *PlainEchoServerActions) Start(ctx *tutorial.ActionContext) error {
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
start, err := tutorial.AskYesNoWithDefault("Start plain-echo-server? [Y/N] (default Y): ", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !start {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := self.server.run(); err != nil {
|
||||
return err
|
||||
}
|
||||
ctx.Runner.AddVariable("port", self.server.Port)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *PlainEchoServerActions) Stop(ctx *tutorial.ActionContext) error {
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
start, err := tutorial.AskYesNoWithDefault("Stop plain-echo-server? [Y/N] (default Y): ", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !start {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if self.server.listener != nil {
|
||||
return self.server.stop()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ZitiEchoServerActions struct {
|
||||
server zitiEchoServer
|
||||
}
|
||||
|
||||
func (self *ZitiEchoServerActions) Start(ctx *tutorial.ActionContext) error {
|
||||
logrus.SetLevel(logrus.WarnLevel)
|
||||
|
||||
self.server.identityJson = "echo-server.json"
|
||||
if !ctx.Runner.AssumeDefault {
|
||||
start, err := tutorial.AskYesNoWithDefault("Start ziti-echo-server? [Y/N] (default Y): ", true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !start {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := self.server.run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ZitiEchoServerActions) Stop(*tutorial.ActionContext) error {
|
||||
if self.server.listener != nil {
|
||||
return self.server.stop()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 tutorial
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
)
|
||||
|
||||
type plainEchoClient struct {
|
||||
host string
|
||||
port uint16
|
||||
}
|
||||
|
||||
func (self *plainEchoClient) echo(input string) error {
|
||||
input = url.QueryEscape(input)
|
||||
u := fmt.Sprintf("http://%v:%v?input=%v", self.host, self.port, input)
|
||||
resp, err := (&http.Client{}).Get(u)
|
||||
if err == nil {
|
||||
c := color.New(color.FgBlue, color.Bold)
|
||||
c.Print("\nplain-http-echo-client: ")
|
||||
_, err = io.Copy(os.Stdout, resp.Body)
|
||||
}
|
||||
return err
|
||||
}
|
||||
+17
-1
@@ -1,4 +1,20 @@
|
||||
package edge
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 tutorial
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
+17
-1
@@ -1,4 +1,20 @@
|
||||
package edge
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 tutorial
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
+17
-1
@@ -1,4 +1,20 @@
|
||||
package edge
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 tutorial
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 tutorial
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/edge"
|
||||
cmdhelper "github.com/openziti/ziti/ziti/cmd/ziti/cmd/helpers"
|
||||
"github.com/spf13/cobra"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
edge.ExtraEdgeCommands = append(edge.ExtraEdgeCommands, NewTutorialCmd)
|
||||
}
|
||||
|
||||
func NewTutorialCmd(p common.OptionsProvider) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "tutorial",
|
||||
Short: "Interactive tutorials for learning about Ziti",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := cmd.Help()
|
||||
cmdhelper.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(newFirstServiceTutorialCmd(p))
|
||||
cmd.AddCommand(newPlainEchoServerCmd(p))
|
||||
cmd.AddCommand(newPlainEchoClientCmd(p))
|
||||
cmd.AddCommand(newZitiEchoClientCmd(p))
|
||||
cmd.AddCommand(newZitiEchoServerCmd(p))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
type TutorialOptions struct {
|
||||
ControllerUrl string
|
||||
Username string
|
||||
Password string
|
||||
NewlinePause time.Duration
|
||||
AssumeDefault bool
|
||||
}
|
||||
|
||||
func (self *TutorialOptions) GetControllerUrl() string {
|
||||
return self.ControllerUrl
|
||||
}
|
||||
|
||||
func (self *TutorialOptions) GetUsername() string {
|
||||
return self.Username
|
||||
}
|
||||
|
||||
func (self *TutorialOptions) GetPassword() string {
|
||||
return self.Password
|
||||
}
|
||||
+17
-1
@@ -1,4 +1,20 @@
|
||||
package edge
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 tutorial
|
||||
|
||||
import (
|
||||
"context"
|
||||
+17
-1
@@ -1,4 +1,20 @@
|
||||
package edge
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 tutorial
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
+17
-1
@@ -1,4 +1,20 @@
|
||||
package edge
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 tutorial
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
+17
-1
@@ -1,4 +1,20 @@
|
||||
package edge
|
||||
/*
|
||||
Copyright NetFoundry, Inc.
|
||||
|
||||
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
|
||||
|
||||
https://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 tutorial
|
||||
|
||||
import (
|
||||
"github.com/openziti/ziti/ziti/cmd/ziti/cmd/common"
|
||||
Reference in New Issue
Block a user