From 0695f512f3e8344e9aaa31aef4a69d2db1f7f79d Mon Sep 17 00:00:00 2001 From: Mohamed Mahmoud Date: Thu, 17 Oct 2024 14:08:22 -0400 Subject: [PATCH] eBPF packet translation tracker Signed-off-by: Mohamed Mahmoud --- bpf/configs.h | 1 + bpf/flows.c | 5 + bpf/flows_filter.h | 10 +- bpf/headers/vmlinux_amd64.h | 13 +- bpf/headers/vmlinux_arm64.h | 13 +- bpf/headers/vmlinux_ppc64le.h | 13 +- bpf/pkt_transformation.h | 180 ++ bpf/types.h | 11 + go.mod | 8 +- go.sum | 14 +- pkg/agent/agent.go | 3 +- pkg/agent/config.go | 2 + pkg/decode/decode_protobuf.go | 12 + pkg/decode/decode_protobuf_test.go | 19 + pkg/ebpf/bpf_arm64_bpfel.go | 13 + pkg/ebpf/bpf_arm64_bpfel.o | Bin 151712 -> 194648 bytes pkg/ebpf/bpf_powerpc_bpfel.go | 13 + pkg/ebpf/bpf_powerpc_bpfel.o | Bin 150536 -> 193496 bytes pkg/ebpf/bpf_s390_bpfeb.go | 13 + pkg/ebpf/bpf_s390_bpfeb.o | Bin 166296 -> 208336 bytes pkg/ebpf/bpf_x86_bpfel.go | 13 + pkg/ebpf/bpf_x86_bpfel.o | Bin 151504 -> 194400 bytes pkg/ebpf/gen.go | 2 +- pkg/model/record.go | 5 + pkg/model/record_test.go | 15 + pkg/pbflow/flow.pb.go | 215 +- pkg/pbflow/proto.go | 34 + pkg/tracer/tracer.go | 30 + proto/flow.proto | 11 + .../cpuguy83/go-md2man/v2/md2man/roff.go | 90 +- .../sampledecoder/sample_decoder.go | 46 + .../go-controller/pkg/config/config.go | 172 +- .../go-controller/pkg/config/utils.go | 106 +- .../go-controller/pkg/libovsdb/ops/router.go | 53 +- .../go-controller/pkg/libovsdb/ops/switch.go | 3 + .../go-controller/pkg/types/const.go | 3 + vendor/github.com/urfave/cli/v2/.gitignore | 13 +- .../github.com/urfave/cli/v2/.golangci.yaml | 4 + .../urfave/cli/v2/CODE_OF_CONDUCT.md | 11 +- vendor/github.com/urfave/cli/v2/LICENSE | 2 +- vendor/github.com/urfave/cli/v2/Makefile | 26 + vendor/github.com/urfave/cli/v2/README.md | 67 +- vendor/github.com/urfave/cli/v2/app.go | 412 ++- vendor/github.com/urfave/cli/v2/category.go | 109 +- vendor/github.com/urfave/cli/v2/cli.go | 32 +- vendor/github.com/urfave/cli/v2/command.go | 302 +- vendor/github.com/urfave/cli/v2/context.go | 247 +- vendor/github.com/urfave/cli/v2/docs.go | 85 +- vendor/github.com/urfave/cli/v2/errors.go | 71 +- vendor/github.com/urfave/cli/v2/fish.go | 8 +- .../github.com/urfave/cli/v2/flag-spec.yaml | 131 + vendor/github.com/urfave/cli/v2/flag.go | 325 +- vendor/github.com/urfave/cli/v2/flag_bool.go | 144 +- .../github.com/urfave/cli/v2/flag_duration.go | 83 +- vendor/github.com/urfave/cli/v2/flag_ext.go | 48 + .../github.com/urfave/cli/v2/flag_float64.go | 87 +- .../urfave/cli/v2/flag_float64_slice.go | 155 +- .../github.com/urfave/cli/v2/flag_generic.go | 107 +- vendor/github.com/urfave/cli/v2/flag_int.go | 85 +- vendor/github.com/urfave/cli/v2/flag_int64.go | 85 +- .../urfave/cli/v2/flag_int64_slice.go | 158 +- .../urfave/cli/v2/flag_int_slice.go | 157 +- vendor/github.com/urfave/cli/v2/flag_path.go | 99 +- .../github.com/urfave/cli/v2/flag_string.go | 101 +- .../urfave/cli/v2/flag_string_slice.go | 157 +- .../urfave/cli/v2/flag_timestamp.go | 135 +- vendor/github.com/urfave/cli/v2/flag_uint.go | 85 +- .../github.com/urfave/cli/v2/flag_uint64.go | 85 +- .../urfave/cli/v2/flag_uint64_slice.go | 219 ++ .../urfave/cli/v2/flag_uint_slice.go | 230 ++ vendor/github.com/urfave/cli/v2/funcs.go | 9 +- .../urfave/cli/v2/godoc-current.txt | 2724 +++++++++++++++++ vendor/github.com/urfave/cli/v2/help.go | 390 ++- .../github.com/urfave/cli/v2/mkdocs-reqs.txt | 5 + vendor/github.com/urfave/cli/v2/mkdocs.yml | 107 + vendor/github.com/urfave/cli/v2/parse.go | 28 +- vendor/github.com/urfave/cli/v2/sliceflag.go | 290 ++ .../github.com/urfave/cli/v2/suggestions.go | 68 + vendor/github.com/urfave/cli/v2/template.go | 95 +- .../urfave/cli/v2/zz_generated.flags.go | 865 ++++++ vendor/github.com/xrash/smetrics/.travis.yml | 9 + vendor/github.com/xrash/smetrics/LICENSE | 21 + vendor/github.com/xrash/smetrics/README.md | 49 + vendor/github.com/xrash/smetrics/doc.go | 19 + vendor/github.com/xrash/smetrics/hamming.go | 25 + .../github.com/xrash/smetrics/jaro-winkler.go | 28 + vendor/github.com/xrash/smetrics/jaro.go | 86 + vendor/github.com/xrash/smetrics/soundex.go | 63 + vendor/github.com/xrash/smetrics/ukkonen.go | 94 + .../xrash/smetrics/wagner-fischer.go | 48 + vendor/modules.txt | 12 +- 91 files changed, 8498 insertions(+), 1743 deletions(-) create mode 100644 bpf/pkt_transformation.h create mode 100644 vendor/github.com/urfave/cli/v2/.golangci.yaml create mode 100644 vendor/github.com/urfave/cli/v2/Makefile create mode 100644 vendor/github.com/urfave/cli/v2/flag-spec.yaml create mode 100644 vendor/github.com/urfave/cli/v2/flag_ext.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_uint64_slice.go create mode 100644 vendor/github.com/urfave/cli/v2/flag_uint_slice.go create mode 100644 vendor/github.com/urfave/cli/v2/godoc-current.txt create mode 100644 vendor/github.com/urfave/cli/v2/mkdocs-reqs.txt create mode 100644 vendor/github.com/urfave/cli/v2/mkdocs.yml create mode 100644 vendor/github.com/urfave/cli/v2/sliceflag.go create mode 100644 vendor/github.com/urfave/cli/v2/suggestions.go create mode 100644 vendor/github.com/urfave/cli/v2/zz_generated.flags.go create mode 100644 vendor/github.com/xrash/smetrics/.travis.yml create mode 100644 vendor/github.com/xrash/smetrics/LICENSE create mode 100644 vendor/github.com/xrash/smetrics/README.md create mode 100644 vendor/github.com/xrash/smetrics/doc.go create mode 100644 vendor/github.com/xrash/smetrics/hamming.go create mode 100644 vendor/github.com/xrash/smetrics/jaro-winkler.go create mode 100644 vendor/github.com/xrash/smetrics/jaro.go create mode 100644 vendor/github.com/xrash/smetrics/soundex.go create mode 100644 vendor/github.com/xrash/smetrics/ukkonen.go create mode 100644 vendor/github.com/xrash/smetrics/wagner-fischer.go diff --git a/bpf/configs.h b/bpf/configs.h index 18e483fb5..c29ed6865 100644 --- a/bpf/configs.h +++ b/bpf/configs.h @@ -12,4 +12,5 @@ volatile const u8 enable_flows_filtering = 0; volatile const u16 dns_port = 0; volatile const u8 enable_network_events_monitoring = 0; volatile const u8 network_events_monitoring_groupid = 0; +volatile const u8 enable_pkt_transformation_tracking = 0; #endif //__CONFIGS_H__ diff --git a/bpf/flows.c b/bpf/flows.c index 7cf822014..0e9489ebb 100644 --- a/bpf/flows.c +++ b/bpf/flows.c @@ -51,6 +51,11 @@ */ #include "network_events_monitoring.h" +/* + * Defines packets transformation tracker + */ +#include "pkt_transformation.h" + static inline int flow_monitor(struct __sk_buff *skb, u8 direction) { // If sampling is defined, will only parse 1 out of "sampling" flows if (sampling > 1 && (bpf_get_prandom_u32() % sampling) != 0) { diff --git a/bpf/flows_filter.h b/bpf/flows_filter.h index 3a541c6d5..e712a605a 100644 --- a/bpf/flows_filter.h +++ b/bpf/flows_filter.h @@ -7,13 +7,9 @@ #include "utils.h" -// remove the comment below to enable debug prints -//#define ENABLE_BPF_PRINTK -#ifdef ENABLE_BPF_PRINTK -#define BPF_PRINTK(fmt, args...) bpf_printk(fmt, ##args) -#else -#define BPF_PRINTK(fmt, args...) -#endif +#define BPF_PRINTK(fmt, args...) \ + if (trace_messages) \ + bpf_printk(fmt, ##args) static __always_inline int is_zero_ip(u8 *ip, u8 len) { for (int i = 0; i < len; i++) { diff --git a/bpf/headers/vmlinux_amd64.h b/bpf/headers/vmlinux_amd64.h index 529622317..3fe68d56e 100644 --- a/bpf/headers/vmlinux_amd64.h +++ b/bpf/headers/vmlinux_amd64.h @@ -22484,10 +22484,17 @@ union nf_conntrack_proto { struct nf_ct_ext; +struct nf_conntrack_zone { + u16 id; + u8 flags; + u8 dir; +}; + struct nf_conn { struct nf_conntrack ct_general; spinlock_t lock; u32 timeout; + struct nf_conntrack_zone zone; struct nf_conntrack_tuple_hash tuplehash[2]; long unsigned int status; possible_net_t ct_net; @@ -22499,12 +22506,6 @@ struct nf_conn { union nf_conntrack_proto proto; }; -struct nf_conntrack_zone { - u16 id; - u8 flags; - u8 dir; -}; - struct xt_action_param; struct xt_mtchk_param; diff --git a/bpf/headers/vmlinux_arm64.h b/bpf/headers/vmlinux_arm64.h index f6826170d..51ccaf36c 100644 --- a/bpf/headers/vmlinux_arm64.h +++ b/bpf/headers/vmlinux_arm64.h @@ -22582,10 +22582,17 @@ union nf_conntrack_proto { struct nf_ct_ext; +struct nf_conntrack_zone { + u16 id; + u8 flags; + u8 dir; +}; + struct nf_conn { struct nf_conntrack ct_general; spinlock_t lock; u32 timeout; + struct nf_conntrack_zone zone; struct nf_conntrack_tuple_hash tuplehash[2]; long unsigned int status; possible_net_t ct_net; @@ -22597,12 +22604,6 @@ struct nf_conn { union nf_conntrack_proto proto; }; -struct nf_conntrack_zone { - u16 id; - u8 flags; - u8 dir; -}; - struct icmphdr { __u8 type; __u8 code; diff --git a/bpf/headers/vmlinux_ppc64le.h b/bpf/headers/vmlinux_ppc64le.h index b854f7559..aed586c7d 100644 --- a/bpf/headers/vmlinux_ppc64le.h +++ b/bpf/headers/vmlinux_ppc64le.h @@ -67125,10 +67125,17 @@ union nf_conntrack_proto { struct nf_ct_ext; +struct nf_conntrack_zone { + u16 id; + u8 flags; + u8 dir; +}; + struct nf_conn { struct nf_conntrack ct_general; spinlock_t lock; u32 timeout; + struct nf_conntrack_zone zone; struct nf_conntrack_tuple_hash tuplehash[2]; long unsigned int status; possible_net_t ct_net; @@ -133097,12 +133104,6 @@ struct nf_hook_entries_rcu_head { void *allocation; }; -struct nf_conntrack_zone { - u16 id; - u8 flags; - u8 dir; -}; - struct nf_conntrack_tuple; struct nf_ct_hook { diff --git a/bpf/pkt_transformation.h b/bpf/pkt_transformation.h new file mode 100644 index 000000000..e73012d15 --- /dev/null +++ b/bpf/pkt_transformation.h @@ -0,0 +1,180 @@ +/* + * Packets Transformations tracker eBPF hooks. + */ + +#ifndef __PKT_TRANSFORMATION_H__ +#define __PKT_TRANSFORMATION_H__ + +#include "utils.h" + +#define s6_addr in6_u.u6_addr8 + +static inline void dump_xlated_flow(struct translated_flow_t *flow) { + BPF_PRINTK("zone_id %d sport %d dport %d icmpId %d\n", flow->zone_id, flow->sport, flow->dport, + flow->icmp_id); + int i; + for (i = 0; i < IP_MAX_LEN; i += 4) { + BPF_PRINTK("scrIP[%d]:%d.%d.%d.%d\n", i, flow->saddr[0 + i], flow->saddr[1 + i], + flow->saddr[2 + i], flow->saddr[3 + i]); + } + for (i = 0; i < IP_MAX_LEN; i += 4) { + BPF_PRINTK("dstIP[%d]:%d.%d.%d.%d\n", i, flow->daddr[0 + i], flow->daddr[1 + i], + flow->daddr[2 + i], flow->daddr[3 + i]); + } +} + +static inline void parse_tuple(struct nf_conntrack_tuple *t, struct translated_flow_t *flow, + u16 zone_id, u16 family, bool invert) { + __builtin_memset(flow, 0, sizeof(*flow)); + if (invert) { + flow->dport = bpf_ntohs(t->src.u.all); + flow->sport = bpf_ntohs(t->dst.u.all); + + switch (family) { + case AF_INET: + __builtin_memcpy(flow->saddr, ip4in6, sizeof(ip4in6)); + __builtin_memcpy(flow->daddr, ip4in6, sizeof(ip4in6)); + bpf_probe_read(flow->daddr + sizeof(ip4in6), sizeof(u32), &t->src.u3.in.s_addr); + bpf_probe_read(flow->saddr + sizeof(ip4in6), sizeof(u32), &t->dst.u3.in.s_addr); + break; + + case AF_INET6: + bpf_probe_read(flow->daddr, IP_MAX_LEN, &t->src.u3.in6.s6_addr); + bpf_probe_read(flow->saddr, IP_MAX_LEN, &t->dst.u3.in6.s6_addr); + break; + } + } else { + flow->dport = bpf_ntohs(t->dst.u.all); + flow->sport = bpf_ntohs(t->src.u.all); + + switch (family) { + case AF_INET: + __builtin_memcpy(flow->saddr, ip4in6, sizeof(ip4in6)); + __builtin_memcpy(flow->daddr, ip4in6, sizeof(ip4in6)); + bpf_probe_read(flow->daddr + sizeof(ip4in6), sizeof(u32), &t->dst.u3.in.s_addr); + bpf_probe_read(flow->saddr + sizeof(ip4in6), sizeof(u32), &t->src.u3.in.s_addr); + break; + + case AF_INET6: + bpf_probe_read(flow->daddr, IP_MAX_LEN, &t->dst.u3.in6.s6_addr); + bpf_probe_read(flow->saddr, IP_MAX_LEN, &t->src.u3.in6.s6_addr); + break; + } + } + flow->icmp_id = t->src.u.icmp.id; + flow->zone_id = zone_id; + dump_xlated_flow(flow); +} + +static inline long translate_lookup_and_update_flow(flow_id *id, u16 flags, + struct nf_conntrack_tuple *orig_t, + struct nf_conntrack_tuple *reply_t, u64 len, + u16 zone_id, u16 family) { + long ret = 0; + u64 current_time = bpf_ktime_get_ns(); + struct translated_flow_t orig; + + parse_tuple(orig_t, &orig, zone_id, family, false); + + // update id with original flow info + __builtin_memcpy(id->src_ip, orig.saddr, IP_MAX_LEN); + __builtin_memcpy(id->dst_ip, orig.daddr, IP_MAX_LEN); + id->src_port = orig.sport; + id->dst_port = orig.dport; + + flow_metrics *aggregate_flow = bpf_map_lookup_elem(&aggregated_flows, id); + if (aggregate_flow != NULL) { + aggregate_flow->end_mono_time_ts = current_time; + parse_tuple(reply_t, &aggregate_flow->translated_flow, zone_id, family, true); + ret = bpf_map_update_elem(&aggregated_flows, id, aggregate_flow, BPF_EXIST); + if (trace_messages && ret != 0) { + bpf_printk("error packet translation updating flow %d\n", ret); + } + return ret; + } + + // there is no matching flows so lets create new one and add the xlation + flow_metrics new_flow = { + .start_mono_time_ts = current_time, + .end_mono_time_ts = current_time, + .packets = 1, + .bytes = len, + .flags = flags, + }; + parse_tuple(reply_t, &new_flow.translated_flow, zone_id, family, true); + ret = bpf_map_update_elem(&aggregated_flows, id, &new_flow, BPF_ANY); + if (trace_messages && ret != 0) { + bpf_printk("error packet translation creating new flow %d\n", ret); + } + + return ret; +} + +static inline int trace_nat_manip_pkt(struct nf_conn *ct, struct sk_buff *skb) { + struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX]; + u16 family = 0, flags = 0, zone_id = 0; + u8 dscp = 0, protocol = 0; + long ret = 0; + u64 len = 0; + flow_id id; + + if (!enable_pkt_transformation_tracking) { + return 0; + } + __builtin_memset(&id, 0, sizeof(id)); + + bpf_probe_read(&tuplehash, sizeof(tuplehash), &ct->tuplehash); + + bpf_probe_read(&zone_id, sizeof(zone_id), &ct->zone.id); + bpf_probe_read(&zone_id, sizeof(zone_id), &ct->zone.id); + + struct nf_conntrack_tuple *orig_tuple = &tuplehash[IP_CT_DIR_ORIGINAL].tuple; + struct nf_conntrack_tuple *reply_tuple = &tuplehash[IP_CT_DIR_REPLY].tuple; + + len = BPF_CORE_READ(skb, len); + id.if_index = BPF_CORE_READ(skb, skb_iif); + // read L2 info + core_fill_in_l2(skb, &id, &family); + + // read L3 info + core_fill_in_l3(skb, &id, family, &protocol, &dscp); + + // read L4 info + switch (protocol) { + case IPPROTO_TCP: + core_fill_in_tcp(skb, &id, &flags); + break; + case IPPROTO_UDP: + core_fill_in_udp(skb, &id); + break; + case IPPROTO_SCTP: + core_fill_in_sctp(skb, &id); + break; + case IPPROTO_ICMP: + core_fill_in_icmpv4(skb, &id); + break; + case IPPROTO_ICMPV6: + core_fill_in_icmpv6(skb, &id); + break; + default: + fill_in_others_protocol(&id, protocol); + } + + BPF_PRINTK("Xlat: protocol %d flags 0x%x family %d dscp %d\n", protocol, flags, family, dscp); + + bpf_probe_read(&zone_id, sizeof(zone_id), &ct->zone.id); + ret = + translate_lookup_and_update_flow(&id, flags, orig_tuple, reply_tuple, len, zone_id, family); + + return ret; +} + +SEC("kprobe/nf_nat_manip_pkt") +int BPF_KPROBE(track_nat_manip_pkt) { + struct sk_buff *skb = (struct sk_buff *)PT_REGS_PARM1(ctx); + struct nf_conn *ct = (struct nf_conn *)PT_REGS_PARM2(ctx); + + return trace_nat_manip_pkt(ct, skb); +} + +#endif /* __PKT_TRANSFORMATION_H__ */ \ No newline at end of file diff --git a/bpf/types.h b/bpf/types.h index 6fdff183e..b35d0ba40 100644 --- a/bpf/types.h +++ b/bpf/types.h @@ -105,6 +105,14 @@ typedef struct flow_metrics_t { u64 flow_rtt; u8 network_events_idx; u8 network_events[MAX_NETWORK_EVENTS][MAX_EVENT_MD]; + struct translated_flow_t { + u8 saddr[IP_MAX_LEN]; + u8 daddr[IP_MAX_LEN]; + u16 sport; + u16 dport; + u16 zone_id; + u8 icmp_id; + } __attribute__((packed)) translated_flow; } __attribute__((packed)) flow_metrics; // Force emitting struct pkt_drops into the ELF. @@ -241,4 +249,7 @@ struct filter_value_t { // Force emitting struct filter_value_t into the ELF. const struct filter_value_t *unused9 __attribute__((unused)); +// Force emitting struct translated_flow_t into the ELF. +const struct translated_flow_t *unused11 __attribute__((unused)); + #endif /* __TYPES_H__ */ diff --git a/go.mod b/go.mod index 77295ff45..a91c6131b 100644 --- a/go.mod +++ b/go.mod @@ -47,7 +47,7 @@ require ( github.com/containernetworking/cni v1.1.2 // indirect github.com/containernetworking/plugins v1.2.0 // indirect github.com/coreos/go-iptables v0.6.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect @@ -109,11 +109,12 @@ require ( github.com/safchain/ethtool v0.3.1-0.20231027162144-83e5e0097c91 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.2 // indirect - github.com/urfave/cli/v2 v2.2.0 // indirect + github.com/urfave/cli/v2 v2.27.2 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect + github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect go.opentelemetry.io/otel v1.29.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 // indirect @@ -151,3 +152,6 @@ require ( sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) + +// HACK +replace github.com/ovn-org/ovn-kubernetes/go-controller => github.com/npinaeva/ovn-kubernetes/go-controller v0.0.0-20241022150829-c03e72d94693 diff --git a/go.sum b/go.sum index e6d74d1ee..701875b63 100644 --- a/go.sum +++ b/go.sum @@ -162,8 +162,8 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= @@ -683,6 +683,8 @@ github.com/netobserv/loki-client-go v0.0.0-20220927092034-f37122a54500 h1:RmnoJe github.com/netobserv/loki-client-go v0.0.0-20220927092034-f37122a54500/go.mod h1:LHXpc5tjKvsfZn0pwLKrvlgEhZcCaw3Di9mUEZGAI4E= github.com/netsampler/goflow2 v1.3.7 h1:XZaTy8kkMnGXpJ9hS3KbO1McyrFTpVNhVFEx9rNhMmc= github.com/netsampler/goflow2 v1.3.7/go.mod h1:4UZsVGVAs//iMCptUHn3WNScztJeUhZH7kDW2+/vDdQ= +github.com/npinaeva/ovn-kubernetes/go-controller v0.0.0-20241022150829-c03e72d94693 h1:x2PYzfMuXA2XloyNMM1cTbYpR9VljnVHk1YkEQOj+mc= +github.com/npinaeva/ovn-kubernetes/go-controller v0.0.0-20241022150829-c03e72d94693/go.mod h1:5oVtJoJgxCHohAghvIMkdQZ40XueMQeQwu+6Rk+U1Oc= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -728,8 +730,6 @@ github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/ovn-org/libovsdb v0.7.1-0.20240820095311-ce1951614a20 h1:OoDvzyaK7F/ZANIIFOgb4Haj7mye3Hle0fYZZNdidSs= github.com/ovn-org/libovsdb v0.7.1-0.20240820095311-ce1951614a20/go.mod h1:dJbxEaalQl83nn904K32FaMjlH/qOObZ0bj4ejQ78AI= -github.com/ovn-org/ovn-kubernetes/go-controller v0.0.0-20240902083137-5d2310e77f87 h1:NHexPw6RbB7bf9YpoK+Cz3HTFYQc9jM60ai0EANquCU= -github.com/ovn-org/ovn-kubernetes/go-controller v0.0.0-20240902083137-5d2310e77f87/go.mod h1:bLkGnzUmNsq1ubG2kbXWXbIP7mMnXLaCxOXGyN6NPWQ= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -905,8 +905,8 @@ github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMW github.com/uber/jaeger-lib v2.4.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= -github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI= +github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk= github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= @@ -930,6 +930,8 @@ github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHM github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xlab/treeprint v1.0.0/go.mod h1:IoImgRak9i3zJyuxOKUP1v4UZd1tMoKkq/Cimt1uhCg= +github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw= +github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/pkg/agent/agent.go b/pkg/agent/agent.go index 2c57627c8..b246208db 100644 --- a/pkg/agent/agent.go +++ b/pkg/agent/agent.go @@ -177,7 +177,7 @@ func FlowsAgent(cfg *Config) (*Flows, error) { m := metrics.NewMetrics(metricsSettings) var s *ovnobserv.SampleDecoder - if cfg.EnableNetworkEventsMonitoring { + if cfg.EnableNetworkEventsMonitoring || cfg.EnablePktTransformationTracking { if !kernel.IsKernelOlderThan("5.14.0") { if s, err = ovnobserv.NewSampleDecoderWithDefaultCollector(context.Background(), networkEventsDBPath, networkEventsOwnerName, cfg.NetworkEventsMonitoringGroupID); err != nil { @@ -213,6 +213,7 @@ func FlowsAgent(cfg *Config) (*Flows, error) { EnableNetworkEventsMonitoring: cfg.EnableNetworkEventsMonitoring, NetworkEventsMonitoringGroupID: cfg.NetworkEventsMonitoringGroupID, EnableFlowFilter: cfg.EnableFlowFilter, + EnablePktTransformation: cfg.EnablePktTransformationTracking, FilterConfig: &tracer.FilterConfig{ FilterAction: cfg.FilterAction, FilterDirection: cfg.FilterDirection, diff --git a/pkg/agent/config.go b/pkg/agent/config.go index a5708d403..8675e11e2 100644 --- a/pkg/agent/config.go +++ b/pkg/agent/config.go @@ -235,6 +235,8 @@ type Config struct { EnableNetworkEventsMonitoring bool `env:"ENABLE_NETWORK_EVENTS_MONITORING" envDefault:"false"` // NetworkEventsMonitoringGroupID to allow ebpf hook to process samples for specific groupID and ignore the rest NetworkEventsMonitoringGroupID int `env:"NETWORK_EVENTS_MONITORING_GROUP_ID" envDefault:"10"` + // EnablePktTransformationTracking allow tracking packets after transformation for example NAT, default is false. + EnablePktTransformationTracking bool `env:"ENABLE_PKT_TRANSFORMATION" envDefault:"false"` /* Deprecated configs are listed below this line * See manageDeprecatedConfigs function for details diff --git a/pkg/decode/decode_protobuf.go b/pkg/decode/decode_protobuf.go index 0449acb96..f77483101 100644 --- a/pkg/decode/decode_protobuf.go +++ b/pkg/decode/decode_protobuf.go @@ -143,6 +143,18 @@ func RecordToMap(fr *model.Record) config.GenericMap { } out["NetworkEvents"] = metadata } + + if fr.Metrics.TranslatedFlow.ZoneId != 0 { + out["ZoneId"] = fr.Metrics.TranslatedFlow.ZoneId + out["XlatSrcPort"] = fr.Metrics.TranslatedFlow.Sport + out["XlatDstPort"] = fr.Metrics.TranslatedFlow.Dport + out["XlatSrcAddr"] = model.IP(fr.Metrics.TranslatedFlow.Saddr).String() + out["XlatDstAddr"] = model.IP(fr.Metrics.TranslatedFlow.Daddr).String() + out["XlatIcmpId"] = fr.Metrics.TranslatedFlow.IcmpId + if len(fr.UdnID) != 0 { + out["UdnId"] = fr.UdnID + } + } return out } diff --git a/pkg/decode/decode_protobuf_test.go b/pkg/decode/decode_protobuf_test.go index 6644d8322..bf67e06a9 100644 --- a/pkg/decode/decode_protobuf_test.go +++ b/pkg/decode/decode_protobuf_test.go @@ -68,6 +68,18 @@ func TestPBFlowToMap(t *testing.T) { DnsFlags: 0x80, DnsErrno: 0, TimeFlowRtt: durationpb.New(someDuration), + Xlat: &pbflow.Xlat{ + SrcAddr: &pbflow.IP{ + IpFamily: &pbflow.IP_Ipv4{Ipv4: 0x0}, + }, + DstAddr: &pbflow.IP{ + IpFamily: &pbflow.IP_Ipv4{Ipv4: 0x0}, + }, + SrcPort: 0, + DstPort: 0, + ZoneId: 100, + UdnId: "udn", + }, } out := PBFlowToMap(flow) @@ -103,6 +115,13 @@ func TestPBFlowToMap(t *testing.T) { "DnsFlagsResponseCode": "NoError", "DnsErrno": uint8(0), "TimeFlowRttNs": someDuration.Nanoseconds(), + "XlatSrcAddr": "0.0.0.0", + "XlatDstAddr": "0.0.0.0", + "XlatSrcPort": uint16(0), + "XlatDstPort": uint16(0), + "ZoneId": uint16(100), + "UdnId": "udn", + "XlatIcmpId": uint8(0), }, out) } diff --git a/pkg/ebpf/bpf_arm64_bpfel.go b/pkg/ebpf/bpf_arm64_bpfel.go index 3fec6b84e..542967873 100644 --- a/pkg/ebpf/bpf_arm64_bpfel.go +++ b/pkg/ebpf/bpf_arm64_bpfel.go @@ -104,6 +104,7 @@ type BpfFlowMetricsT struct { FlowRtt uint64 NetworkEventsIdx uint8 NetworkEvents [4][8]uint8 + TranslatedFlow BpfTranslatedFlowT } type BpfFlowRecordT struct { @@ -149,6 +150,15 @@ const ( BpfTcpFlagsTRST_ACK_FLAG BpfTcpFlagsT = 1024 ) +type BpfTranslatedFlowT struct { + Saddr [16]uint8 + Daddr [16]uint8 + Sport uint16 + Dport uint16 + ZoneId uint16 + IcmpId uint8 +} + // LoadBpf returns the embedded CollectionSpec for Bpf. func LoadBpf() (*ebpf.CollectionSpec, error) { reader := bytes.NewReader(_BpfBytes) @@ -202,6 +212,7 @@ type BpfProgramSpecs struct { TcxEgressPcaParse *ebpf.ProgramSpec `ebpf:"tcx_egress_pca_parse"` TcxIngressFlowParse *ebpf.ProgramSpec `ebpf:"tcx_ingress_flow_parse"` TcxIngressPcaParse *ebpf.ProgramSpec `ebpf:"tcx_ingress_pca_parse"` + TrackNatManipPkt *ebpf.ProgramSpec `ebpf:"track_nat_manip_pkt"` } // BpfMapSpecs contains maps before they are loaded into the kernel. @@ -270,6 +281,7 @@ type BpfPrograms struct { TcxEgressPcaParse *ebpf.Program `ebpf:"tcx_egress_pca_parse"` TcxIngressFlowParse *ebpf.Program `ebpf:"tcx_ingress_flow_parse"` TcxIngressPcaParse *ebpf.Program `ebpf:"tcx_ingress_pca_parse"` + TrackNatManipPkt *ebpf.Program `ebpf:"track_nat_manip_pkt"` } func (p *BpfPrograms) Close() error { @@ -286,6 +298,7 @@ func (p *BpfPrograms) Close() error { p.TcxEgressPcaParse, p.TcxIngressFlowParse, p.TcxIngressPcaParse, + p.TrackNatManipPkt, ) } diff --git a/pkg/ebpf/bpf_arm64_bpfel.o b/pkg/ebpf/bpf_arm64_bpfel.o index 983545e615857c57ad0f333f951b3048e1f95e4c..3612bb813d435bb980e43bfd6a7138b2a1340df3 100644 GIT binary patch literal 194648 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 PWi*G)f7-s>7A5>Yb(%lB literal 151712 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 diff --git a/pkg/ebpf/bpf_powerpc_bpfel.go b/pkg/ebpf/bpf_powerpc_bpfel.go index b75d4d539..aa20e967b 100644 --- a/pkg/ebpf/bpf_powerpc_bpfel.go +++ b/pkg/ebpf/bpf_powerpc_bpfel.go @@ -104,6 +104,7 @@ type BpfFlowMetricsT struct { FlowRtt uint64 NetworkEventsIdx uint8 NetworkEvents [4][8]uint8 + TranslatedFlow BpfTranslatedFlowT } type BpfFlowRecordT struct { @@ -149,6 +150,15 @@ const ( BpfTcpFlagsTRST_ACK_FLAG BpfTcpFlagsT = 1024 ) +type BpfTranslatedFlowT struct { + Saddr [16]uint8 + Daddr [16]uint8 + Sport uint16 + Dport uint16 + ZoneId uint16 + IcmpId uint8 +} + // LoadBpf returns the embedded CollectionSpec for Bpf. func LoadBpf() (*ebpf.CollectionSpec, error) { reader := bytes.NewReader(_BpfBytes) @@ -202,6 +212,7 @@ type BpfProgramSpecs struct { TcxEgressPcaParse *ebpf.ProgramSpec `ebpf:"tcx_egress_pca_parse"` TcxIngressFlowParse *ebpf.ProgramSpec `ebpf:"tcx_ingress_flow_parse"` TcxIngressPcaParse *ebpf.ProgramSpec `ebpf:"tcx_ingress_pca_parse"` + TrackNatManipPkt *ebpf.ProgramSpec `ebpf:"track_nat_manip_pkt"` } // BpfMapSpecs contains maps before they are loaded into the kernel. @@ -270,6 +281,7 @@ type BpfPrograms struct { TcxEgressPcaParse *ebpf.Program `ebpf:"tcx_egress_pca_parse"` TcxIngressFlowParse *ebpf.Program `ebpf:"tcx_ingress_flow_parse"` TcxIngressPcaParse *ebpf.Program `ebpf:"tcx_ingress_pca_parse"` + TrackNatManipPkt *ebpf.Program `ebpf:"track_nat_manip_pkt"` } func (p *BpfPrograms) Close() error { @@ -286,6 +298,7 @@ func (p *BpfPrograms) Close() error { p.TcxEgressPcaParse, p.TcxIngressFlowParse, p.TcxIngressPcaParse, + p.TrackNatManipPkt, ) } diff --git a/pkg/ebpf/bpf_powerpc_bpfel.o b/pkg/ebpf/bpf_powerpc_bpfel.o index b2b546195c68a05bfe941004bd5a25dde44d1580..22620c0948542d31148e2bb83c4d2e40d54c5ab7 100644 GIT binary patch literal 193496 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 literal 150536 zcmeFa4SZZxwKje-?X;yLErk>qDV&nFlt`g1U$qKOnx?eSHX%)*MR1Z%rfrfo$;nAS z(g+Svq*j!Y0wOA=rC?FnC{|YHxlrc)*~`Zq*Ymb7h~*+lK}l~0BnM|I zdvLPSqsJvU8~Km+sv*}p7$v1x*FxE81H$78AS@$XhTXzjBW!ai8ckFbz1YWik0x(}GHe4nJJcWC{k6Iy@itv3jN?O2sN z8u_EzghvgvNAVN+?o~P#Wn+6gJC3GPMZ#dHk^L~6^+x-S!4>zuB{~OZX!@Y(J=*F+ zxhUrqit_&YDq&C$Ow6UTI(%H4jXHlVms<8bmLnRdk0G3@)V2Faa=g{a<^6fM-#UNq zGyiQ*ygYyHOKg{V=u2dcZV}4zp~}3z@k3fqyVXwiuPvzWzJ&IR=I%O4Xb#lx2P6J| zALQtNUp%DP-y6NBL~nCoe%`iK;_Zo#2+jMsmZS9!?UzwMrycvPy#`mSeNn&v6Z*hK zV6*-jy>E-&!ukyk*Za!L_6X>`Q_B_f&z1OEv=g%kuAd|E+DSq%PHDN1hW|xFYqiFv z%vHmJ8&4HRuxqx^wXlgPwJTJvb)nMoQ8Dif!17p`&`Ya#NWf8Is-cmwFU7N21Ex%NBW$`@_N zKeB(>xUe7PrAGQk0+$;<2CqN_!HpXaq0)WCou6-*^k$UY^ICWRN$kdW{11))(c+#^ z=Xbq(HNE#X<@b$$M$(^z7PyqxK7Y2vgX^_^!o*yONBzU6-Fuh|`YOsh5%DKse-iPB zK-nT37Z^6wEEW5LUB^j0oI62iuxpCN53~5O7Js$H^?4LpJqNp3E9kFtb({!xakOC^ zgFZsA>u90jTyzSF>%bE_f7zuE&TuYA7s{6l4d?1}GT6n|r9L%0*mZ=(Q6Pk1mo{KH zSBitUI(Rr26(H%XJ>Jh=L3u4_Xnqj%pCbHls+GTgmc_07{U=-8%HRK5i>sdn{goEC z^7o%)aVvlSOp9Cj`%kpE^_PAfki)4~{{HEfZsqTvW^pTje}%=Z{QW0b+{)iS)#6tE ze&6C&{{G`FE(HCYUZH+Wi-LabzqP6c&)q}K?{qvU94FlP&|Z0%`r{r^C;oRR{I78Q zxf;o|q|wuMi~1|&qy6xi5$qX@X9h8~ zi{mbPO0D^&tJh$(mTxW06@6v=gq(H@FBqkMmeW_Je#rbqpEjEp#MOV+f{30`TK-xN z!U(|_t+%xxV%I43N9q+lX_e!+!uE6Xh|MM+Hfgz{eBKu}Y5785@8`J8{6n8w^3R3Z zDv5f*Xzjnb^2W6P)=snZxcUvtq4lTZL9YJlot*a9TzSW6f33|}`WWrsx$=(F{=XK+ zNqN_)oEzV3tsZMvD!+Dt(&kX<1WTtKK3KI^Dt}PT^ERUzW`h;Z*7l0>=LuiiEz0+W z&)PzLNA%1TzWPO!&-w^woBv1Tr5$E#dxjIW-8tW&=5V6=MelB#_eAbfyL7xCG=JNS z+oc>y9rp)yxb`+fjo4MEQ-j`bSu&eiU|58`5{$xS!Q_4=1WWgiSWCm+5ma-*5G~ z=lX5$9_`;Q9!}Ksd_C&@!S2Up91JJwINQ4W2Npj~?8wWXF7ejgPg=Tm#C-ahlHR-f zfTZ{C(Qzj9-zfY+EvCo*B< zPX6nJA5J_=Xx@HW1wDI&$n#*N@pMp!2d{8kFZcRnzEn8==I5{Kw@jA`(rje@MSGpz ztAW`g_Ct;#ZO^m)V3L(?)A?A`&VxUMC zrge|?kIE{Qhrf$_C71WM(E6OANX8w6a zeCapymlW}(-^^cJ#P^{uoPTZ+U;54bMMZq+H}h+RA68Zi%{><@7fL*x=rX$A=sKe< zMw^UYVsxd^2BBf1M`+Yf+5e(`I+C9k`stuPPQ3Clhm7p6I?Q_IW%>Silr|x&S^A^Q ztI`scc^g$;V|v3j^^>Chf_A=*_oJN{*pIKm)#&MSvQR!hF8uNDlxO;^0y{Xuy73_H z{Z8Z_YyuM@?)^sMt-J5h`kScZ*JkJtf19Y|T<`9ETCb6DQ~b!+@h>`_>iDbUc$6=G zNB^wpuGeDNb+pC3`aj=ythKAz*uP4}$M`qW-s4@LQE zuda)td>{FRzOIj=e6{zrG-udzMD4Zp(nM;F+Iy13dw1Vl!d?tU2+@4h-Wf%FwRd_E z-v=l3rxo$l-iji=+IxcV!->Aoygy8pc<=6=CG0(3(u?gqu86PpPATI1;Do-;GopIb zUYnOi{7~(+_4q_eMeA25UcI}wm$297VG(^=zcvqx@YP)LtD}dUt0_*sJros6Mq<=XX)Q+N<-tDBnkZp|A76C|~Wh`FNz|0er-%8VWVS&DjOrOp( zi|uPHp|8R8)febnVftp5u&=pFX}g7n;7h z682qDLSI(+;l#^@=Kb%j5^vtE>yM}%T7Q>GdX%sBy~XrxEzs9z`c{^(@9ib@Z8v>y zE6{h1>1!yV@9Glzwwb;w3-n!O`kG4UyS{|Jou=!u?$x}&lxxQElkv%aC+$1W z_Q&UYQm(%7&;En_VAm-mIG53RT(E1F#Sar2>^j-vueSJWEq%Lyu#w6Eq;Q^k1!LU7J< zoW^tKPE#yyUXM@zhCF~;Z!Sszs~FP z=T17G52srB`*j{4+WQYdzs}#osaF1e9jL>pR{nmSuZL5u{QdMM=5OWi*LHU2`oZ;c zB|W#_+CN9)Zhtj@?sTf~gZ|kn5A`g8J0E$a=T7@!4lOMAw4Qp^JnS2(UmmZ;^7<+d zXg}N|*&g&fi#6cRgWW!Dd*zdIzuPx%uhe}nx6d8-J}&*m?UR?<&uFxLmHlc)(R&s7 zeUCGwA^IvGmwerO0_h#kOFX^fk4B$0`fH&h24=)lc31LAUxf&qe4FL8yM8J6EdE{A<;{uy3h$v7LM*u^jYx z?$^@u;+~EhLAUxh_0k`LK>geKMG$I#$eoJ?+FxiV?{w!mL67=*?z|~fLuyZl5JIp~ z`$g`&Db#+Gvwwxj**ODebz;v(_4nF3OW&mZBX{1kQ5}tX#h#4H)#`BL)mB@4s@>mh z_3X;qWA(hi(tE6)QAtwIT~^OX7X3+;tM!$p$D3ay%rEAfUtFB8|13mV@6?x0JR|-R z-A^3peD-R{qKb2VQtnkV>J7qfhG42sBJWK|Jyjep@mzaUXn}L>cG3wd55JRgyiTHC ztv0Wm8!&_NL(0T2xqr#5g5Wd}bngiTsuuf{YKS{8zI4v1VxNm=a4yR7mXCU^lw+_; z)F2+0eek&Vv@ps?jgseH`KTG*d~lpxdq_Oxommd#`6kwj9@w%1ffu_(av{+3VWVSXYCftmB-aDf{i-f2KFKZ>zjAD_jIPr zv3%Y5Uzo3U3vbF9W|w<^p)g;QyYvj**pGYKo23Vd3}QuIatEY24LgK3(~D{gRXO;grXSbBkJ+G&0{pZ@* z>apCl^Hh88SLl2o*M2sRmfL#)!Bm?+ROq~-P_7Yv%@DYGNCmxL-%k*K$mvsl5Zd!N zn5}X!TIAH7yeZ|*UoGG1mM^jqIc+Y;S-uro-@$atw?OXFa`g+$CnZ1EuH|u!2QN_% zIr&klKi95-mZL9W?OISC_g>@6dh??m@52S z`);)MEzmcmL7zK8s15GwAzzPkRloT~uHMW)-1`cyUfumuPS^GcDzrSgcA948vU+m$ z>z>b38gzc^@|kkFjeiwZ-f33ef_k3P;GP58ewUu!A$G^*ZCRds>i85?yi_~bxMKaH zZ@wERtp03#>AP6-apQy=A9`;$|2dsr;(2GEVe|D|{W^VCucoiGo<`9#Yej=lH*UJ; zTjQw1^zMCJ#=}di z7fRga@6PeqIx}&_%XOtAhCs2a4#Uv2!=c5Ae8+P&{Q;VQk) zonKP#@nGfhfnLd{Mg3wBQ2m9^UCBSFRC$y~^0#p@=$WQ`*Pfvomg|ojr)#=v z&v4}a7C0Y+AU}p^J5c{CU6+)5XNaTa)*}@@)yn&rQeRW8zI534f@xM? zt~^suP}y}KV3-_Mkdk$QFU^0HGU zKR3T{<9zw3akgIh4R6og&vnPPVeu1(tzX>zjia8{bzF~YH@}Ygg~VO^xN$MRj=A6D&k%a) z5l;y%UdP-k{Mb{Hb5x)tnp8DF{x@LHNx%Ex&9h#n-Uzomp zy3R*tH9sQx_uBh1vnGE<;%>ehywY{d434sqcDDM?`Hfr0%&_%@^DmRj`Hfr0%;4xS zl0M}Jn{@sk6wLc;o8`9rI%fK-g%K3yd!flqHouv!^&J%EYjT%PzC&(!$#qPLdT{B94YdJ{XN&d({h?`>9ZXNvmV_mQTwsJ+27wZHE?YljLe2f8W8 zBeyQ--D~~J>8n{(ra5(fN*AAB*|W|#;Cf7HzniNJ36ktoct+SwC>qf@h|1ibAVCM;O2Sx z_qJb<=i1BNk8ZT@2^Gpm--mtSWxcnp{`+8)6w6x+H}(PfeFoCeYzdv$+~=^P=4rGwEpTA#;E zXAy^`Oa3~4VLG4B!_vWM9If*{ru&8IU^LqI@|d11Ob4UU=08l&GW~Fy-=b`@5r4>N zrfih#YqU-U6TzJiwNKKx8z=fI7fZXk??Z81WN1(5_lpaE2Ou~>)5~Lj5XpA?9fBoatiCC_@y#JHr z7ueZ*$McfUNP18ux%*pptK0;g&U%A)s{XNf-m!iMZQN%)b7eM|)^yf4>)rY3V88Mw zm|q9>-biS_-{8(k!^A^kS77grg!Vfif#nk>zG&$>p$W}@0(&ndOnh0=nJ=d9Ug><* zuk!hRz93)qx8Qne!Fw!;!Ge6%KlAxMDCw>5(SGjg%-hxzSpT7!La=ymd?+MQ1z&OhGv!+blq=NtKQpS4HtZK}UKc8=) zlky4Ho_r26q}!UL9DQx(r)_4}K20ABrQ#P?Xq@?RX!?5kA5^ui3+S%%l;|RNE=-%^*@Y()h<@Z%j;(J0jqy1R_ zp^cl(S5OM=9=T8T>G&MwtG-{FzF!pR({Vhw0v!|~csnve=-sE|7w4(;ug0=dv6IO8 z`YI;p`e~ni@2oGePW1LAti21yCFd7|2Wj`2&>L-cme>6*jvEK~d}KM@`%@FM!p7jBvjCO>h;h zW4iiJVCT}|e0{zJc77ht*LDmlbbb)de_ZM*uygouzP4{rq3ic>zWRBhD2? zwof=;{WLhi@~>2X4JPUSXIQCz8%(nDSE~O8lWhF6_tb((9Bt`m>d%4w-a%NYejQA* z@>i;V2b0taVWs+CFiH2_!biWk^j+-AuW(Z@^+%j%*l7dh; zZnoMFNw{&~Nf@o;z;DF=TD$eW!3w2MqF+h+{C}5pK8KP>;@ zjILY$#OJ)(#ossT`3L4z(8CrA6TcJvj5mQX()`3dr|6-D^ONR%+ODl1)Ol=lKJppn zYvtlN!NB~#|JN5^ya*Us;`^XCkuAR)K#>#SM$Z6*Z8}ekmV^2V-?L=9QIGqcE8}ro zHZ*&ac2wZ@Stdz|~- zi(1!y+KuJ=%+el<^jz2N7i~uRY}^+v((~Xbf2QztT@>Z}!e?$MXGA|a;Ub-gMESHc zT%;4eaE$KzZ3d6!569@bDx9J9z~`RuXJ|dS^-Hk22GZD{b@i5BC~^1uCP8|UrlYN- zURuu8IP8;pIbEWj``r(|r{II-e)r_;ZM-Z0+zKb_{o!QQ8&1~z-E)P0??XPEtae2C zQV)~0U7~!chsoN0;oFk9Tm4MR`?e~Hzm$Ku`LNrkqko}F4)Pwa?rWBNy01xp-7Y!l z2ge20d|ZAt3*+4GdD8#Vi3XwJEuBK!x316iOQ^v9nf9~v_!gBPuj>uAtIzcD`n*q% z*XMnD$4-&s?{P@_jvI3NAP#*!swek7b)65U6K^s87NgsYW{qBJbi2{_8NJ!)UZVp> z?>4&6=)Feo5gH~sjNT`-usx#tdmM)f`~S;t7kyq0vN92h_rW-7XuGZvq#tar695Z; zkHW3%-TwT3$WXO=KZ@_K@QFLC;(PdnpR0P$t^X%nC~U7+-P{ZKf*3-$QJ>QRJB-Bb z{E7pV#PvBHuwzPGpVPq_Em)Y*=X9Xm-wSP@p3gD-dG3An32WtcyiZ_yGMay|$@0li z8spt$rC~<-!6uiF+81mxJ2Q9yQht+_Bg0;XeUr&H&$j%YgqZZpjgssQM)*mv_g&*i^81lP8^q{c8SN>_*&*EOK#MxeF0?nGbN#g7Wv}Mv!;JbtFa{2Y5N6aL-0y0I8TE_6-fsvq`dkghIR95a3C6hoGfDIWV_g4IzX@cN zV7q901hXxF^CR|CT9&JyCQ+07eXlU1{*||LhUMezP=CwYseYKZL;Wvrr}|}Zrq)N8 zQGX1^py3e0j4w3b4(b=Ky~2$8Pre=0U-Io_{*r44?T7hx(*Bum2lfBJ&U?c6Ov%6X z3?bf=@Sh|gf3J#ubrI+rLG%8H3Pj*MlR52|7@xOVPc9zD=SoT#pJP-VGK}j!dKlMo zg>lypv>dKK6pky-&M>a_|Lfy{_VY0A`nCGI>)*xWoVDM7+IV)F)XR-lf4P2nhVnC` zj+JqzeAGhm=<-qeJ412rJh>zK9ArGt;$QT5bJXe4n;o z@qOC9gA23(W6=%S_|EuMU+wbH=^>d_{RiS?Iuj+rL^%$4g4C+sZIeG6_?P00$+_!cOr|ZPu z?N8{pZbrHf9rqyjh10de_Z_Kz?fj7ABSWe4lE&C`@{dN}iP<@QJCWYEBPsDhyW89JoTR<&SxIki`>j#k zKWJ~WbEURtjIaAZ?QOc>({B5*?Y0lw-lqFh?QOd6+TLd8N^OtZ{dTTo`?~G6KiuB- zsHN*ZUwhjl7PoVywudeLC8J+3s{8-#_Wo0Q+h>Fy-G7MgTe$WteSW0-7wz_ay7ICQ zNjsI7-6{Umw{@Q7dx_9=!TvehYY6q-yT|HVA9LQIJ`TJII{g@SUNG$3XBTcpaCTDP zClPn&2+j|B_dQ=!PN#8beA&fI=d10X&sWcF^7*P?1c43|VZxmY zxqQ`+^7-m{RO=QU$K3uw{@h3Rp=j5=u&ehrZC}?OBl+8~cKBdjQF}SRl<{eVb{~&? z%Ey&B_W@t-v+>rABjvHz%ehbQKK0YaSbdCkObGFTuz#%5^wuV^r*G>@qh{Zonm*FG zAfMk+zu=AT+#|H}kkGzg8YXoAINbV}=nuEr`OQ{4587(yL0h%ohg-j4a@zmHt#%%? zRmY2PtDP@x)o~}>s{6~~R^3+*x7vBo)&r);&V#n&!C-jJ#+22 z^ey(hy2YMX2WcOU?749brDFMV^-=O1Zg_jeJzwhUe~RB0)<@sVs0WUu(Rw)ipQwkT zb>jSg&Tr%1Isebq=ln>0=I6P(u5!P}68Chy{{NC6aiDPhsZ_bc#B(zKMCZq!<9Tqu zxIuosfpO~^EI2L#n|d3)zli|rs|)Dm%(uB-apQbw>%nICT-YP(`;30j=p9CH zH@es8ZAL$C^kYWvG5S%XA2Ir2qjwv<%jhSKe!}RzM*q#|eMa{SZMXARcfMTc=dbkq z)tw_1_Otx&T)h=ug??`53vur`TE<>W=*70exSM+otPZMv_^V_DI6 zg`RUTf6-T^a_;>J@_pVv)$YGaLGC@1E18P)3L(&cf`FXZ?~yrO@B$~n6y*u1ZI z?>uQo_x-WWC@_*IP;$;`t&?5%4ZJYJZA77vjss0k>Q)4)jrH4I}gvkE`k@}da{ut$poio+1qkOS*ruuhywDyC|D5ThVwDyz2 zeqGo<-Toinr$7#VqyO7d3vz)=>4>kddOpN^;M{+lw7Ivk=|qIrKsPdeWgceeUxtJ zr={jELiwbgV?UEP|NkEY_bC|~57B{=^BlMk-Y?R1KF@0?k#5uHRMZcXC|_Z|^b^WA zdf%0N3gx5Eqq|4Azwmvaxc7C@L%Uegk@g#C2kVt~Gk*@P&AZk9QuR2+ez%HxL8Mps4Nxcm2`$2uSzuKNSV9#yc-)v9lzSw`)_juavdlBu4Pnlghzi3bBJfuCL z^N;p~&THKN`E>s`ljWpGy64TyZ6DspakB8f<~y|AqU#RVz8qOx`(6aUq`~E5E|+?r zKISs~;zoYGQ9i0q{cksz2z-x)zn9q8X3yKz%I~xP>qx!yAKFDa(s_@wgXzw0XOHu@ z_Jr;iZiXHVC1`)$U!>kH-ggx~5MFLQIlX;}nbJPg!_b~sD)Dq;vCux(Uy(k9^ucQ= zg?#ieTl(B8R5@1;>X&n?0z3aRzOTgkbNjIDuX1jc&gbvypB%T&EIzkV|ID8s={z`p zex!bz|GtvWqXYZ>k-3^F_}!#XoFbO#g`P(^5YbxbLI6@1YfakE!he$tP_4ywM?}gGN7R^s`2F ze>H6Tw8g(*^g*NFGWt!Uj~e}kQ9bu~x!;3o4oaO{eMR)S`P62VpW{bZ`DM+=zL&Qd z^}un?eQ&QhpcMQgGXLar@}K=4R1oNfZQNTSdR@Dg`W{kW!T96a{b23Nai4xC{T=0G zdEECKiqB`XJ@e-?+OGNU-)Q^h&u6rq^WVSG_RgPMX}jmot+f4vZd$>5Q$NUm|3=#- ze?Ft_kw2e#SlTClZuOAG-T922SLeQe^F>S7dJZeq-}2{H>UZ>iwqxmfQNPUBi~482 zUer(X^`icouNU>(e7$_l?1F^o@~f8a&aLcwS-I~ex$`=Ap7*%PtG|bp z?!3;`%XclEqYmp`&+GEvOL|PxbLUpy*0{YFkSRM&`bT-$Zk^ZW&Z`PCC5=4m)$t(_B&m_ar-j=Oh1W^f2Gf<^nASZIhCHX7N1k;{ImF+O6Q}| zd3)jakA|O9{aD(ib>E+a#=Un+{g;=WXy;V51?N;#CH=pN%DANnm~$+B!05 zMnxmUJ$=vk{{_EciJae*DsPy0O2(V$Jed0l?ma2@J?H(SqDnCm?|B|$`=}BAY{-Sj*gk56KU4U&j~e0o z!q0$`|7*S z*K`O|Z*cumjl(|X@Ak`c`{e!0H67y~$Ae(kGKsr=?_gK0raOH%)M*@(LD6@*L`#0} zuy^+}((Y4^TqA-(f4$!C^1J>5iRbOtc`Wzs)&2&RFKPdU!}aab`9$9Si!|NoyJ4lq zU$OmKPeK31!}Gg-mBjP*ziD`W*I%OXlJ>uOxV~MNs=m2G&>ksG&)MIk@mFmBnQ~vy zuMaeyb4Yt%-z@yR{b|+j^1Hr8<0b9acFpPAl~H{;`_~TFcf&f3zhe9KTz^o_m+#5K z#G?1adiSWmx#tqk8|FbSoTGjl<_Fv9hP{khi$ylzibum6szCA+ZJbk2b&h2Xz?!yl1cDq+T_D)g2 z=M43SiGOzdyi4@_-#dQ(PU`i4$4~XA{P_RB<0osR)c5A|&#(U-KUq)FaqRye<0nT= z&J}fEgySfO)_?u{NuPsp@A?<0znnh=g;01tmp}j2c@We0illyUeam);d-}X`^IF=; zkQ?tI$H09`A2eOLQs!mpO5Nv8k8jZUcs-}+-80kD7Yc3PafwjoN7d;{-A`^$v}k%_ zwb3S{Zx-s#JK7WLjo)T;ozXQ$dyIA)?K0Y7^eslW8r@=alhJKPuQZx9db!bSjqWhI z-Kf4d)tmDY{Qd#$W8nEeR|E%p zKcG~4^nT9qP_5ENzH_rb9lvT_EVr?%Mdb=)x_f&3o^B}2YZ^hK)ZHDKp3R-z?S5ucrlTkH zb7Gk-t)W;|psPUsV8-Wk6{u)#X<>15+;r#0^(`GI_W0eIFw?y$>xkJr|MZmSdQ`};*Ge#8_hj5u8a=D#lTrA_a|vb6Rsn1v9IwdO3c+# z7p`(#TX1bQ{5h7a~#|M2xQE6lky>tOE z`panM@A^0;T_0x~vfVi*__*AdFaYe@+=me<=%J6$_btT4UlED6iPSN8EYB&plDJsr z*`QfmEc0ogL%5=CvJQNN!%oLXJ_|2)mayexSea2K7hZFw7?UpoJL6=qqtQ{zh}`y$-7dRkFGKKdBF9+tcN5p??o6_ zjgLm~@h87x)C|DT3JNi=3lye%mn(l<4e+(V_!If}Dc`#dl=2?}rTk}=Kki)Mhk(&m zBL8iZ?36QAcue^LHU*9Ea+=MnbAyAC^&sIJ2ngU|9;UE;%g%92$_~mgpU)GkL#^lIvcRaf z5By84j_(6zcm$MX_`coqXHZnHcQ`8w^i)v%d5iIZa(Qb&$AZ2Ul=j>T$}#^wP|lkk z1!bT6B`BWRUK}@Zel!b|{=5W~^NSo{bm$K79mo&j2hN<9Bx)_u{v$h0u8t8eTNzn5_SAi}CeGBL^(D#7Sx9j0CM zV=M3wl-Gh!JCm@W5tzQ41zu%%0C+Vp%^m`7GyEuUx8Vc8S>O$jc@}slF#8N}*}Dz@ z9{Bx+|1ipn?KS*I@b5DGAHbh5{3qZc!x&e~zH0b+=x6BQ2P*4_;9mtegns=K!v}z$ z2Hr*)^wWPgoCJOrSjq_e7vQTQG64J{@Y|^em;tKo7Z$ah$s3OWfo;ifI55U636p`} zY?uTlj%FUmfp5<$uflMW0tob#EP;j?eTxB25=YneWQrLX2hNJ{9tobt&z>)Dmeoanj--F_yaze3&3(Kjl;T zbfTE64_BVIL8jSc-VO|YG{kmT%*o#ZnY8hC1FtpwQDB5|E%?}PI0O7?!)t&)uh`W~ zS#&LgWCm1IzQ4_81Od!A+(1H`(XT?6Yv&&UN816mN_{;O;r|i19rq^fevsID!>BKe zDjJ+$ASSl3zrg2mf%P!YVx2}`gzmnagpA|cC^Hr}v+pq+158~AqfRi449ZS6j6BMc zhS5!8=NZQ1sB8r=_0a!Xj1OG4*)Sd%Wmg*>4}6nh4BcgS7{>5hw%;%c8+*Vohpz7$ zMje;^$S{gj_OxM;vOgQfv$hQXdRNMV=WQ9ko`WPlbIXo0JQ>U<#pPU6}GK6HCcxZVnkc9DL2jqwK%XXwE- zM1Zgb*8yDDnhZM%LoY7h@K)d?@C}fm4SXBtF2ha0Lx#J6ITzaunJn-(jlUE4Cx!=r ze{c96;33E&$i4~zeTlyH0%W?$un-z8Lj@zqJ_rHiM^m0(L8NUAM;Lbf!|6O8{EaFi zpPLN-PHB5-k9gOp{TRxzq()SKp#OE=lUMA#_-|2$M|mp-V2PXm$Kgr zd<}RE_nXXijpk$?03Y^8Lu@n{@5P{w`NFp6fd_!!VG?%(e*`#*2KXc}@67@~47?F| z0QmdB9|ax)ehQd24B^4{D`3hW0R9v3XMw#jXiPjbh=+hD1AiVkI~Hp#V9F=)z?%!a z5x5C>0Wj+z3%tzm0Psqa9|B%&_y90}xBLOfyA8(&0h4%e_JRKl^#ETD%yMyI+7C>d zlfVPOw4n+3Lx!`!_XA%I{s8bpz?_2&0Wuffj(pAP(W;343%f$=8`}#_rVUBpCc|0a5coH|7q}0Y z&wwNzAa4hz4O!qDfmxpez_$ZGOL^db1IC|s0Qj>2_XA@gUiLM^Wxzi$90UHP;ZeZP z8^&a8G$-x6mj?;uz+F@WJjJjNe3D`Qr1^fS7AG8VA6_AH3cv)Q60^bNqxtoAd zZ0}}_g9C=&hb%v0`2E12Hhe4aSAf~R1GpG&!Zn2J3GiWujDpXD|3SbcFvC7v#52LC{X@WK8|E6G;ci?9fa}5MIOAa~ zz0~yhzziS8++g_2#d*o|>oM>*o6L`Zsh9O-!G0Y; z@{u*-(~zMrG5j%t$6#T>^73A;i{Td%4hR1|KuL}AGv@9mc5=keqpgpEJi<8mk_51% z4*73y;8W2Mdlre6;8TYAo(BAZhy*H1YqYoLMZFCoK(&8X7cMq|Xqs=ViU8+ZHCiINV!%6IRQ|}h&>x1(`Eb~;7LXoD%P2;2#B?#pUiD0A_&B+@8>&vSjaX$S?`>rOoW`7aBjh z-}gzg?O-yz4doKs9)!F+$HC*CEc8qJvMkh}#KnD2;w&x;F%d+BHnUHC9eTcCiH}9F zljoVe!(RgU5oF+sqm!tlUje_@5`PcOew4)ZXTw9ltSioulF;*aU_Lvtz@v}Tb{_y9 z2mE#Lhky?QmU2Nq*Msy8ANWXo0jGl9PiEM)}#KJY5gEUu@3zX3Xgi*+dd9n?bXQ3GJT+A+WB08FEA{0cf;S^o%p zl%@a4u#fojz^Llc^MJ=3kM)kp9BMd=_$1)Xcy9+rdyGy3zZV#;A>l5=NyI*FI1BtW!$ZJ7cJi?2c_$BixUYJ$z?FuFfUAMo zwjlDplFN(l01+o~HTrfh@S6<}0j~u{J;+#fIWWgphAVybpDge-!0@5bi-F$*{8>ISd!oyC^LOx2-hRN zK0}g_|2{B%vI+Rd!1RCC#m@}$y|rH%-U^- zAw)h{6c?m?Uqp<|m~lbnxwIAc^4Z034e+lNdN%@>;TDcbJj;5M@!typQ zXCLCMf7aW_fqzR$g#ExAN0PWcXSfO2LhL`vJnup95yq{>$9D{~9iK4#2c{xGRK`!v zXP#4*_Y;%h7+}Hv)4jxEe{x(b)qW2J7Gi$^eg^k~NICxk{1=z1H1;PXT8RBQf?qHu zSh=yZ*-4_B|KV;zx~p@S?&=#NF?q34Wn+J&{u3lJE=H_D+H%!2t=q%EYXTl^>1z$o z2EPlKV{Q{J3)1#@yytxTo*A;$wGEGR?~}kBXAwq!%J6952Mn|AzXVL3Y*Y4eVjtJn zjn90)XYxs4o{vx`$C@X==R2BpzzlrPzX|jy@DYZcFEB5LaaOKhLgo;|3i;BW*8#io)&NtUnEMNpV|2kuq>KS(sJ)Gye zc6av7hWt6Fqk^XovcsDj5_pG#jk={ zM;pcunf^Ygg`i5(xso)=rO7kJhfO};Q zKMnjTR+%ROU#H359N^=OFZE!U$*vCFI7wc#4x=(>LXWHGHyWNu0S&R^3_!g+KW;r8 z`v{2a0R=hK&*vMf0DjjQnt#^#)AH#ur}R*n46rfYgtVI=KRqIIqTvDXQP-m>^I_l_ z#{U@bDk?w&eZp`O_+|z&*qt;&Shr_{j6ic5f1x z@3o0M@MFf$0`qK``~hIDafye3e`qoXfS)nU8vFzBX~@S1{=4A;;IU`vy*?`T2*XL> z;|w=hg`ZA4f%(oBhEzF=ooO;0q~|z2zzki!=b1dJ zaacOnO$(st`;bF8biT=f43k^^de!rW66tqa`Z*=ie_`p#f^?48^!Hc2LG>>HKI|Ns z1IWHf^qoa_j*x|+$3kW!=n$?Mh7S-|DxZaR`&!KNYmmWsw~cerr+_DeGW;4Cb>jKB z{%kl2JnD^dgzPl|j|V;$G)oL&;vrn+;G-#Mc-aYtac)<3nqjO>%Bl>H0&X;nHOc5p zfEU3o+O`gu_GE!A#LmrQzQQR1tYK|(L5u6L#0TuDH+kULgb1cA1It62 zS*<##rxDjW#1Rg?(C(oeF3-KMN#AGL_opf59l8>7PqfH88ruf&Ao&^ao9y1-0(U_u z`&#Yu#5;li4nF5H1Hj`l`Yz`X@KM0@JHC*9ykQ^sWW!0|(+xKPztM0O_*}ySz_o^l zfL9tm0K5ixE%ndB{+r<>@MR{G1>SCW0C=b2A>f-09{|41Fkh6v+prJ(Im1cd?-*_Z z{t@sc$Tkc73&VW5{;wvJ1&*!JvJU`{H#`JfZukK3@rJnoJlU`h{5s(Kp+5x(#1ENBa=9hj58&S0 z4F3f8-fQ@$z+W`{GvLP!{~Y*f!%yShzZrgJjyHM~8io1(8Zw6({tfWahJOouyy4#g zPc!^1?3rWudFY&P_^*(uHvBi>I>RpjHyi#taA5c!z*)mD0`CMCKb(uRRl`2;hk)_t zC4uiVoCSW^@DT8~f#u%Q&@T-8z&|yd1pb}jCg8sq&H|UMLq9`34*(wmEcJgne86xP zc&gz6;5mkefRn&%>jS_`fLWi<0;t3fydmJ(hWSO4Dw9b9*BNdCZZ@0+ZZ$jr92y=1zQXVU;A;)@ODi`T_JIe0cc6Zf zz#n!P&))}tFQjjrjrE1$Ebz~Oe?>ci|7?7I!DVzC-u0p$;3I%{0cU|va2U_6xxmz! zO=7GA<~TeAybO3F@B!dU40}}=%MJU$q2VO(TY-6R6Y#abthX%iEhaMrywC6f;Cq0N zh72b!gNA+JZvazI68L+-^sy%3-xyxEz$+Wou721B{v=@9nFT)1@Br`};2X+N7T~ji zZv;+OW4{jgCh~#nO`c!wxzw-^yaxE)lm`xhyMeR7S>T&_FYpdvAH!f*9A}cimw?Z3 zCvZTS<8W>Qyb+lD-(LaV1e^u_0q`ow4gvoH`0Kp!1U$10CoABS>vis#orZccJODi1 z@DT7Bh7SNQ0^SV${DM|Ja4&EY_|3q5z**pS;APAgxEJ^`%FjSqfZs}a;G2Obft{V< z#qThD^$f4k2>x_SoqF~iRS zKVkTJ;GY@hdF-zZj|2V-a18hQz_AYVdEi$8)3zqyBY>M}1MoE9)hr9}$-rsg$UlFI zajrH8e1vf+q@AT$w%sSn^ia}ba-abSaoGnu8**#|hNNN0yAb1ixf*=R-wbX&a0~NB zxCnR+ZNhai@T(y+4}8w^P;?0`;IlkFu2$d-(vrX%fGLy3wFwydy#ZX80e=K^2-g+B z_k()4$L+my-<)m0Hk*ixYus9h_`qD-u`FCS?ZCYpgOb2pPs=ISocsas*BSqA;C93J0CyR_7x+-`aLoq(J?Idw*8{iG9$e>{49ngG3?lo48-Uv= zgU|zvAn(id0guLC5{zhh-5Ep{_qa2N0pKekzaDf5*W2`7*-P9Bya7Chn}9nEzYq92 zWqW&p`MVM>psvIZbLZ$taA)Vv4=KYsh3iXQ@!se@C*x3wW!Z3hvgkAu!S#2*9x7%0P!fa$9~u4jSiZ%JHy&xd12 z6E04kh_krH0Q0#r1bmcX7GfrF2%5xYA@(=mx!|)b81B3(Cl6d}I0@|DBgz6ZUzjU? zaw%kphj4Md-b39H{q}E(!1Q9TqM(M@p%J_#FF!sO;ct!bWf5ohz9qsxEFyoo@xj7y zp`qERjPr_P*@&DQOA6%X*7b7kIn1#S&nYSH_ZyfL(j>{TX5(mj%&z4V8ew$STMmZsqDwJtBI! z>G2WUZa4|tZ@3BgeZVLt`%T#g4POELF~e5^?>BrE@aGM0L)Kq5jDA=4sNwA}>j}fx z0zVDRzPl4L+~Xm>9@`&(F#gSmzhLqM!0~Ri=N{k*z-X`0N#LV^-(huiEN~h;R^(Ht zpKC#rxcL0s37W-q5@eXy5b&vn9|k_t@T0)z7=9dh5islD$34vJVo(OY8^yea7|{@W zC*&DGUi~h^*MVNBI^?${)&MhX0W}duV_bV!h&>0qUGI^0e>bpecjt$`lh&s8uE#xW z_q-Z$fgGP{4Dbtihr;JJv3{L)zhz$pmcfNXeME)~|ebFc%u?Y~g z5PKnSbPRibF2vpoT-PJfaqk0O1Zd++R%M;ymau&@8S_@RxxO;c5c^ za8OpzCh#dU5%@C0KJYb84=@ADF2n0C@ZSR-_ui@R-H6|U_ALqmE^KeR_+^ zIeDHTFmHF?b4cfXAF%s?$M4DGL)g|c-a--Yu-)M2lf3b_=Oc&Ek54tZy(V`~L3~L; zyrCezt{^VC!k)V$`EVR~tI6GE`D`z^@6Lj_=|L4@?+W+O|1e+kzG`y!n4WK0T-t`h z8sxrOVBW{;M<(}gcAtuQu}>myVf?uOzc9H^6v*8lk*kK>vnF?6f!t>za>qmNd6WBe zf!tt3?lm;vGJbf6eXc<6fruQPW1Pu-zCiAa5xFk`PlO!%(rvhhzRtR1I1c;-D95Q8 zrt1p@y1pFI`$mD>w~j zZSYsIjdn0h#5F^Z`ok>4J}Aq_KtI8@padVEOB4$Kbm+v=SajZIdC|A-Fii5n2;LXL zcSi7sBKX6G+4nvY;eRxOKW3O?#1DWuKG4o5ffs<%XMY5|29$nz0C+nneeWm0dqL@6 zKLdUYls@z{@Qa}IlV^aB!bM;B73eHntdBRKyns^PdjS|&-i6>Ja2W7-{)iyBHp1Ua zLE|?>_-iBh<5Tl8e~IAUh|JRC^D^5a{C7m~jSwC@^LxHd{+kj0 zfe3ysg2!d^@)INYxClNmg6BqXRRk}M;5S9^`Ut)}f^Ui7J0chxKs{b6RaIYKwJNn@ z$;CCPhE;Vnsg&2#+m-P)G;c}a*J`_4Gojbg+MP-Fr1)d9p~ufuYm1|)9xv0gF4fiD z+0&WsTyL_iogH4-olb3NPJ1n3k5I;2yCe$2SXXCvkHiJw_jNl$qP()!^oFjKm?J3N z*^=>E*Q8oIS~6R_jdRX~`TX425w@=F$h7$3I%?cFkNkOgc6wcNx3}@Mxn$!rC(a6x z;%vyEplK_cMNlyP1>w+J-P?m&2z#1g+lJ1L&Qwq9hD@p_^fDbS!x?MVH?IY|ySt+k z1xt5%UF|(7{sJ*7u_H{O8aunK>hP1op8e2oN`Dv_wYsH%ziRC+lU5O1Qz#XT!dDn(#;#gOvDu2h^C}?N4nQ*&-8kmn%8e+>vx%|=Cy0P zGixExV(qV$;)=pjIgf~7R$k5{OeFNyuJ2skygr5BBJSwPbfdak*Mp{zt;lEAv~EeQ z&vbaLT`BwwbF)hqlOO>{szdv(U^}=-O-GA^a~zmU=gLc3gpvm5I55|vzo|kZ%8<^H z&$%AGu7SOQpqk#-obI7-_oTZPNljZ3w2A56(p4Y=dzUOfx4ve@3a>`VvZ|G-g-hyd zsvDNnE_Y=!eWpfZxV5Ufx~8tdtFJi^;vVl@v}9>RO?|3L?p{FytbuX}w=G(-Jhf

Wk_X@b;V>mF6PUmy4Lya2Ah0j-63I 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 OJrwD6{Au{2?f!qP{ZTXk diff --git a/pkg/ebpf/bpf_s390_bpfeb.go b/pkg/ebpf/bpf_s390_bpfeb.go index 1a2f37054..688bd3329 100644 --- a/pkg/ebpf/bpf_s390_bpfeb.go +++ b/pkg/ebpf/bpf_s390_bpfeb.go @@ -104,6 +104,7 @@ type BpfFlowMetricsT struct { FlowRtt uint64 NetworkEventsIdx uint8 NetworkEvents [4][8]uint8 + TranslatedFlow BpfTranslatedFlowT } type BpfFlowRecordT struct { @@ -149,6 +150,15 @@ const ( BpfTcpFlagsTRST_ACK_FLAG BpfTcpFlagsT = 1024 ) +type BpfTranslatedFlowT struct { + Saddr [16]uint8 + Daddr [16]uint8 + Sport uint16 + Dport uint16 + ZoneId uint16 + IcmpId uint8 +} + // LoadBpf returns the embedded CollectionSpec for Bpf. func LoadBpf() (*ebpf.CollectionSpec, error) { reader := bytes.NewReader(_BpfBytes) @@ -202,6 +212,7 @@ type BpfProgramSpecs struct { TcxEgressPcaParse *ebpf.ProgramSpec `ebpf:"tcx_egress_pca_parse"` TcxIngressFlowParse *ebpf.ProgramSpec `ebpf:"tcx_ingress_flow_parse"` TcxIngressPcaParse *ebpf.ProgramSpec `ebpf:"tcx_ingress_pca_parse"` + TrackNatManipPkt *ebpf.ProgramSpec `ebpf:"track_nat_manip_pkt"` } // BpfMapSpecs contains maps before they are loaded into the kernel. @@ -270,6 +281,7 @@ type BpfPrograms struct { TcxEgressPcaParse *ebpf.Program `ebpf:"tcx_egress_pca_parse"` TcxIngressFlowParse *ebpf.Program `ebpf:"tcx_ingress_flow_parse"` TcxIngressPcaParse *ebpf.Program `ebpf:"tcx_ingress_pca_parse"` + TrackNatManipPkt *ebpf.Program `ebpf:"track_nat_manip_pkt"` } func (p *BpfPrograms) Close() error { @@ -286,6 +298,7 @@ func (p *BpfPrograms) Close() error { p.TcxEgressPcaParse, p.TcxIngressFlowParse, p.TcxIngressPcaParse, + p.TrackNatManipPkt, ) } diff --git a/pkg/ebpf/bpf_s390_bpfeb.o b/pkg/ebpf/bpf_s390_bpfeb.o index 89ab5f0253e9db89a0327cfa61759bdf9272650e..4e6d731c27cc6c8b7e0f2c501e9782855a938f1b 100644 GIT binary patch literal 208336 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

=Wc^~`;c2Yn7lL`6YnW8nuJ9w62eGq;V{`J%?p^ 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 literal 166296 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

jm=C+XkM;Rbig_|7DOn_YQ`N@Lk>NQ?JzwUB z=PmI)TG#v}m0o?^-WcAOtPgqDvBJ)p^uw+a$n#9vNomYh%j2^1W%6Nx3i!Tarzq{( zMjl%P;``y#N0n?{iTt`wTi@FGoTcFdSheW+qoyimM zBj`ss5BT~Q`y2a-AC?*Dh4u90u#U#}lJWiP7=J&DUMqH!u9HK(qTZ^Nb$elbKRK-H zMLq1<{3QQu=8^9<^E}@5?{OxM^7BYM9~9d?N!}#M#8bT8cwQ;C>w2f3QnGl^=_#s5 ze{BB7xDm&Xn|xe&9(ww`vq(nWN=jeY}0>;^9Ao_n4KP1yJDaU%WcfSP0 z+eVW3g?P{Rcz3FF;5#Jj+Pq}ldq4#-PMhD=Uo*ZCFZ3Rf{IZvZa`MRd`2IRqZt^)} zlE+PdpJ0E^Ny)#6cfU*IX}Eql+26abR4M*>92q~lgkSMGV19URRUbbaP0P<0Ng*$Aa;)mbaU~AMKUW;;`kkSj`nZk@{a}5l$u4p+~R$iuk$ z`|tX=dOYgmx=+w!9PgDK^ek`Yj7shiAICNNL40i`>RRUKi%eRKub*$mWc9ejd>ti) z2J<+K?|hHL$$lOy#5uPv*!hq++nK(BJ-hN@J+P4{??XHa_9h+`&MWBI`Vr%hi=#y- z#<3nZ>jmTI@#FbuP5p}XCm!i};QgtO)3RO9&oRC+Uif3zx3L}UgzNeF;rvgWLw_^1 zHV|j(*?JV~oql9;ffUHI@uG}_QO4`J#vzn@-0-`m`ot&1&!U;Mv3~5bPQ>+rbt9|` zM~3UL7o6hP>jUwP_Cj3UUR-Y)*jc6a=PU}(-Qv1QKX*#beAoR&D{+}7eto7R*FE#Y zcV{uK;D@lg?eCRSO8jt=zOHN#^9{sTOB7WCAe5p$7*8}!_Iqal*JDEz8(hH6b z`Ov%4_+R+HF()|3tfX-iz^M{Oo>l zeI~0me&M=1#_eRk9t{1|_=W4iXCJ>Z*O3-q#?S6E>+MYm@4d#PVSS44+1IDme%kFc zmdASWxkA)?*!9+>rH`m4>u$;D3?0e0)JXmQ4tuN|*FUEFp8WUktJ2c@>9*?IbA$Di zv$b(wVD|^P`;XZwaJ#zyu;&PV9_(0QtJt&Lf269N4CB7a=IM^A@wyMONYb9=L-ZSe z4v#6&jzYm#adYO)PA2MB_J|EW<=Hrsa^O5U*TgTU{vh1w!>uVg= z#(hXCy1t@gqWchgF5&b1`P_$uc&Aoh_aPzPQ;pYsNQif4yzWCnyhHKde;<+t1BG$; zo9|1wAF=Dj`u)g!k5`x%ZCp=GQA_cDlzCJj5&HTSxppF<$@d$W)vAk@j8h zMVM~rz zKGyGFVtv-vpCTW@dBD~K`fc+x&a)L`C}pF4%PjPo#dn?I*VPqqoNw0|O~zE}*R`#Z zpl9_w59@lXDs_9dUZOWd`b9nLh5MNGejl^O?_*Xh+{YB#UF&-5yxn*o zQ*77uPG1+|iSw2xtgCjN5U=lud#@}qz6(XUFZox|SRU6!>c#t*kE$Gf%S-eh7e6G^ zahLm;4@p40M~f1d5bxrBqxYNZV>>@`-EqI^dz?1kTfeUf*ApJEcz<)*xuLv%ec|?U zD0yV|=d4Y>Am07{+wWt}@cWpGtT28aZ^n7o`}{_&(++Y3q8e9+#M}b_dX49>+La$svG@tLOf z>*HIzk6Eo!#`mbOj>q*bcRy28IrYQ*sEAA2(5nfoI8#UBJimVc^mj-!U|KoZx z=jhuMYq&R_q3-RIc#O>F-;?{k(W%j9=& zrsMOv&#{>t?>87)#Qs^!82-wAb@^_*sGPI@{^0Kqs!Q-|yIY z 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

2Kr)aG)=)0mkrp!=|ri&%`nJGRW`s#k~aT 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

!)fj?=u2ly6X$|(Tf1xy>;0{k_@FU{~0-v!1$ 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 pbflow.Record 0, // 1: pbflow.DupMapEntry.direction:type_name -> pbflow.Direction 0, // 2: pbflow.Record.direction:type_name -> pbflow.Direction - 9, // 3: pbflow.Record.time_flow_start:type_name -> google.protobuf.Timestamp - 9, // 4: pbflow.Record.time_flow_end:type_name -> google.protobuf.Timestamp + 10, // 3: pbflow.Record.time_flow_start:type_name -> google.protobuf.Timestamp + 10, // 4: pbflow.Record.time_flow_end:type_name -> google.protobuf.Timestamp 5, // 5: pbflow.Record.data_link:type_name -> pbflow.DataLink 6, // 6: pbflow.Record.network:type_name -> pbflow.Network 8, // 7: pbflow.Record.transport:type_name -> pbflow.Transport 7, // 8: pbflow.Record.agent_ip:type_name -> pbflow.IP - 10, // 9: pbflow.Record.dns_latency:type_name -> google.protobuf.Duration - 10, // 10: pbflow.Record.time_flow_rtt:type_name -> google.protobuf.Duration + 11, // 9: pbflow.Record.dns_latency:type_name -> google.protobuf.Duration + 11, // 10: pbflow.Record.time_flow_rtt:type_name -> google.protobuf.Duration 3, // 11: pbflow.Record.dup_list:type_name -> pbflow.DupMapEntry - 7, // 12: pbflow.Network.src_addr:type_name -> pbflow.IP - 7, // 13: pbflow.Network.dst_addr:type_name -> pbflow.IP - 2, // 14: pbflow.Collector.Send:input_type -> pbflow.Records - 1, // 15: pbflow.Collector.Send:output_type -> pbflow.CollectorReply - 15, // [15:16] is the sub-list for method output_type - 14, // [14:15] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name + 9, // 12: pbflow.Record.xlat:type_name -> pbflow.Xlat + 7, // 13: pbflow.Network.src_addr:type_name -> pbflow.IP + 7, // 14: pbflow.Network.dst_addr:type_name -> pbflow.IP + 7, // 15: pbflow.Xlat.src_addr:type_name -> pbflow.IP + 7, // 16: pbflow.Xlat.dst_addr:type_name -> pbflow.IP + 2, // 17: pbflow.Collector.Send:input_type -> pbflow.Records + 1, // 18: pbflow.Collector.Send:output_type -> pbflow.CollectorReply + 18, // [18:19] is the sub-list for method output_type + 17, // [17:18] is the sub-list for method input_type + 17, // [17:17] is the sub-list for extension type_name + 17, // [17:17] is the sub-list for extension extendee + 0, // [0:17] is the sub-list for field type_name } func init() { file_proto_flow_proto_init() } @@ -907,7 +1028,7 @@ func file_proto_flow_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_flow_proto_rawDesc, NumEnums: 1, - NumMessages: 8, + NumMessages: 9, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/pbflow/proto.go b/pkg/pbflow/proto.go index 8341a4d7f..0d07309ff 100644 --- a/pkg/pbflow/proto.go +++ b/pkg/pbflow/proto.go @@ -2,6 +2,7 @@ package pbflow import ( "encoding/binary" + "fmt" "net" "github.com/netobserv/netobserv-ebpf-agent/pkg/ebpf" @@ -76,6 +77,12 @@ func FlowToPB(fr *model.Record, s *ovnobserv.SampleDecoder) *Record { DnsFlags: uint32(fr.Metrics.DnsRecord.Flags), DnsErrno: uint32(fr.Metrics.DnsRecord.Errno), TimeFlowRtt: durationpb.New(fr.TimeFlowRtt), + Xlat: &Xlat{ + SrcPort: uint32(fr.Metrics.TranslatedFlow.Sport), + DstPort: uint32(fr.Metrics.TranslatedFlow.Dport), + ZoneId: uint32(fr.Metrics.TranslatedFlow.ZoneId), + IcmpId: uint32(fr.Metrics.TranslatedFlow.IcmpId), + }, } if fr.Metrics.DnsRecord.Latency != 0 { pbflowRecord.DnsLatency = durationpb.New(fr.DNSLatency) @@ -94,9 +101,13 @@ func FlowToPB(fr *model.Record, s *ovnobserv.SampleDecoder) *Record { if fr.Id.EthProtocol == model.IPv6Type { pbflowRecord.Network.SrcAddr = &IP{IpFamily: &IP_Ipv6{Ipv6: fr.Id.SrcIp[:]}} pbflowRecord.Network.DstAddr = &IP{IpFamily: &IP_Ipv6{Ipv6: fr.Id.DstIp[:]}} + pbflowRecord.Xlat.SrcAddr = &IP{IpFamily: &IP_Ipv6{Ipv6: fr.Metrics.TranslatedFlow.Saddr[:]}} + pbflowRecord.Xlat.DstAddr = &IP{IpFamily: &IP_Ipv6{Ipv6: fr.Metrics.TranslatedFlow.Daddr[:]}} } else { pbflowRecord.Network.SrcAddr = &IP{IpFamily: &IP_Ipv4{Ipv4: model.IntEncodeV4(fr.Id.SrcIp)}} pbflowRecord.Network.DstAddr = &IP{IpFamily: &IP_Ipv4{Ipv4: model.IntEncodeV4(fr.Id.DstIp)}} + pbflowRecord.Xlat.SrcAddr = &IP{IpFamily: &IP_Ipv4{Ipv4: model.IntEncodeV4(fr.Metrics.TranslatedFlow.Saddr)}} + pbflowRecord.Xlat.DstAddr = &IP{IpFamily: &IP_Ipv4{Ipv4: model.IntEncodeV4(fr.Metrics.TranslatedFlow.Daddr)}} } if s != nil { seen := make(map[string]bool) @@ -113,6 +124,17 @@ func FlowToPB(fr *model.Record, s *ovnobserv.SampleDecoder) *Record { } } } + zoneIDtoUdnIDMap, err := s.GetConntrackZoneToUDN() + if err != nil { + protoLog.Errorf("unable to get zoneIDtoUdnIdMap: %v", err) + } else { + if udnID, ok := zoneIDtoUdnIDMap[fmt.Sprint(fr.Metrics.TranslatedFlow.ZoneId)]; ok { + pbflowRecord.Xlat.UdnId = udnID + protoLog.Debugf("Packet Xlation zoneID %d mapped to udnID %s", fr.Metrics.TranslatedFlow.ZoneId, udnID) + } else { + protoLog.Errorf("unable to find zoneId %d in ZoneID2UdnID map", fr.Metrics.TranslatedFlow.ZoneId) + } + } } return &pbflowRecord } @@ -154,6 +176,14 @@ func PBToFlow(pb *Record) *model.Record { Errno: uint8(pb.DnsErrno), Latency: uint64(pb.DnsLatency.AsDuration()), }, + TranslatedFlow: ebpf.BpfTranslatedFlowT{ + Saddr: ipToIPAddr(pb.Xlat.GetSrcAddr()), + Daddr: ipToIPAddr(pb.Xlat.GetDstAddr()), + Sport: uint16(pb.Xlat.GetSrcPort()), + Dport: uint16(pb.Xlat.GetDstPort()), + ZoneId: uint16(pb.Xlat.GetZoneId()), + IcmpId: uint8(pb.Xlat.GetIcmpId()), + }, }, }, TimeFlowStart: pb.TimeFlowStart.AsTime(), @@ -176,6 +206,10 @@ func PBToFlow(pb *Record) *model.Record { out.NetworkMonitorEventsMD = append(out.NetworkMonitorEventsMD, pb.GetNetworkEventsMetadata()...) protoLog.Debugf("decoded Network events monitor metadata: %v", out.NetworkMonitorEventsMD) } + + if len(pb.GetXlat().UdnId) != 0 { + out.UdnID = pb.GetXlat().UdnId + } return &out } diff --git a/pkg/tracer/tracer.go b/pkg/tracer/tracer.go index 26dfc4a94..89e34f3f4 100644 --- a/pkg/tracer/tracer.go +++ b/pkg/tracer/tracer.go @@ -43,6 +43,7 @@ const ( constEnableFlowFiltering = "enable_flows_filtering" constEnableNetworkEventsMonitoring = "enable_network_events_monitoring" constNetworkEventsMonitoringGroupID = "network_events_monitoring_groupid" + constEnablePktTransformation = "enable_pkt_transformation_tracking" pktDropHook = "kfree_skb" constPcaEnable = "enable_pca" pcaRecordsMap = "packet_record" @@ -77,6 +78,7 @@ type FlowFetcher struct { egressTCXLink map[ifaces.Interface]link.Link ingressTCXLink map[ifaces.Interface]link.Link networkEventsMonitoringLink link.Link + nfNatManIPLink link.Link lookupAndDeleteSupported bool } @@ -94,6 +96,7 @@ type FlowFetcherConfig struct { NetworkEventsMonitoringGroupID int EnableFlowFilter bool EnablePCA bool + EnablePktTransformation bool FilterConfig *FilterConfig } @@ -148,6 +151,10 @@ func NewFlowFetcher(cfg *FlowFetcherConfig) (*FlowFetcher, error) { networkEventsMonitoringGroupID = cfg.NetworkEventsMonitoringGroupID } + enablePktTransformation := 0 + if cfg.EnablePktTransformation { + enablePktTransformation = 1 + } if err := spec.RewriteConstants(map[string]interface{}{ constSampling: uint32(cfg.Sampling), constTraceMessages: uint8(traceMsgs), @@ -157,6 +164,7 @@ func NewFlowFetcher(cfg *FlowFetcherConfig) (*FlowFetcher, error) { constEnableFlowFiltering: uint8(enableFlowFiltering), constEnableNetworkEventsMonitoring: uint8(enableNetworkEventsMonitoring), constNetworkEventsMonitoringGroupID: uint8(networkEventsMonitoringGroupID), + constEnablePktTransformation: uint8(enablePktTransformation), }); err != nil { return nil, fmt.Errorf("rewriting BPF constants definition: %w", err) } @@ -245,6 +253,14 @@ func NewFlowFetcher(cfg *FlowFetcherConfig) (*FlowFetcher, error) { } } next: + var nfNatManIPLink link.Link + if cfg.EnablePktTransformation { + nfNatManIPLink, err = link.Kprobe("nf_nat_manip_pkt", objects.TrackNatManipPkt, nil) + if err != nil { + log.Warningf("failed to attach the BPF program to nat_manip kprobe: %v", err) + return nil, fmt.Errorf("failed to attach the BPF program to nat_manip kprobe: %w", err) + } + } // read events from igress+egress ringbuffer flows, err := ringbuf.NewReader(objects.DirectFlows) if err != nil { @@ -263,6 +279,7 @@ next: pktDropsTracePoint: pktDropsLink, rttFentryLink: rttFentryLink, rttKprobeLink: rttKprobeLink, + nfNatManIPLink: nfNatManIPLink, egressTCXLink: map[ifaces.Interface]link.Link{}, ingressTCXLink: map[ifaces.Interface]link.Link{}, networkEventsMonitoringLink: networkEventsMonitoringLink, @@ -598,6 +615,11 @@ func (m *FlowFetcher) Close() error { errs = append(errs, err) } } + if m.nfNatManIPLink != nil { + if err := m.nfNatManIPLink.Close(); err != nil { + errs = append(errs, err) + } + } // m.ringbufReader.Read is a blocking operation, so we need to close the ring buffer // from another goroutine to avoid the system not being able to exit if there // isn't traffic in a given interface @@ -855,6 +877,7 @@ func kernelSpecificLoadAndAssign(oldKernel, rtKernel, supportNetworkEvents bool, TcIngressPcaParse *cilium.Program `ebpf:"tc_ingress_pca_parse"` TcxEgressPcaParse *cilium.Program `ebpf:"tcx_egress_pca_parse"` TcxIngressPcaParse *cilium.Program `ebpf:"tcx_ingress_pca_parse"` + TrackNatManipPkt *cilium.Program `ebpf:"track_nat_manip_pkt"` } type newBpfObjects struct { newBpfPrograms @@ -879,6 +902,7 @@ func kernelSpecificLoadAndAssign(oldKernel, rtKernel, supportNetworkEvents bool, TcIngressPcaParse: newObjects.TcIngressPcaParse, TcxEgressPcaParse: newObjects.TcxEgressPcaParse, TcxIngressPcaParse: newObjects.TcxIngressPcaParse, + TrackNatManipPkt: newObjects.TrackNatManipPkt, TcpRcvKprobe: nil, TcpRcvFentry: nil, KfreeSkb: nil, @@ -904,6 +928,7 @@ func kernelSpecificLoadAndAssign(oldKernel, rtKernel, supportNetworkEvents bool, TcxEgressPcaParse *cilium.Program `ebpf:"tcx_egress_pca_parse"` TcxIngressPcaParse *cilium.Program `ebpf:"tcx_ingress_pca_parse"` TCPRcvKprobe *cilium.Program `ebpf:"tcp_rcv_kprobe"` + TrackNatManipPkt *cilium.Program `ebpf:"track_nat_manip_pkt"` } type newBpfObjects struct { newBpfPrograms @@ -928,6 +953,7 @@ func kernelSpecificLoadAndAssign(oldKernel, rtKernel, supportNetworkEvents bool, TcxEgressPcaParse: newObjects.TcxEgressPcaParse, TcxIngressPcaParse: newObjects.TcxIngressPcaParse, TcpRcvKprobe: newObjects.TCPRcvKprobe, + TrackNatManipPkt: newObjects.TrackNatManipPkt, TcpRcvFentry: nil, KfreeSkb: nil, RhNetworkEventsMonitoring: nil, @@ -952,6 +978,7 @@ func kernelSpecificLoadAndAssign(oldKernel, rtKernel, supportNetworkEvents bool, TcxEgressPcaParse *cilium.Program `ebpf:"tcx_egress_pca_parse"` TcxIngressPcaParse *cilium.Program `ebpf:"tcx_ingress_pca_parse"` TCPRcvFentry *cilium.Program `ebpf:"tcp_rcv_fentry"` + TrackNatManipPkt *cilium.Program `ebpf:"track_nat_manip_pkt"` } type newBpfObjects struct { newBpfPrograms @@ -976,6 +1003,7 @@ func kernelSpecificLoadAndAssign(oldKernel, rtKernel, supportNetworkEvents bool, TcxEgressPcaParse: newObjects.TcxEgressPcaParse, TcxIngressPcaParse: newObjects.TcxIngressPcaParse, TcpRcvFentry: newObjects.TCPRcvFentry, + TrackNatManipPkt: newObjects.TrackNatManipPkt, TcpRcvKprobe: nil, KfreeSkb: nil, RhNetworkEventsMonitoring: nil, @@ -1002,6 +1030,7 @@ func kernelSpecificLoadAndAssign(oldKernel, rtKernel, supportNetworkEvents bool, TCPRcvFentry *cilium.Program `ebpf:"tcp_rcv_fentry"` TCPRcvKprobe *cilium.Program `ebpf:"tcp_rcv_kprobe"` KfreeSkb *cilium.Program `ebpf:"kfree_skb"` + TrackNatManipPkt *cilium.Program `ebpf:"track_nat_manip_pkt"` } type newBpfObjects struct { newBpfPrograms @@ -1027,6 +1056,7 @@ func kernelSpecificLoadAndAssign(oldKernel, rtKernel, supportNetworkEvents bool, TcpRcvFentry: newObjects.TCPRcvFentry, TcpRcvKprobe: newObjects.TCPRcvKprobe, KfreeSkb: newObjects.KfreeSkb, + TrackNatManipPkt: newObjects.TrackNatManipPkt, RhNetworkEventsMonitoring: nil, }, BpfMaps: ebpf.BpfMaps{ diff --git a/proto/flow.proto b/proto/flow.proto index 82b192b00..f6f6ed6ba 100644 --- a/proto/flow.proto +++ b/proto/flow.proto @@ -61,6 +61,7 @@ message Record { uint32 dns_errno = 25; repeated DupMapEntry dup_list = 26; repeated string network_events_metadata = 27; + Xlat xlat = 28; } message DataLink { @@ -95,3 +96,13 @@ enum Direction { INGRESS = 0; EGRESS = 1; } + +message Xlat { + IP src_addr = 1; + IP dst_addr = 2; + uint32 src_port = 3; + uint32 dst_port = 4; + uint32 zone_id = 5; + string udn_id = 6; + uint32 icmp_id = 7; +} diff --git a/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go index 4b19188d9..8a290f197 100644 --- a/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go +++ b/vendor/github.com/cpuguy83/go-md2man/v2/md2man/roff.go @@ -1,6 +1,7 @@ package md2man import ( + "bufio" "bytes" "fmt" "io" @@ -21,34 +22,35 @@ type roffRenderer struct { } const ( - titleHeader = ".TH " - topLevelHeader = "\n\n.SH " - secondLevelHdr = "\n.SH " - otherHeader = "\n.SS " - crTag = "\n" - emphTag = "\\fI" - emphCloseTag = "\\fP" - strongTag = "\\fB" - strongCloseTag = "\\fP" - breakTag = "\n.br\n" - paraTag = "\n.PP\n" - hruleTag = "\n.ti 0\n\\l'\\n(.lu'\n" - linkTag = "\n\\[la]" - linkCloseTag = "\\[ra]" - codespanTag = "\\fB" - codespanCloseTag = "\\fR" - codeTag = "\n.EX\n" - codeCloseTag = "\n.EE\n" - quoteTag = "\n.PP\n.RS\n" - quoteCloseTag = "\n.RE\n" - listTag = "\n.RS\n" - listCloseTag = "\n.RE\n" - dtTag = "\n.TP\n" - dd2Tag = "\n" - tableStart = "\n.TS\nallbox;\n" - tableEnd = ".TE\n" - tableCellStart = "T{\n" - tableCellEnd = "\nT}\n" + titleHeader = ".TH " + topLevelHeader = "\n\n.SH " + secondLevelHdr = "\n.SH " + otherHeader = "\n.SS " + crTag = "\n" + emphTag = "\\fI" + emphCloseTag = "\\fP" + strongTag = "\\fB" + strongCloseTag = "\\fP" + breakTag = "\n.br\n" + paraTag = "\n.PP\n" + hruleTag = "\n.ti 0\n\\l'\\n(.lu'\n" + linkTag = "\n\\[la]" + linkCloseTag = "\\[ra]" + codespanTag = "\\fB" + codespanCloseTag = "\\fR" + codeTag = "\n.EX\n" + codeCloseTag = ".EE\n" // Do not prepend a newline character since code blocks, by definition, include a newline already (or at least as how blackfriday gives us on). + quoteTag = "\n.PP\n.RS\n" + quoteCloseTag = "\n.RE\n" + listTag = "\n.RS\n" + listCloseTag = "\n.RE\n" + dtTag = "\n.TP\n" + dd2Tag = "\n" + tableStart = "\n.TS\nallbox;\n" + tableEnd = ".TE\n" + tableCellStart = "T{\n" + tableCellEnd = "\nT}\n" + tablePreprocessor = `'\" t` ) // NewRoffRenderer creates a new blackfriday Renderer for generating roff documents @@ -75,6 +77,16 @@ func (r *roffRenderer) GetExtensions() blackfriday.Extensions { // RenderHeader handles outputting the header at document start func (r *roffRenderer) RenderHeader(w io.Writer, ast *blackfriday.Node) { + // We need to walk the tree to check if there are any tables. + // If there are, we need to enable the roff table preprocessor. + ast.Walk(func(node *blackfriday.Node, entering bool) blackfriday.WalkStatus { + if node.Type == blackfriday.Table { + out(w, tablePreprocessor+"\n") + return blackfriday.Terminate + } + return blackfriday.GoToNext + }) + // disable hyphenation out(w, ".nh\n") } @@ -322,6 +334,28 @@ func out(w io.Writer, output string) { } func escapeSpecialChars(w io.Writer, text []byte) { + scanner := bufio.NewScanner(bytes.NewReader(text)) + + // count the number of lines in the text + // we need to know this to avoid adding a newline after the last line + n := bytes.Count(text, []byte{'\n'}) + idx := 0 + + for scanner.Scan() { + dt := scanner.Bytes() + if idx < n { + idx++ + dt = append(dt, '\n') + } + escapeSpecialCharsLine(w, dt) + } + + if err := scanner.Err(); err != nil { + panic(err) + } +} + +func escapeSpecialCharsLine(w io.Writer, text []byte) { for i := 0; i < len(text); i++ { // escape initial apostrophe or period if len(text) >= 1 && (text[0] == '\'' || text[0] == '.') { diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder/sample_decoder.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder/sample_decoder.go index 0bf419bd5..aac21dfeb 100644 --- a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder/sample_decoder.go +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder/sample_decoder.go @@ -5,6 +5,8 @@ import ( "context" "encoding/binary" "fmt" + "k8s.io/apimachinery/pkg/util/sets" + "strings" "github.com/ovn-org/libovsdb/client" "github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/ovsdb" @@ -288,3 +290,47 @@ func (d *SampleDecoder) DeleteCollector(collectorID int) error { fmt.Println("res: ", res) return err } + +// TODO check start with [prefix]udnName +var ctPrefixes = sets.New("GR_", "breth0_", "cr-rtos-", "etor-GR_", "ext_", "jtor-GR_", "k8s-", "rtoe-GR_", "rtoj-GR_") + +func (d *SampleDecoder) GetConntrackZoneToUDN() (map[string]string, error) { + res := map[string]string{} + bridges := []*ovsdb.Bridge{} + err := d.ovsdbClient.WhereCache(func(item *ovsdb.Bridge) bool { + return item.Name == bridgeName + }).List(context.Background(), &bridges) + if err != nil || len(bridges) != 1 { + return nil, fmt.Errorf("failed finding br-int: %w", err) + } + udns := sets.New[string]() + // node names can only have - or . and alphanumerics + for ctName := range bridges[0].ExternalIDs { + if strings.HasPrefix(ctName, "ct-zone-GR_") && strings.HasSuffix(ctName, "_dnat") { + // remove "ct-zone-GR_" prefix + s := ctName[11 : len(ctName)-5] + // format is [_] + if i := strings.Index(s, "_"); i != -1 { + udns.Insert(s[:i]) + } + } + } + //fmt.Println("udns: ", udns) + + for ctName, ctZone := range bridges[0].ExternalIDs { + if strings.HasPrefix(ctName, "ct-zone-") { + foundUDN := false + for udn := range udns { + if strings.Contains(ctName, udn) { + res[ctZone] = udn + foundUDN = true + break + } + } + if !foundUDN { + res[ctZone] = "default" + } + } + } + return res, nil +} diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config/config.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config/config.go index 6a54509af..3b129624b 100644 --- a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config/config.go +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config/config.go @@ -13,14 +13,14 @@ import ( "strings" "time" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "github.com/urfave/cli/v2" gcfg "gopkg.in/gcfg.v1" lumberjack "gopkg.in/natefinch/lumberjack.v2" + "k8s.io/apimachinery/pkg/api/validation" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" "k8s.io/klog/v2" - kexec "k8s.io/utils/exec" utilnet "k8s.io/utils/net" @@ -60,19 +60,20 @@ var ( // Default holds parsed config file parameters and command-line overrides Default = DefaultConfig{ - MTU: 1400, - ConntrackZone: 64000, - EncapType: "geneve", - EncapIP: "", - EncapPort: DefaultEncapPort, - InactivityProbe: 100000, // in Milliseconds - OpenFlowProbe: 180, // in Seconds - OfctrlWaitBeforeClear: 0, // in Milliseconds - MonitorAll: true, - OVSDBTxnTimeout: DefaultDBTxnTimeout, - LFlowCacheEnable: true, - RawClusterSubnets: "10.128.0.0/14/23", - Zone: types.OvnDefaultZone, + MTU: 1400, + ConntrackZone: 64000, + EncapType: "geneve", + EncapIP: "", + EncapPort: DefaultEncapPort, + InactivityProbe: 100000, // in Milliseconds + OpenFlowProbe: 180, // in Seconds + OfctrlWaitBeforeClear: 0, // in Milliseconds + MonitorAll: true, + OVSDBTxnTimeout: DefaultDBTxnTimeout, + LFlowCacheEnable: true, + RawClusterSubnets: "10.128.0.0/14/23", + Zone: types.OvnDefaultZone, + RawUDNAllowedDefaultServices: "default/kubernetes,kube-system/kube-dns", } // Logging holds logging-related parsed config file parameters and command-line overrides @@ -110,13 +111,14 @@ var ( // Kubernetes holds Kubernetes-related parsed config file parameters and command-line overrides Kubernetes = KubernetesConfig{ - APIServer: DefaultAPIServer, - RawServiceCIDRs: "172.16.1.0/24", - OVNConfigNamespace: "ovn-kubernetes", - HostNetworkNamespace: "", - PlatformType: "", - DNSServiceNamespace: "kube-system", - DNSServiceName: "kube-dns", + APIServer: DefaultAPIServer, + RawServiceCIDRs: "172.16.1.0/24", + OVNConfigNamespace: "ovn-kubernetes", + HostNetworkNamespace: "", + DisableRequestedChassis: false, + PlatformType: "", + DNSServiceNamespace: "kube-system", + DNSServiceName: "kube-dns", // By default, use a short lifetime length for certificates to ensure that the automatic rotation works well, // might revisit in the future to use a more sensible value CertDuration: 10 * time.Minute, @@ -280,6 +282,14 @@ type DefaultConfig struct { // Zone name to which ovnkube-node/ovnkube-controller belongs to Zone string `gcfg:"zone"` + + // RawUDNAllowedDefaultServices holds the unparsed UDNAllowedDefaultServices. Should only be + // used inside config module. + RawUDNAllowedDefaultServices string `gcfg:"udn-allowed-default-services"` + + // UDNAllowedDefaultServices holds a list of namespaced names of + // default cluster network services accessible from primary user-defined networks + UDNAllowedDefaultServices []string } // LoggingConfig holds logging-related parsed config file parameters and command-line overrides @@ -346,26 +356,27 @@ type CNIConfig struct { // KubernetesConfig holds Kubernetes-related parsed config file parameters and command-line overrides type KubernetesConfig struct { - BootstrapKubeconfig string `gcfg:"bootstrap-kubeconfig"` - CertDir string `gcfg:"cert-dir"` - CertDuration time.Duration `gcfg:"cert-duration"` - Kubeconfig string `gcfg:"kubeconfig"` - CACert string `gcfg:"cacert"` - CAData []byte - APIServer string `gcfg:"apiserver"` - Token string `gcfg:"token"` - TokenFile string `gcfg:"tokenFile"` - CompatServiceCIDR string `gcfg:"service-cidr"` - RawServiceCIDRs string `gcfg:"service-cidrs"` - ServiceCIDRs []*net.IPNet - OVNConfigNamespace string `gcfg:"ovn-config-namespace"` - OVNEmptyLbEvents bool `gcfg:"ovn-empty-lb-events"` - PodIP string `gcfg:"pod-ip"` // UNUSED - RawNoHostSubnetNodes string `gcfg:"no-hostsubnet-nodes"` - NoHostSubnetNodes labels.Selector - HostNetworkNamespace string `gcfg:"host-network-namespace"` - PlatformType string `gcfg:"platform-type"` - HealthzBindAddress string `gcfg:"healthz-bind-address"` + BootstrapKubeconfig string `gcfg:"bootstrap-kubeconfig"` + CertDir string `gcfg:"cert-dir"` + CertDuration time.Duration `gcfg:"cert-duration"` + Kubeconfig string `gcfg:"kubeconfig"` + CACert string `gcfg:"cacert"` + CAData []byte + APIServer string `gcfg:"apiserver"` + Token string `gcfg:"token"` + TokenFile string `gcfg:"tokenFile"` + CompatServiceCIDR string `gcfg:"service-cidr"` + RawServiceCIDRs string `gcfg:"service-cidrs"` + ServiceCIDRs []*net.IPNet + OVNConfigNamespace string `gcfg:"ovn-config-namespace"` + OVNEmptyLbEvents bool `gcfg:"ovn-empty-lb-events"` + PodIP string `gcfg:"pod-ip"` // UNUSED + RawNoHostSubnetNodes string `gcfg:"no-hostsubnet-nodes"` + NoHostSubnetNodes labels.Selector + HostNetworkNamespace string `gcfg:"host-network-namespace"` + DisableRequestedChassis bool `gcfg:"disable-requestedchassis"` + PlatformType string `gcfg:"platform-type"` + HealthzBindAddress string `gcfg:"healthz-bind-address"` // CompatMetricsBindAddress is overridden by the corresponding option in MetricsConfig CompatMetricsBindAddress string `gcfg:"metrics-bind-address"` @@ -636,6 +647,7 @@ func PrepareTestConfig() error { HybridOverlay = savedHybridOverlay OvnKubeNode = savedOvnKubeNode ClusterManager = savedClusterManager + Kubernetes.DisableRequestedChassis = false EnableMulticast = false Default.OVSDBTxnTimeout = 5 * time.Second @@ -921,6 +933,14 @@ var CommonFlags = []cli.Flag{ Value: Default.Zone, Destination: &cliConfig.Default.Zone, }, + &cli.StringFlag{ + Name: "udn-allowed-default-services", + Usage: "a list of namespaced names of default cluster network services accessible from primary" + + "user-defined networks. If not specified defaults to [\"default/kubernetes\", \"kube-system/kube-dns\"]." + + "Only used when enable-network-segmentation is set", + Value: Default.RawUDNAllowedDefaultServices, + Destination: &cliConfig.Default.RawUDNAllowedDefaultServices, + }, } // MonitoringFlags capture monitoring-related options @@ -1184,6 +1204,12 @@ var K8sFlags = []cli.Flag{ Destination: &cliConfig.Kubernetes.HostNetworkNamespace, Value: Kubernetes.HostNetworkNamespace, }, + &cli.BoolFlag{ + Name: "disable-requestedchassis", + Usage: "If set to true, requested-chassis option will not be set during pod creation", + Destination: &cliConfig.Kubernetes.DisableRequestedChassis, + Value: Kubernetes.DisableRequestedChassis, + }, &cli.StringFlag{ Name: "platform-type", Usage: "The cloud provider platform type ovn-kubernetes is deployed on. " + @@ -1759,7 +1785,7 @@ func buildKubernetesConfig(exec kexec.Interface, cli, file *config, saPath strin // completeKubernetesConfig completes the Kubernetes config by parsing raw values // into their final form. -func completeKubernetesConfig(allSubnets *configSubnets) error { +func completeKubernetesConfig(allSubnets *ConfigSubnets) error { Kubernetes.ServiceCIDRs = []*net.IPNet{} for _, cidrString := range strings.Split(Kubernetes.RawServiceCIDRs, ",") { _, serviceCIDR, err := net.ParseCIDR(cidrString) @@ -1767,7 +1793,7 @@ func completeKubernetesConfig(allSubnets *configSubnets) error { return fmt.Errorf("kubernetes service network CIDR %q invalid: %v", cidrString, err) } Kubernetes.ServiceCIDRs = append(Kubernetes.ServiceCIDRs, serviceCIDR) - allSubnets.append(configSubnetService, serviceCIDR) + allSubnets.Append(ConfigSubnetService, serviceCIDR) } if len(Kubernetes.ServiceCIDRs) > 2 { return fmt.Errorf("kubernetes service-cidrs must contain either a single CIDR or else an IPv4/IPv6 pair") @@ -1865,7 +1891,7 @@ func buildGatewayConfig(ctx *cli.Context, cli, file *config) error { return nil } -func completeGatewayConfig(allSubnets *configSubnets, masqueradeIPs *MasqueradeIPsConfig) error { +func completeGatewayConfig(allSubnets *ConfigSubnets, masqueradeIPs *MasqueradeIPsConfig) error { // Validate v4 and v6 join subnets v4IP, v4JoinCIDR, err := net.ParseCIDR(Gateway.V4JoinSubnet) if err != nil || utilnet.IsIPv6(v4IP) { @@ -1876,8 +1902,8 @@ func completeGatewayConfig(allSubnets *configSubnets, masqueradeIPs *MasqueradeI if err != nil || !utilnet.IsIPv6(v6IP) { return fmt.Errorf("invalid gateway v6 join subnet specified, subnet: %s: error: %v", Gateway.V6JoinSubnet, err) } - allSubnets.append(configSubnetJoin, v4JoinCIDR) - allSubnets.append(configSubnetJoin, v6JoinCIDR) + allSubnets.Append(ConfigSubnetJoin, v4JoinCIDR) + allSubnets.Append(ConfigSubnetJoin, v6JoinCIDR) //validate v4 and v6 masquerade subnets v4MasqueradeIP, v4MasqueradeCIDR, err := net.ParseCIDR(Gateway.V4MasqueradeSubnet) @@ -1896,8 +1922,8 @@ func completeGatewayConfig(allSubnets *configSubnets, masqueradeIPs *MasqueradeI return fmt.Errorf("unable to allocate V6MasqueradeIPs: %s", err) } - allSubnets.append(configSubnetMasquerade, v4MasqueradeCIDR) - allSubnets.append(configSubnetMasquerade, v6MasqueradeCIDR) + allSubnets.Append(ConfigSubnetMasquerade, v4MasqueradeCIDR) + allSubnets.Append(ConfigSubnetMasquerade, v6MasqueradeCIDR) return nil } @@ -2027,7 +2053,7 @@ func buildHybridOverlayConfig(ctx *cli.Context, cli, file *config) error { // completeHybridOverlayConfig completes the HybridOverlay config by parsing raw values // into their final form. -func completeHybridOverlayConfig(allSubnets *configSubnets) error { +func completeHybridOverlayConfig(allSubnets *ConfigSubnets) error { if !HybridOverlay.Enabled || len(HybridOverlay.RawClusterSubnets) == 0 { return nil } @@ -2038,7 +2064,7 @@ func completeHybridOverlayConfig(allSubnets *configSubnets) error { return fmt.Errorf("hybrid overlay cluster subnet invalid: %v", err) } for _, subnet := range HybridOverlay.ClusterSubnets { - allSubnets.append(configSubnetHybrid, subnet.CIDR) + allSubnets.Append(ConfigSubnetHybrid, subnet.CIDR) } return nil @@ -2060,7 +2086,7 @@ func buildClusterManagerConfig(ctx *cli.Context, cli, file *config) error { // completeClusterManagerConfig completes the ClusterManager config by parsing raw values // into their final form. -func completeClusterManagerConfig(allSubnets *configSubnets) error { +func completeClusterManagerConfig(allSubnets *ConfigSubnets) error { // Validate v4 and v6 transit switch subnets v4IP, v4TransitCIDR, err := net.ParseCIDR(ClusterManager.V4TransitSwitchSubnet) if err != nil || utilnet.IsIPv6(v4IP) { @@ -2071,8 +2097,8 @@ func completeClusterManagerConfig(allSubnets *configSubnets) error { if err != nil || !utilnet.IsIPv6(v6IP) { return fmt.Errorf("invalid transit switch v6 subnet specified, subnet: %s: error: %v", ClusterManager.V6TransitSwitchSubnet, err) } - allSubnets.append(configSubnetTransit, v4TransitCIDR) - allSubnets.append(configSubnetTransit, v6TransitCIDR) + allSubnets.Append(ConfigSubnetTransit, v4TransitCIDR) + allSubnets.Append(ConfigSubnetTransit, v6TransitCIDR) return nil } @@ -2101,14 +2127,19 @@ func buildDefaultConfig(cli, file *config) error { // completeDefaultConfig completes the Default config by parsing raw values // into their final form. -func completeDefaultConfig(allSubnets *configSubnets) error { +func completeDefaultConfig(allSubnets *ConfigSubnets) error { var err error Default.ClusterSubnets, err = ParseClusterSubnetEntries(Default.RawClusterSubnets) if err != nil { return fmt.Errorf("cluster subnet invalid: %v", err) } for _, subnet := range Default.ClusterSubnets { - allSubnets.append(configSubnetCluster, subnet.CIDR) + allSubnets.Append(ConfigSubnetCluster, subnet.CIDR) + } + + Default.UDNAllowedDefaultServices, err = parseServicesNamespacedNames(Default.RawUDNAllowedDefaultServices) + if err != nil { + return fmt.Errorf("UDN allowed services field is invalid: %v", err) } Default.HostMasqConntrackZone = Default.ConntrackZone + 1 @@ -2118,6 +2149,27 @@ func completeDefaultConfig(allSubnets *configSubnets) error { return nil } +// parseServicesNamespacedNames splits the input string by `,` and returns a slice +// of keys that were verified to be a valid namespaced service name. It ignores spaces between the elements. +func parseServicesNamespacedNames(servicesRaw string) ([]string, error) { + var services []string + for _, udnEnabledSVC := range strings.Split(servicesRaw, ",") { + svcKey := strings.TrimSpace(udnEnabledSVC) + namespace, name, err := cache.SplitMetaNamespaceKey(strings.TrimSpace(svcKey)) + if namespace == "" { + return nil, fmt.Errorf("UDN enabled service %q no namespace set: %v", svcKey, err) + } + if errs := validation.ValidateNamespaceName(namespace, false); len(errs) != 0 { + return nil, fmt.Errorf("UDN enabled service %q has an invalid namespace: %v", svcKey, err) + } + if errs := validation.NameIsDNSSubdomain(name, false); len(errs) != 0 { + return nil, fmt.Errorf("UDN enabled service %q has an invalid name: %v", svcKey, err) + } + services = append(services, svcKey) + } + return services, nil +} + // getConfigFilePath returns config file path and 'true' if the config file is // the fallback path (eg not given by the user), 'false' if given explicitly // by the user @@ -2333,7 +2385,7 @@ func initConfigWithPath(ctx *cli.Context, exec kexec.Interface, saPath string, d } func completeConfig() error { - allSubnets := newConfigSubnets() + allSubnets := NewConfigSubnets() if err := completeKubernetesConfig(allSubnets); err != nil { return err @@ -2356,7 +2408,7 @@ func completeConfig() error { return err } - if err := allSubnets.checkForOverlaps(); err != nil { + if err := allSubnets.CheckForOverlaps(); err != nil { return err } diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config/utils.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config/utils.go index 17cdb3027..b27be4d7c 100644 --- a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config/utils.go +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config/utils.go @@ -162,67 +162,69 @@ func ParseFlowCollectors(flowCollectors string) ([]HostPort, error) { return parsedFlowsCollectors, nil } -type configSubnetType string +type ConfigSubnetType string const ( - configSubnetJoin configSubnetType = "built-in join subnet" - configSubnetCluster configSubnetType = "cluster subnet" - configSubnetService configSubnetType = "service subnet" - configSubnetHybrid configSubnetType = "hybrid overlay subnet" - configSubnetMasquerade configSubnetType = "masquerade subnet" - configSubnetTransit configSubnetType = "transit switch subnet" + ConfigSubnetJoin ConfigSubnetType = "built-in join subnet" + ConfigSubnetCluster ConfigSubnetType = "cluster subnet" + ConfigSubnetService ConfigSubnetType = "service subnet" + ConfigSubnetHybrid ConfigSubnetType = "hybrid overlay subnet" + ConfigSubnetMasquerade ConfigSubnetType = "masquerade subnet" + ConfigSubnetTransit ConfigSubnetType = "transit switch subnet" + UserDefinedSubnets ConfigSubnetType = "user defined subnet" + UserDefinedJoinSubnet ConfigSubnetType = "user defined join subnet" ) -type configSubnet struct { - subnetType configSubnetType - subnet *net.IPNet +type ConfigSubnet struct { + SubnetType ConfigSubnetType + Subnet *net.IPNet } -// configSubnets represents a set of configured subnets (and their names) -type configSubnets struct { - subnets []configSubnet - v4 map[configSubnetType]bool - v6 map[configSubnetType]bool +// ConfigSubnets represents a set of configured subnets (and their names) +type ConfigSubnets struct { + Subnets []ConfigSubnet + V4 map[ConfigSubnetType]bool + V6 map[ConfigSubnetType]bool } -// newConfigSubnets returns a new configSubnets -func newConfigSubnets() *configSubnets { - return &configSubnets{ - v4: make(map[configSubnetType]bool), - v6: make(map[configSubnetType]bool), +// NewConfigSubnets returns a new ConfigSubnets +func NewConfigSubnets() *ConfigSubnets { + return &ConfigSubnets{ + V4: make(map[ConfigSubnetType]bool), + V6: make(map[ConfigSubnetType]bool), } } // append adds a single subnet to cs -func (cs *configSubnets) append(subnetType configSubnetType, subnet *net.IPNet) { - cs.subnets = append(cs.subnets, configSubnet{subnetType: subnetType, subnet: subnet}) - if subnetType != configSubnetJoin && subnetType != configSubnetMasquerade && subnetType != configSubnetTransit { +func (cs *ConfigSubnets) Append(subnetType ConfigSubnetType, subnet *net.IPNet) { + cs.Subnets = append(cs.Subnets, ConfigSubnet{SubnetType: subnetType, Subnet: subnet}) + if subnetType == ConfigSubnetCluster || subnetType == ConfigSubnetService || subnetType == ConfigSubnetHybrid { if utilnet.IsIPv6CIDR(subnet) { - cs.v6[subnetType] = true + cs.V6[subnetType] = true } else { - cs.v4[subnetType] = true + cs.V4[subnetType] = true } } } -// checkForOverlaps checks if any of the subnets in cs overlap -func (cs *configSubnets) checkForOverlaps() error { - for i, si := range cs.subnets { +// CheckForOverlaps checks if any of the subnets in cs overlap +func (cs *ConfigSubnets) CheckForOverlaps() error { + for i, si := range cs.Subnets { for j := 0; j < i; j++ { - sj := cs.subnets[j] - if si.subnet.Contains(sj.subnet.IP) || sj.subnet.Contains(si.subnet.IP) { + sj := cs.Subnets[j] + if si.Subnet.Contains(sj.Subnet.IP) || sj.Subnet.Contains(si.Subnet.IP) { return fmt.Errorf("illegal network configuration: %s %q overlaps %s %q", - si.subnetType, si.subnet.String(), - sj.subnetType, sj.subnet.String()) + si.SubnetType, si.Subnet.String(), + sj.SubnetType, sj.Subnet.String()) } } } return nil } -func (cs *configSubnets) describeSubnetType(subnetType configSubnetType) string { - ipv4 := cs.v4[subnetType] - ipv6 := cs.v6[subnetType] +func (cs *ConfigSubnets) describeSubnetType(subnetType ConfigSubnetType) string { + ipv4 := cs.V4[subnetType] + ipv6 := cs.V6[subnetType] var familyType string switch { case ipv4 && !ipv6: @@ -240,45 +242,27 @@ func (cs *configSubnets) describeSubnetType(subnetType configSubnetType) string // checkIPFamilies determines if cs contains a valid single-stack IPv4 configuration, a // valid single-stack IPv6 configuration, a valid dual-stack configuration, or none of the // above. -func (cs *configSubnets) checkIPFamilies() (usingIPv4, usingIPv6 bool, err error) { - if len(cs.v6) == 0 { +func (cs *ConfigSubnets) checkIPFamilies() (usingIPv4, usingIPv6 bool, err error) { + if len(cs.V6) == 0 { // Single-stack IPv4 return true, false, nil - } else if len(cs.v4) == 0 { + } else if len(cs.V4) == 0 { // Single-stack IPv6 return false, true, nil - } else if reflect.DeepEqual(cs.v4, cs.v6) { + } else if reflect.DeepEqual(cs.V4, cs.V6) { // Dual-stack return true, true, nil } - netConfig := cs.describeSubnetType(configSubnetCluster) - netConfig += ", " + cs.describeSubnetType(configSubnetService) - if cs.v4[configSubnetHybrid] || cs.v6[configSubnetHybrid] { - netConfig += ", " + cs.describeSubnetType(configSubnetHybrid) + netConfig := cs.describeSubnetType(ConfigSubnetCluster) + netConfig += ", " + cs.describeSubnetType(ConfigSubnetService) + if cs.V4[ConfigSubnetHybrid] || cs.V6[ConfigSubnetHybrid] { + netConfig += ", " + cs.describeSubnetType(ConfigSubnetHybrid) } return false, false, fmt.Errorf("illegal network configuration: %s", netConfig) } -func ContainsJoinIP(ip net.IP) bool { - var joinSubnetsConfig []string - if IPv4Mode { - joinSubnetsConfig = append(joinSubnetsConfig, Gateway.V4JoinSubnet) - } - if IPv6Mode { - joinSubnetsConfig = append(joinSubnetsConfig, Gateway.V6JoinSubnet) - } - - for _, subnet := range joinSubnetsConfig { - _, joinSubnet, _ := net.ParseCIDR(subnet) - if joinSubnet.Contains(ip) { - return true - } - } - return false -} - // masqueradeIP represents the masqueradeIPs used by the masquerade subnets for host to service traffic type MasqueradeIPsConfig struct { V4OVNMasqueradeIP net.IP diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/router.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/router.go index 0eb8499ab..9aeb42123 100644 --- a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/router.go +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/router.go @@ -8,9 +8,10 @@ import ( libovsdbclient "github.com/ovn-org/libovsdb/client" libovsdb "github.com/ovn-org/libovsdb/ovsdb" + "k8s.io/apimachinery/pkg/util/sets" + "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/config" "github.com/ovn-org/ovn-kubernetes/go-controller/pkg/nbdb" - "k8s.io/apimachinery/pkg/util/sets" ) // ROUTER OPs @@ -644,7 +645,7 @@ func CreateOrReplaceLogicalRouterStaticRouteWithPredicate(nbClient libovsdbclien lr := &nbdb.LogicalRouter{Name: routerName} router, err := GetLogicalRouter(nbClient, lr) if err != nil { - return err + return fmt.Errorf("unable to get logical router %s: %w", routerName, err) } newPredicate := func(item *nbdb.LogicalRouterStaticRoute) bool { for _, routeUUID := range router.StaticRoutes { @@ -656,7 +657,7 @@ func CreateOrReplaceLogicalRouterStaticRouteWithPredicate(nbClient libovsdbclien } routes, err := FindLogicalRouterStaticRoutesWithPredicate(nbClient, newPredicate) if err != nil { - return err + return fmt.Errorf("unable to get logical router static routes with predicate on router %s: %w", routerName, err) } var ops []libovsdb.Operation @@ -697,7 +698,7 @@ func CreateOrReplaceLogicalRouterStaticRouteWithPredicate(nbClient libovsdbclien ops, err = CreateOrUpdateLogicalRouterStaticRoutesWithPredicateOps(nbClient, ops, routerName, lrsr, nil, fields...) if err != nil { - return err + return fmt.Errorf("unable to get create or update logical router static routes on router %s: %w", routerName, err) } _, err = TransactAndCheck(nbClient, ops) return err @@ -886,6 +887,7 @@ func buildNAT( logicalPort string, externalMac string, externalIDs map[string]string, + match string, ) *nbdb.NAT { nat := &nbdb.NAT{ Type: natType, @@ -893,6 +895,7 @@ func buildNAT( LogicalIP: logicalIP, Options: map[string]string{"stateless": "false"}, ExternalIDs: externalIDs, + Match: match, } if logicalPort != "" { @@ -912,6 +915,16 @@ func BuildSNAT( logicalIP *net.IPNet, logicalPort string, externalIDs map[string]string, +) *nbdb.NAT { + return BuildSNATWithMatch(externalIP, logicalIP, logicalPort, externalIDs, "") +} + +func BuildSNATWithMatch( + externalIP *net.IP, + logicalIP *net.IPNet, + logicalPort string, + externalIDs map[string]string, + match string, ) *nbdb.NAT { externalIPStr := "" if externalIP != nil { @@ -923,7 +936,7 @@ func BuildSNAT( if logicalIPMask != 32 && logicalIPMask != 128 { logicalIPStr = logicalIP.String() } - return buildNAT(nbdb.NATTypeSNAT, externalIPStr, logicalIPStr, logicalPort, "", externalIDs) + return buildNAT(nbdb.NATTypeSNAT, externalIPStr, logicalIPStr, logicalPort, "", externalIDs, match) } // BuildDNATAndSNAT builds a logical router DNAT/SNAT @@ -933,6 +946,17 @@ func BuildDNATAndSNAT( logicalPort string, externalMac string, externalIDs map[string]string, +) *nbdb.NAT { + return BuildDNATAndSNATWithMatch(externalIP, logicalIP, logicalPort, externalMac, externalIDs, "") +} + +func BuildDNATAndSNATWithMatch( + externalIP *net.IP, + logicalIP *net.IPNet, + logicalPort string, + externalMac string, + externalIDs map[string]string, + match string, ) *nbdb.NAT { externalIPStr := "" if externalIP != nil { @@ -948,13 +972,18 @@ func BuildDNATAndSNAT( logicalIPStr, logicalPort, externalMac, - externalIDs) + externalIDs, + match) } -// isEquivalentNAT if it has same uuid. Otherwise, check if types match. -// ExternalIP must be unique amonst non-SNATs; -// LogicalIP must be unique amonst SNATs; -// If provided, LogicalPort is expected to match; +// isEquivalentNAT checks if the `searched` NAT is equivalent to `existing`. +// Returns true if the UUID is set in `searched` and matches the UUID of `existing`. +// Otherwise, perform the following checks: +// - Compare the Type and Match fields. +// - Compare ExternalIP if it is set in `searched`. +// - Compare LogicalIP if the Type in `searched` is SNAT. +// - Compare LogicalPort if it is set in `searched`. +// - Ensure that all ExternalIDs of `searched` exist and have the same value in `existing`. func isEquivalentNAT(existing *nbdb.NAT, searched *nbdb.NAT) bool { // Simple case: uuid was provided. if searched.UUID != "" && existing.UUID == searched.UUID { @@ -965,6 +994,10 @@ func isEquivalentNAT(existing *nbdb.NAT, searched *nbdb.NAT) bool { return false } + if searched.Match != existing.Match { + return false + } + // Compre externalIP if its not empty. if searched.ExternalIP != "" && searched.ExternalIP != existing.ExternalIP { return false diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/switch.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/switch.go index fbee34b55..964e711bb 100644 --- a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/switch.go +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/libovsdb/ops/switch.go @@ -312,6 +312,9 @@ func createOrUpdateLogicalSwitchPortsOps(nbClient libovsdbclient.Client, ops []l m := newModelClient(nbClient) ops, err := m.CreateOrUpdateOps(ops, opModels...) sw.Ports = originalPorts + if err != nil && errors.Is(err, libovsdbclient.ErrNotFound) && !createSwitch { + err = fmt.Errorf("could not find switch: %q, %w", sw.Name, err) + } return ops, err } diff --git a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types/const.go b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types/const.go index 7b021716e..1b2499ea5 100644 --- a/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types/const.go +++ b/vendor/github.com/ovn-org/ovn-kubernetes/go-controller/pkg/types/const.go @@ -108,6 +108,7 @@ const ( MGMTPortPolicyPriority = "1005" NodeSubnetPolicyPriority = "1004" InterNodePolicyPriority = "1003" + UDNHostCIDRPolicyPriority = "99" HybridOverlaySubnetPriority = 1002 HybridOverlayReroutePriority = 501 DefaultNoRereoutePriority = 102 @@ -196,6 +197,8 @@ const ( LoadBalancerKindExternalID = OvnK8sPrefix + "/" + "kind" // key for load_balancer service external-id LoadBalancerOwnerExternalID = OvnK8sPrefix + "/" + "owner" + // key for UDN enabled services routes + UDNEnabledServiceExternalID = OvnK8sPrefix + "/" + "udn-enabled-default-service" // different secondary network topology type defined in CNI netconf Layer3Topology = "layer3" diff --git a/vendor/github.com/urfave/cli/v2/.gitignore b/vendor/github.com/urfave/cli/v2/.gitignore index 2d5e149b4..1ef91a60b 100644 --- a/vendor/github.com/urfave/cli/v2/.gitignore +++ b/vendor/github.com/urfave/cli/v2/.gitignore @@ -1,7 +1,14 @@ *.coverprofile +*.exe *.orig -node_modules/ -vendor +.*envrc +.envrc .idea -internal/*/built-example +# goimports is installed here if not available +/.local/ +/site/ coverage.txt +internal/*/built-example +vendor +/cmd/urfave-cli-genflags/urfave-cli-genflags +*.exe diff --git a/vendor/github.com/urfave/cli/v2/.golangci.yaml b/vendor/github.com/urfave/cli/v2/.golangci.yaml new file mode 100644 index 000000000..89b6e8661 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/.golangci.yaml @@ -0,0 +1,4 @@ +# https://golangci-lint.run/usage/configuration/ +linters: + enable: + - misspell diff --git a/vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md b/vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md index 41ba294f6..9fee14807 100644 --- a/vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md +++ b/vendor/github.com/urfave/cli/v2/CODE_OF_CONDUCT.md @@ -55,11 +55,12 @@ further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting Dan Buch at dan@meatballhat.com. All complaints will be -reviewed and investigated and will result in a response that is deemed necessary -and appropriate to the circumstances. The project team is obligated to maintain -confidentiality with regard to the reporter of an incident. Further details of -specific enforcement policies may be posted separately. +reported by contacting urfave-governance@googlegroups.com, a members-only group +that is world-postable. All complaints will be reviewed and investigated and +will result in a response that is deemed necessary and appropriate to the +circumstances. The project team is obligated to maintain confidentiality with +regard to the reporter of an incident. Further details of specific enforcement +policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other diff --git a/vendor/github.com/urfave/cli/v2/LICENSE b/vendor/github.com/urfave/cli/v2/LICENSE index 42a597e29..2c84c78a1 100644 --- a/vendor/github.com/urfave/cli/v2/LICENSE +++ b/vendor/github.com/urfave/cli/v2/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016 Jeremy Saenz & Contributors +Copyright (c) 2022 urfave/cli maintainers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/github.com/urfave/cli/v2/Makefile b/vendor/github.com/urfave/cli/v2/Makefile new file mode 100644 index 000000000..f0d41905e --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/Makefile @@ -0,0 +1,26 @@ +# NOTE: this Makefile is meant to provide a simplified entry point for humans to +# run all of the critical steps to verify one's changes are harmonious in +# nature. Keeping target bodies to one line each and abstaining from make magic +# are very important so that maintainers and contributors can focus their +# attention on files that are primarily Go. + +GO_RUN_BUILD := go run internal/build/build.go + +.PHONY: all +all: generate vet test check-binary-size gfmrun yamlfmt v2diff + +# NOTE: this is a special catch-all rule to run any of the commands +# defined in internal/build/build.go with optional arguments passed +# via GFLAGS (global flags) and FLAGS (command-specific flags), e.g.: +# +# $ make test GFLAGS='--packages cli' +%: + $(GO_RUN_BUILD) $(GFLAGS) $* $(FLAGS) + +.PHONY: docs +docs: + mkdocs build + +.PHONY: serve-docs +serve-docs: + mkdocs serve diff --git a/vendor/github.com/urfave/cli/v2/README.md b/vendor/github.com/urfave/cli/v2/README.md index c9237fbc6..9080aee41 100644 --- a/vendor/github.com/urfave/cli/v2/README.md +++ b/vendor/github.com/urfave/cli/v2/README.md @@ -1,66 +1,19 @@ -cli -=== +# cli -[![GoDoc](https://godoc.org/github.com/urfave/cli?status.svg)](https://godoc.org/github.com/urfave/cli) -[![codebeat](https://codebeat.co/badges/0a8f30aa-f975-404b-b878-5fab3ae1cc5f)](https://codebeat.co/projects/github-com-urfave-cli) -[![Go Report Card](https://goreportcard.com/badge/urfave/cli)](https://goreportcard.com/report/urfave/cli) -[![codecov](https://codecov.io/gh/urfave/cli/branch/master/graph/badge.svg)](https://codecov.io/gh/urfave/cli) +[![Run Tests](https://github.com/urfave/cli/actions/workflows/cli.yml/badge.svg?branch=v2-maint)](https://github.com/urfave/cli/actions/workflows/cli.yml) +[![Go Reference](https://pkg.go.dev/badge/github.com/urfave/cli/v2.svg)](https://pkg.go.dev/github.com/urfave/cli/v2) +[![Go Report Card](https://goreportcard.com/badge/github.com/urfave/cli/v2)](https://goreportcard.com/report/github.com/urfave/cli/v2) +[![codecov](https://codecov.io/gh/urfave/cli/branch/v2-maint/graph/badge.svg?token=t9YGWLh05g)](https://app.codecov.io/gh/urfave/cli/tree/v2-maint) cli is a simple, fast, and fun package for building command line apps in Go. The goal is to enable developers to write fast and distributable command line applications in an expressive way. -## Usage Documentation +## Documentation -Usage documentation exists for each major version. Don't know what version you're on? You're probably using the version from the `master` branch, which is currently `v2`. +More documentation is available in [`./docs`](./docs) or the hosted +documentation site at . -- `v2` - [./docs/v2/manual.md](./docs/v2/manual.md) -- `v1` - [./docs/v1/manual.md](./docs/v1/manual.md) +## License -## Installation - -Make sure you have a working Go environment. Go version 1.11+ is supported. [See the install instructions for Go](http://golang.org/doc/install.html). - -Go Modules are strongly recommended when using this package. [See the go blog guide on using Go Modules](https://blog.golang.org/using-go-modules). - -### Using `v2` releases - -``` -$ GO111MODULE=on go get github.com/urfave/cli/v2 -``` - -```go -... -import ( - "github.com/urfave/cli/v2" // imports as package "cli" -) -... -``` - -### Using `v1` releases - -``` -$ GO111MODULE=on go get github.com/urfave/cli -``` - -```go -... -import ( - "github.com/urfave/cli" -) -... -``` - -### GOPATH - -Make sure your `PATH` includes the `$GOPATH/bin` directory so your commands can -be easily used: -``` -export PATH=$PATH:$GOPATH/bin -``` - -### Supported platforms - -cli is tested against multiple versions of Go on Linux, and against the latest -released version of Go on OS X and Windows. This project uses Github Actions for -builds. For more build info, please look at the [./.github/workflows/cli.yml](https://github.com/urfave/cli/blob/master/.github/workflows/cli.yml). +See [`LICENSE`](./LICENSE) diff --git a/vendor/github.com/urfave/cli/v2/app.go b/vendor/github.com/urfave/cli/v2/app.go index d0c8f84e2..af072e769 100644 --- a/vendor/github.com/urfave/cli/v2/app.go +++ b/vendor/github.com/urfave/cli/v2/app.go @@ -8,16 +8,24 @@ import ( "os" "path/filepath" "sort" + "strings" "time" ) +const suggestDidYouMeanTemplate = "Did you mean %q?" + var ( - changeLogURL = "https://github.com/urfave/cli/blob/master/docs/CHANGELOG.md" + changeLogURL = "https://github.com/urfave/cli/blob/main/docs/CHANGELOG.md" appActionDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-action-signature", changeLogURL) contactSysadmin = "This is an error in the application. Please contact the distributor of this application if this is not you." errInvalidActionType = NewExitError("ERROR invalid Action type. "+ fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+ fmt.Sprintf("See %s", appActionDeprecationURL), 2) + ignoreFlagPrefix = "test." // this is to ignore test flags when adding flags from other packages + + SuggestFlag SuggestFlagFunc = nil // initialized in suggestions.go unless built with urfave_cli_no_suggest + SuggestCommand SuggestCommandFunc = nil // initialized in suggestions.go unless built with urfave_cli_no_suggest + SuggestDidYouMeanTemplate string = suggestDidYouMeanTemplate ) // App is the main structure of a cli application. It is recommended that @@ -31,12 +39,17 @@ type App struct { Usage string // Text to override the USAGE section of help UsageText string + // Whether this command supports arguments + Args bool // Description of the program argument format. ArgsUsage string // Version of the program Version string // Description of the program Description string + // DefaultCommand is the (optional) name of a command + // to run if no command names are passed as CLI arguments. + DefaultCommand string // List of commands to execute Commands []*Command // List of flags to parse @@ -52,6 +65,8 @@ type App struct { HideVersion bool // categories contains the categorized commands and is populated on app startup categories CommandCategories + // flagCategories contains the categorized flags and is populated on app startup + flagCategories FlagCategories // An action to execute when the shell completion flag is set BashComplete BashCompleteFunc // An action to execute before any subcommands are run, but after the context is ready @@ -64,20 +79,25 @@ type App struct { Action ActionFunc // Execute this function if the proper command cannot be found CommandNotFound CommandNotFoundFunc - // Execute this function if an usage error occurs + // Execute this function if a usage error occurs OnUsageError OnUsageErrorFunc + // Execute this function when an invalid flag is accessed from the context + InvalidFlagAccessHandler InvalidFlagAccessFunc // Compilation date Compiled time.Time // List of all authors who contributed Authors []*Author // Copyright of the binary if any Copyright string + // Reader reader to write input to (useful for tests) + Reader io.Reader // Writer writer to write output to Writer io.Writer // ErrWriter writes error output ErrWriter io.Writer - // Execute this function to handle ExitErrors. If not provided, HandleExitCoder is provided to - // function as a default, so this is optional. + // ExitErrHandler processes any error encountered while running an App before + // it is returned to the caller. If no function is provided, HandleExitCoder + // is used as the default behavior. ExitErrHandler ExitErrHandlerFunc // Other custom info Metadata map[string]interface{} @@ -87,14 +107,32 @@ type App struct { // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. CustomAppHelpTemplate string + // SliceFlagSeparator is used to customize the separator for SliceFlag, the default is "," + SliceFlagSeparator string + // DisableSliceFlagSeparator is used to disable SliceFlagSeparator, the default is false + DisableSliceFlagSeparator bool // Boolean to enable short-option handling so user can combine several // single-character bool arguments into one // i.e. foobar -o -v -> foobar -ov UseShortOptionHandling bool - - didSetup bool + // Enable suggestions for commands and flags + Suggest bool + // Allows global flags set by libraries which use flag.XXXVar(...) directly + // to be parsed through this library + AllowExtFlags bool + // Treat all flags as normal arguments if true + SkipFlagParsing bool + + didSetup bool + separator separatorSpec + + rootCommand *Command } +type SuggestFlagFunc func(flags []Flag, provided string, hideHelp bool) string + +type SuggestCommandFunc func(commands []*Command, provided string) string + // Tries to find out when this binary was compiled. // Returns the current time if it fails to find it. func compileTime() time.Time { @@ -110,13 +148,14 @@ func compileTime() time.Time { func NewApp() *App { return &App{ Name: filepath.Base(os.Args[0]), - HelpName: filepath.Base(os.Args[0]), Usage: "A new cli application", UsageText: "", BashComplete: DefaultAppComplete, Action: helpCommand.Action, Compiled: compileTime(), + Reader: os.Stdin, Writer: os.Stdout, + ErrWriter: os.Stderr, } } @@ -135,7 +174,7 @@ func (a *App) Setup() { } if a.HelpName == "" { - a.HelpName = filepath.Base(os.Args[0]) + a.HelpName = a.Name } if a.Usage == "" { @@ -158,19 +197,47 @@ func (a *App) Setup() { a.Compiled = compileTime() } + if a.Reader == nil { + a.Reader = os.Stdin + } + if a.Writer == nil { a.Writer = os.Stdout } - var newCommands []*Command + if a.ErrWriter == nil { + a.ErrWriter = os.Stderr + } + + if a.AllowExtFlags { + // add global flags added by other packages + flag.VisitAll(func(f *flag.Flag) { + // skip test flags + if !strings.HasPrefix(f.Name, ignoreFlagPrefix) { + a.Flags = append(a.Flags, &extFlag{f}) + } + }) + } + + if len(a.SliceFlagSeparator) != 0 { + a.separator.customized = true + a.separator.sep = a.SliceFlagSeparator + } + + if a.DisableSliceFlagSeparator { + a.separator.customized = true + a.separator.disabled = true + } for _, c := range a.Commands { - if c.HelpName == "" { - c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) + cname := c.Name + if c.HelpName != "" { + cname = c.HelpName } - newCommands = append(newCommands, c) + c.separator = a.separator + c.HelpName = fmt.Sprintf("%s %s", a.HelpName, cname) + c.flagCategories = newFlagCategoriesFromFlags(c.Flags) } - a.Commands = newCommands if a.Command(helpCommand.Name) == nil && !a.HideHelp { if !a.HideHelpCommand { @@ -192,17 +259,42 @@ func (a *App) Setup() { } sort.Sort(a.categories.(*commandCategories)) + a.flagCategories = newFlagCategoriesFromFlags(a.Flags) + if a.Metadata == nil { a.Metadata = make(map[string]interface{}) } +} - if a.Writer == nil { - a.Writer = os.Stdout +func (a *App) newRootCommand() *Command { + return &Command{ + Name: a.Name, + Usage: a.Usage, + UsageText: a.UsageText, + Description: a.Description, + ArgsUsage: a.ArgsUsage, + BashComplete: a.BashComplete, + Before: a.Before, + After: a.After, + Action: a.Action, + OnUsageError: a.OnUsageError, + Subcommands: a.Commands, + Flags: a.Flags, + flagCategories: a.flagCategories, + HideHelp: a.HideHelp, + HideHelpCommand: a.HideHelpCommand, + UseShortOptionHandling: a.UseShortOptionHandling, + HelpName: a.HelpName, + CustomHelpTemplate: a.CustomAppHelpTemplate, + categories: a.categories, + SkipFlagParsing: a.SkipFlagParsing, + isRoot: true, + separator: a.separator, } } func (a *App) newFlagSet() (*flag.FlagSet, error) { - return flagSet(a.Name, a.Flags) + return flagSet(a.Name, a.Flags, a.separator) } func (a *App) useShortOptionHandling() bool { @@ -229,212 +321,72 @@ func (a *App) RunContext(ctx context.Context, arguments []string) (err error) { // always appends the completion flag at the end of the command shellComplete, arguments := checkShellCompleteFlag(a, arguments) - set, err := a.newFlagSet() - if err != nil { - return err - } + cCtx := NewContext(a, nil, &Context{Context: ctx}) + cCtx.shellComplete = shellComplete - err = parseIter(set, a, arguments[1:], shellComplete) - nerr := normalizeFlags(a.Flags, set) - context := NewContext(a, set, &Context{Context: ctx}) - if nerr != nil { - _, _ = fmt.Fprintln(a.Writer, nerr) - _ = ShowAppHelp(context) - return nerr - } - context.shellComplete = shellComplete - - if checkCompletions(context) { - return nil - } + a.rootCommand = a.newRootCommand() + cCtx.Command = a.rootCommand - if err != nil { - if a.OnUsageError != nil { - err := a.OnUsageError(context, err, false) - a.handleExitCoder(context, err) - return err - } - _, _ = fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) - _ = ShowAppHelp(context) + if err := checkDuplicatedCmds(a.rootCommand); err != nil { return err } + return a.rootCommand.Run(cCtx, arguments...) +} - if !a.HideHelp && checkHelp(context) { - _ = ShowAppHelp(context) - return nil - } +// RunAsSubcommand is for legacy/compatibility purposes only. New code should only +// use App.RunContext. This function is slated to be removed in v3. +func (a *App) RunAsSubcommand(ctx *Context) (err error) { + a.Setup() - if !a.HideVersion && checkVersion(context) { - ShowVersion(context) - return nil - } + cCtx := NewContext(a, nil, ctx) + cCtx.shellComplete = ctx.shellComplete - cerr := checkRequiredFlags(a.Flags, context) - if cerr != nil { - _ = ShowAppHelp(context) - return cerr - } + a.rootCommand = a.newRootCommand() + cCtx.Command = a.rootCommand - if a.After != nil { - defer func() { - if afterErr := a.After(context); afterErr != nil { - if err != nil { - err = newMultiError(err, afterErr) - } else { - err = afterErr - } - } - }() - } + return a.rootCommand.Run(cCtx, ctx.Args().Slice()...) +} - if a.Before != nil { - beforeErr := a.Before(context) - if beforeErr != nil { - _, _ = fmt.Fprintf(a.Writer, "%v\n\n", beforeErr) - _ = ShowAppHelp(context) - a.handleExitCoder(context, beforeErr) - err = beforeErr - return err - } +func (a *App) suggestFlagFromError(err error, command string) (string, error) { + flag, parseErr := flagFromError(err) + if parseErr != nil { + return "", err } - args := context.Args() - if args.Present() { - name := args.First() - c := a.Command(name) - if c != nil { - return c.Run(context) + flags := a.Flags + hideHelp := a.HideHelp + if command != "" { + cmd := a.Command(command) + if cmd == nil { + return "", err } + flags = cmd.Flags + hideHelp = hideHelp || cmd.HideHelp } - if a.Action == nil { - a.Action = helpCommand.Action + if SuggestFlag == nil { + return "", err + } + suggestion := SuggestFlag(flags, flag, hideHelp) + if len(suggestion) == 0 { + return "", err } - // Run default Action - err = a.Action(context) - - a.handleExitCoder(context, err) - return err + return fmt.Sprintf(SuggestDidYouMeanTemplate+"\n\n", suggestion), nil } // RunAndExitOnError calls .Run() and exits non-zero if an error was returned // // Deprecated: instead you should return an error that fulfills cli.ExitCoder -// to cli.App.Run. This will cause the application to exit with the given eror +// to cli.App.Run. This will cause the application to exit with the given error // code in the cli.ExitCoder func (a *App) RunAndExitOnError() { if err := a.Run(os.Args); err != nil { - _, _ = fmt.Fprintln(a.errWriter(), err) + _, _ = fmt.Fprintln(a.ErrWriter, err) OsExiter(1) } } -// RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to -// generate command-specific flags -func (a *App) RunAsSubcommand(ctx *Context) (err error) { - // Setup also handles HideHelp and HideHelpCommand - a.Setup() - - var newCmds []*Command - for _, c := range a.Commands { - if c.HelpName == "" { - c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) - } - newCmds = append(newCmds, c) - } - a.Commands = newCmds - - set, err := a.newFlagSet() - if err != nil { - return err - } - - err = parseIter(set, a, ctx.Args().Tail(), ctx.shellComplete) - nerr := normalizeFlags(a.Flags, set) - context := NewContext(a, set, ctx) - - if nerr != nil { - _, _ = fmt.Fprintln(a.Writer, nerr) - _, _ = fmt.Fprintln(a.Writer) - if len(a.Commands) > 0 { - _ = ShowSubcommandHelp(context) - } else { - _ = ShowCommandHelp(ctx, context.Args().First()) - } - return nerr - } - - if checkCompletions(context) { - return nil - } - - if err != nil { - if a.OnUsageError != nil { - err = a.OnUsageError(context, err, true) - a.handleExitCoder(context, err) - return err - } - _, _ = fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) - _ = ShowSubcommandHelp(context) - return err - } - - if len(a.Commands) > 0 { - if checkSubcommandHelp(context) { - return nil - } - } else { - if checkCommandHelp(ctx, context.Args().First()) { - return nil - } - } - - cerr := checkRequiredFlags(a.Flags, context) - if cerr != nil { - _ = ShowSubcommandHelp(context) - return cerr - } - - if a.After != nil { - defer func() { - afterErr := a.After(context) - if afterErr != nil { - a.handleExitCoder(context, err) - if err != nil { - err = newMultiError(err, afterErr) - } else { - err = afterErr - } - } - }() - } - - if a.Before != nil { - beforeErr := a.Before(context) - if beforeErr != nil { - a.handleExitCoder(context, beforeErr) - err = beforeErr - return err - } - } - - args := context.Args() - if args.Present() { - name := args.First() - c := a.Command(name) - if c != nil { - return c.Run(context) - } - } - - // Run default Action - err = a.Action(context) - - a.handleExitCoder(context, err) - return err -} - // Command returns the named command on App. Returns nil if the command does not exist func (a *App) Command(name string) *Command { for _, c := range a.Commands { @@ -474,20 +426,19 @@ func (a *App) VisibleCommands() []*Command { return ret } +// VisibleFlagCategories returns a slice containing all the categories with the flags they contain +func (a *App) VisibleFlagCategories() []VisibleFlagCategory { + if a.flagCategories == nil { + return []VisibleFlagCategory{} + } + return a.flagCategories.VisibleCategories() +} + // VisibleFlags returns a slice of the Flags with Hidden=false func (a *App) VisibleFlags() []Flag { return visibleFlags(a.Flags) } -func (a *App) errWriter() io.Writer { - // When the app ErrWriter is nil use the package level one. - if a.ErrWriter == nil { - return ErrWriter - } - - return a.ErrWriter -} - func (a *App) appendFlag(fl Flag) { if !hasFlag(a.Flags, fl) { a.Flags = append(a.Flags, fl) @@ -500,14 +451,45 @@ func (a *App) appendCommand(c *Command) { } } -func (a *App) handleExitCoder(context *Context, err error) { +func (a *App) handleExitCoder(cCtx *Context, err error) { if a.ExitErrHandler != nil { - a.ExitErrHandler(context, err) + a.ExitErrHandler(cCtx, err) } else { HandleExitCoder(err) } } +func (a *App) argsWithDefaultCommand(oldArgs Args) Args { + if a.DefaultCommand != "" { + rawArgs := append([]string{a.DefaultCommand}, oldArgs.Slice()...) + newArgs := args(rawArgs) + + return &newArgs + } + + return oldArgs +} + +func runFlagActions(c *Context, fs []Flag) error { + for _, f := range fs { + isSet := false + for _, name := range f.Names() { + if c.IsSet(name) { + isSet = true + break + } + } + if isSet { + if af, ok := f.(ActionableFlag); ok { + if err := af.RunAction(c); err != nil { + return err + } + } + } + } + return nil +} + // Author represents someone who has contributed to a cli project. type Author struct { Name string // The Authors name @@ -527,16 +509,28 @@ func (a *Author) String() string { // HandleAction attempts to figure out which Action signature was used. If // it's an ActionFunc or a func with the legacy signature for Action, the func // is run! -func HandleAction(action interface{}, context *Context) (err error) { +func HandleAction(action interface{}, cCtx *Context) (err error) { switch a := action.(type) { case ActionFunc: - return a(context) + return a(cCtx) case func(*Context) error: - return a(context) + return a(cCtx) case func(*Context): // deprecated function signature - a(context) + a(cCtx) return nil } return errInvalidActionType } + +func checkStringSliceIncludes(want string, sSlice []string) bool { + found := false + for _, s := range sSlice { + if want == s { + found = true + break + } + } + + return found +} diff --git a/vendor/github.com/urfave/cli/v2/category.go b/vendor/github.com/urfave/cli/v2/category.go index 867e3908c..0986fffca 100644 --- a/vendor/github.com/urfave/cli/v2/category.go +++ b/vendor/github.com/urfave/cli/v2/category.go @@ -1,10 +1,12 @@ package cli +import "sort" + // CommandCategories interface allows for category manipulation type CommandCategories interface { // AddCommand adds a command to a category, creating a new category if necessary. AddCommand(category string, command *Command) - // categories returns a copy of the category slice + // Categories returns a slice of categories sorted by name Categories() []CommandCategory } @@ -77,3 +79,108 @@ func (c *commandCategory) VisibleCommands() []*Command { } return ret } + +// FlagCategories interface allows for category manipulation +type FlagCategories interface { + // AddFlags adds a flag to a category, creating a new category if necessary. + AddFlag(category string, fl Flag) + // VisibleCategories returns a slice of visible flag categories sorted by name + VisibleCategories() []VisibleFlagCategory +} + +type defaultFlagCategories struct { + m map[string]*defaultVisibleFlagCategory +} + +func newFlagCategories() FlagCategories { + return &defaultFlagCategories{ + m: map[string]*defaultVisibleFlagCategory{}, + } +} + +func newFlagCategoriesFromFlags(fs []Flag) FlagCategories { + fc := newFlagCategories() + + var categorized bool + for _, fl := range fs { + if cf, ok := fl.(CategorizableFlag); ok { + if cat := cf.GetCategory(); cat != "" && cf.IsVisible() { + fc.AddFlag(cat, cf) + categorized = true + } + } + } + + if categorized { + for _, fl := range fs { + if cf, ok := fl.(CategorizableFlag); ok { + if cf.GetCategory() == "" && cf.IsVisible() { + fc.AddFlag("", fl) + } + } + } + } + + return fc +} + +func (f *defaultFlagCategories) AddFlag(category string, fl Flag) { + if _, ok := f.m[category]; !ok { + f.m[category] = &defaultVisibleFlagCategory{name: category, m: map[string]Flag{}} + } + + f.m[category].m[fl.String()] = fl +} + +func (f *defaultFlagCategories) VisibleCategories() []VisibleFlagCategory { + catNames := []string{} + for name := range f.m { + catNames = append(catNames, name) + } + + sort.Strings(catNames) + + ret := make([]VisibleFlagCategory, len(catNames)) + for i, name := range catNames { + ret[i] = f.m[name] + } + + return ret +} + +// VisibleFlagCategory is a category containing flags. +type VisibleFlagCategory interface { + // Name returns the category name string + Name() string + // Flags returns a slice of VisibleFlag sorted by name + Flags() []VisibleFlag +} + +type defaultVisibleFlagCategory struct { + name string + m map[string]Flag +} + +func (fc *defaultVisibleFlagCategory) Name() string { + return fc.name +} + +func (fc *defaultVisibleFlagCategory) Flags() []VisibleFlag { + vfNames := []string{} + for flName, fl := range fc.m { + if vf, ok := fl.(VisibleFlag); ok { + if vf.IsVisible() { + vfNames = append(vfNames, flName) + } + } + } + + sort.Strings(vfNames) + + ret := make([]VisibleFlag, len(vfNames)) + for i, flName := range vfNames { + ret[i] = fc.m[flName].(VisibleFlag) + } + + return ret +} diff --git a/vendor/github.com/urfave/cli/v2/cli.go b/vendor/github.com/urfave/cli/v2/cli.go index 62a5bc22d..28ad0582b 100644 --- a/vendor/github.com/urfave/cli/v2/cli.go +++ b/vendor/github.com/urfave/cli/v2/cli.go @@ -1,23 +1,25 @@ // Package cli provides a minimal framework for creating and organizing command line // Go applications. cli is designed to be easy to understand and write, the most simple // cli application can be written as follows: -// func main() { -// (&cli.App{}).Run(os.Args) -// } +// +// func main() { +// (&cli.App{}).Run(os.Args) +// } // // Of course this application does not do much, so let's make this an actual application: -// func main() { -// app := &cli.App{ -// Name: "greet", -// Usage: "say a greeting", -// Action: func(c *cli.Context) error { -// fmt.Println("Greetings") -// return nil -// }, -// } // -// app.Run(os.Args) -// } +// func main() { +// app := &cli.App{ +// Name: "greet", +// Usage: "say a greeting", +// Action: func(c *cli.Context) error { +// fmt.Println("Greetings") +// return nil +// }, +// } +// +// app.Run(os.Args) +// } package cli -//go:generate go run flag-gen/main.go flag-gen/assets_vfsdata.go +//go:generate make -C cmd/urfave-cli-genflags run diff --git a/vendor/github.com/urfave/cli/v2/command.go b/vendor/github.com/urfave/cli/v2/command.go index 95840f32e..472c1ff44 100644 --- a/vendor/github.com/urfave/cli/v2/command.go +++ b/vendor/github.com/urfave/cli/v2/command.go @@ -3,6 +3,7 @@ package cli import ( "flag" "fmt" + "reflect" "sort" "strings" ) @@ -19,6 +20,8 @@ type Command struct { UsageText string // A longer explanation of how the command works Description string + // Whether this command supports arguments + Args bool // A short description of the arguments of this command ArgsUsage string // The category the command is part of @@ -38,7 +41,8 @@ type Command struct { // List of child commands Subcommands []*Command // List of flags to parse - Flags []Flag + Flags []Flag + flagCategories FlagCategories // Treat all flags as normal arguments if true SkipFlagParsing bool // Boolean to hide built-in help command and help flag @@ -61,6 +65,14 @@ type Command struct { // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. CustomHelpTemplate string + + // categories contains the categorized commands and is populated on app startup + categories CommandCategories + + // if this is a root "special" command + isRoot bool + + separator separatorSpec } type Commands []*Command @@ -88,10 +100,21 @@ func (c *Command) FullName() string { return strings.Join(c.commandNamePath, " ") } -// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags -func (c *Command) Run(ctx *Context) (err error) { - if len(c.Subcommands) > 0 { - return c.startApp(ctx) +func (cmd *Command) Command(name string) *Command { + for _, c := range cmd.Subcommands { + if c.HasName(name) { + return c + } + } + + return nil +} + +func (c *Command) setup(ctx *Context) { + if c.Command(helpCommand.Name) == nil && !c.HideHelp { + if !c.HideHelpCommand { + c.Subcommands = append(c.Subcommands, helpCommand) + } } if !c.HideHelp && HelpFlag != nil { @@ -103,41 +126,77 @@ func (c *Command) Run(ctx *Context) (err error) { c.UseShortOptionHandling = true } - set, err := c.parseFlags(ctx.Args(), ctx.shellComplete) + c.categories = newCommandCategories() + for _, command := range c.Subcommands { + c.categories.AddCommand(command.Category, command) + } + sort.Sort(c.categories.(*commandCategories)) - context := NewContext(ctx.App, set, ctx) - context.Command = c - if checkCommandCompletions(context, c.Name) { + for _, scmd := range c.Subcommands { + if scmd.HelpName == "" { + scmd.HelpName = fmt.Sprintf("%s %s", c.HelpName, scmd.Name) + } + scmd.separator = c.separator + } + + if c.BashComplete == nil { + c.BashComplete = DefaultCompleteWithFlags(c) + } +} + +func (c *Command) Run(cCtx *Context, arguments ...string) (err error) { + + if !c.isRoot { + c.setup(cCtx) + if err := checkDuplicatedCmds(c); err != nil { + return err + } + } + + a := args(arguments) + set, err := c.parseFlags(&a, cCtx.shellComplete) + cCtx.flagSet = set + + if checkCompletions(cCtx) { return nil } if err != nil { if c.OnUsageError != nil { - err = c.OnUsageError(context, err, false) - context.App.handleExitCoder(context, err) + err = c.OnUsageError(cCtx, err, !c.isRoot) + cCtx.App.handleExitCoder(cCtx, err) return err } - _, _ = fmt.Fprintln(context.App.Writer, "Incorrect Usage:", err.Error()) - _, _ = fmt.Fprintln(context.App.Writer) - _ = ShowCommandHelp(context, c.Name) + _, _ = fmt.Fprintf(cCtx.App.Writer, "%s %s\n\n", "Incorrect Usage:", err.Error()) + if cCtx.App.Suggest { + if suggestion, err := c.suggestFlagFromError(err, ""); err == nil { + fmt.Fprintf(cCtx.App.Writer, "%s", suggestion) + } + } + if !c.HideHelp { + if c.isRoot { + _ = ShowAppHelp(cCtx) + } else { + _ = ShowCommandHelp(cCtx.parentContext, c.Name) + } + } return err } - if checkCommandHelp(context, c.Name) { - return nil + if checkHelp(cCtx) { + return helpCommand.Action(cCtx) } - cerr := checkRequiredFlags(c.Flags, context) - if cerr != nil { - _ = ShowCommandHelp(context, c.Name) - return cerr + if c.isRoot && !cCtx.App.HideVersion && checkVersion(cCtx) { + ShowVersion(cCtx) + return nil } - if c.After != nil { + if c.After != nil && !cCtx.shellComplete { defer func() { - afterErr := c.After(context) + afterErr := c.After(cCtx) if afterErr != nil { - context.App.handleExitCoder(context, err) + cCtx.App.handleExitCoder(cCtx, err) if err != nil { err = newMultiError(err, afterErr) } else { @@ -147,36 +206,112 @@ func (c *Command) Run(ctx *Context) (err error) { }() } - if c.Before != nil { - err = c.Before(context) - if err != nil { - _ = ShowCommandHelp(context, c.Name) - context.App.handleExitCoder(context, err) + cerr := cCtx.checkRequiredFlags(c.Flags) + if cerr != nil { + _ = helpCommand.Action(cCtx) + return cerr + } + + if c.Before != nil && !cCtx.shellComplete { + beforeErr := c.Before(cCtx) + if beforeErr != nil { + cCtx.App.handleExitCoder(cCtx, beforeErr) + err = beforeErr return err } } - if c.Action == nil { - c.Action = helpSubcommand.Action + if err = runFlagActions(cCtx, c.Flags); err != nil { + return err } - context.Command = c - err = c.Action(context) + var cmd *Command + args := cCtx.Args() + if args.Present() { + name := args.First() + cmd = c.Command(name) + if cmd == nil { + hasDefault := cCtx.App.DefaultCommand != "" + isFlagName := checkStringSliceIncludes(name, cCtx.FlagNames()) + + var ( + isDefaultSubcommand = false + defaultHasSubcommands = false + ) + + if hasDefault { + dc := cCtx.App.Command(cCtx.App.DefaultCommand) + defaultHasSubcommands = len(dc.Subcommands) > 0 + for _, dcSub := range dc.Subcommands { + if checkStringSliceIncludes(name, dcSub.Names()) { + isDefaultSubcommand = true + break + } + } + } - if err != nil { - context.App.handleExitCoder(context, err) + if isFlagName || (hasDefault && (defaultHasSubcommands && isDefaultSubcommand)) { + argsWithDefault := cCtx.App.argsWithDefaultCommand(args) + if !reflect.DeepEqual(args, argsWithDefault) { + cmd = cCtx.App.rootCommand.Command(argsWithDefault.First()) + } + } + } + } else if c.isRoot && cCtx.App.DefaultCommand != "" { + if dc := cCtx.App.Command(cCtx.App.DefaultCommand); dc != c { + cmd = dc + } } + + if cmd != nil { + newcCtx := NewContext(cCtx.App, nil, cCtx) + newcCtx.Command = cmd + return cmd.Run(newcCtx, cCtx.Args().Slice()...) + } + + if c.Action == nil { + c.Action = helpCommand.Action + } + + err = c.Action(cCtx) + + cCtx.App.handleExitCoder(cCtx, err) return err } func (c *Command) newFlagSet() (*flag.FlagSet, error) { - return flagSet(c.Name, c.Flags) + return flagSet(c.Name, c.Flags, c.separator) } func (c *Command) useShortOptionHandling() bool { return c.UseShortOptionHandling } +func (c *Command) suggestFlagFromError(err error, command string) (string, error) { + flag, parseErr := flagFromError(err) + if parseErr != nil { + return "", err + } + + flags := c.Flags + hideHelp := c.HideHelp + if command != "" { + cmd := c.Command(command) + if cmd == nil { + return "", err + } + flags = cmd.Flags + hideHelp = hideHelp || cmd.HideHelp + } + + suggestion := SuggestFlag(flags, flag, hideHelp) + if len(suggestion) == 0 { + return "", err + } + + return fmt.Sprintf(SuggestDidYouMeanTemplate, suggestion) + "\n\n", nil +} + func (c *Command) parseFlags(args Args, shellComplete bool) (*flag.FlagSet, error) { set, err := c.newFlagSet() if err != nil { @@ -215,68 +350,40 @@ func (c *Command) HasName(name string) bool { return false } -func (c *Command) startApp(ctx *Context) error { - app := &App{ - Metadata: ctx.App.Metadata, - Name: fmt.Sprintf("%s %s", ctx.App.Name, c.Name), - } - - if c.HelpName == "" { - app.HelpName = c.HelpName - } else { - app.HelpName = app.Name +// VisibleCategories returns a slice of categories and commands that are +// Hidden=false +func (c *Command) VisibleCategories() []CommandCategory { + ret := []CommandCategory{} + for _, category := range c.categories.Categories() { + if visible := func() CommandCategory { + if len(category.VisibleCommands()) > 0 { + return category + } + return nil + }(); visible != nil { + ret = append(ret, visible) + } } + return ret +} - app.Usage = c.Usage - app.Description = c.Description - app.ArgsUsage = c.ArgsUsage - - // set CommandNotFound - app.CommandNotFound = ctx.App.CommandNotFound - app.CustomAppHelpTemplate = c.CustomHelpTemplate - - // set the flags and commands - app.Commands = c.Subcommands - app.Flags = c.Flags - app.HideHelp = c.HideHelp - app.HideHelpCommand = c.HideHelpCommand - - app.Version = ctx.App.Version - app.HideVersion = ctx.App.HideVersion - app.Compiled = ctx.App.Compiled - app.Writer = ctx.App.Writer - app.ErrWriter = ctx.App.ErrWriter - app.ExitErrHandler = ctx.App.ExitErrHandler - app.UseShortOptionHandling = ctx.App.UseShortOptionHandling - - app.categories = newCommandCategories() +// VisibleCommands returns a slice of the Commands with Hidden=false +func (c *Command) VisibleCommands() []*Command { + var ret []*Command for _, command := range c.Subcommands { - app.categories.AddCommand(command.Category, command) - } - - sort.Sort(app.categories.(*commandCategories)) - - // bash completion - app.EnableBashCompletion = ctx.App.EnableBashCompletion - if c.BashComplete != nil { - app.BashComplete = c.BashComplete - } - - // set the actions - app.Before = c.Before - app.After = c.After - if c.Action != nil { - app.Action = c.Action - } else { - app.Action = helpSubcommand.Action + if !command.Hidden { + ret = append(ret, command) + } } - app.OnUsageError = c.OnUsageError + return ret +} - for index, cc := range app.Commands { - app.Commands[index].commandNamePath = []string{c.Name, cc.Name} +// VisibleFlagCategories returns a slice containing all the visible flag categories with the flags they contain +func (c *Command) VisibleFlagCategories() []VisibleFlagCategory { + if c.flagCategories == nil { + c.flagCategories = newFlagCategoriesFromFlags(c.Flags) } - - return app.RunAsSubcommand(ctx) + return c.flagCategories.VisibleCategories() } // VisibleFlags returns a slice of the Flags with Hidden=false @@ -299,3 +406,16 @@ func hasCommand(commands []*Command, command *Command) bool { return false } + +func checkDuplicatedCmds(parent *Command) error { + seen := make(map[string]struct{}) + for _, c := range parent.Subcommands { + for _, name := range c.Names() { + if _, exists := seen[name]; exists { + return fmt.Errorf("parent command [%s] has duplicated subcommand name or alias: %s", parent.Name, name) + } + seen[name] = struct{}{} + } + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/context.go b/vendor/github.com/urfave/cli/v2/context.go index 74ed51912..8dd476521 100644 --- a/vendor/github.com/urfave/cli/v2/context.go +++ b/vendor/github.com/urfave/cli/v2/context.go @@ -2,7 +2,6 @@ package cli import ( "context" - "errors" "flag" "fmt" "strings" @@ -42,88 +41,140 @@ func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context { } // NumFlags returns the number of flags set -func (c *Context) NumFlags() int { - return c.flagSet.NFlag() +func (cCtx *Context) NumFlags() int { + return cCtx.flagSet.NFlag() } // Set sets a context flag to a value. -func (c *Context) Set(name, value string) error { - return c.flagSet.Set(name, value) +func (cCtx *Context) Set(name, value string) error { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return fs.Set(name, value) + } + + return fmt.Errorf("no such flag -%s", name) } // IsSet determines if the flag was actually set -func (c *Context) IsSet(name string) bool { - if fs := lookupFlagSet(name, c); fs != nil { - if fs := lookupFlagSet(name, c); fs != nil { - isSet := false - fs.Visit(func(f *flag.Flag) { - if f.Name == name { - isSet = true - } - }) - if isSet { - return true +func (cCtx *Context) IsSet(name string) bool { + + if fs := cCtx.lookupFlagSet(name); fs != nil { + isSet := false + fs.Visit(func(f *flag.Flag) { + if f.Name == name { + isSet = true } + }) + if isSet { + return true } - f := lookupFlag(name, c) + f := cCtx.lookupFlag(name) if f == nil { return false } - return f.IsSet() + if f.IsSet() { + return true + } + + // now redo flagset search on aliases + aliases := f.Names() + fs.Visit(func(f *flag.Flag) { + for _, alias := range aliases { + if f.Name == alias { + isSet = true + } + } + }) + + if isSet { + return true + } } return false } // LocalFlagNames returns a slice of flag names used in this context. -func (c *Context) LocalFlagNames() []string { +func (cCtx *Context) LocalFlagNames() []string { var names []string - c.flagSet.Visit(makeFlagNameVisitor(&names)) - return names + cCtx.flagSet.Visit(makeFlagNameVisitor(&names)) + // Check the flags which have been set via env or file + if cCtx.Command != nil && cCtx.Command.Flags != nil { + for _, f := range cCtx.Command.Flags { + if f.IsSet() { + names = append(names, f.Names()...) + } + } + } + + // Sort out the duplicates since flag could be set via multiple + // paths + m := map[string]struct{}{} + var unames []string + for _, name := range names { + if _, ok := m[name]; !ok { + m[name] = struct{}{} + unames = append(unames, name) + } + } + + return unames } // FlagNames returns a slice of flag names used by the this context and all of // its parent contexts. -func (c *Context) FlagNames() []string { +func (cCtx *Context) FlagNames() []string { var names []string - for _, ctx := range c.Lineage() { - ctx.flagSet.Visit(makeFlagNameVisitor(&names)) + for _, pCtx := range cCtx.Lineage() { + names = append(names, pCtx.LocalFlagNames()...) } return names } // Lineage returns *this* context and all of its ancestor contexts in order from // child to parent -func (c *Context) Lineage() []*Context { +func (cCtx *Context) Lineage() []*Context { var lineage []*Context - for cur := c; cur != nil; cur = cur.parentContext { + for cur := cCtx; cur != nil; cur = cur.parentContext { lineage = append(lineage, cur) } return lineage } +// Count returns the num of occurrences of this flag +func (cCtx *Context) Count(name string) int { + if fs := cCtx.lookupFlagSet(name); fs != nil { + if cf, ok := fs.Lookup(name).Value.(Countable); ok { + return cf.Count() + } + } + return 0 +} + // Value returns the value of the flag corresponding to `name` -func (c *Context) Value(name string) interface{} { - return c.flagSet.Lookup(name).Value.(flag.Getter).Get() +func (cCtx *Context) Value(name string) interface{} { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return fs.Lookup(name).Value.(flag.Getter).Get() + } + return nil } // Args returns the command line arguments associated with the context. -func (c *Context) Args() Args { - ret := args(c.flagSet.Args()) +func (cCtx *Context) Args() Args { + ret := args(cCtx.flagSet.Args()) return &ret } // NArg returns the number of the command line arguments. -func (c *Context) NArg() int { - return c.Args().Len() +func (cCtx *Context) NArg() int { + return cCtx.Args().Len() } -func lookupFlag(name string, ctx *Context) Flag { - for _, c := range ctx.Lineage() { +func (cCtx *Context) lookupFlag(name string) Flag { + for _, c := range cCtx.Lineage() { if c.Command == nil { continue } @@ -137,8 +188,8 @@ func lookupFlag(name string, ctx *Context) Flag { } } - if ctx.App != nil { - for _, f := range ctx.App.Flags { + if cCtx.App != nil { + for _, f := range cCtx.App.Flags { for _, n := range f.Names() { if n == name { return f @@ -150,58 +201,58 @@ func lookupFlag(name string, ctx *Context) Flag { return nil } -func lookupFlagSet(name string, ctx *Context) *flag.FlagSet { - for _, c := range ctx.Lineage() { +func (cCtx *Context) lookupFlagSet(name string) *flag.FlagSet { + for _, c := range cCtx.Lineage() { + if c.flagSet == nil { + continue + } if f := c.flagSet.Lookup(name); f != nil { return c.flagSet } } - + cCtx.onInvalidFlag(name) return nil } -func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) { - switch ff.Value.(type) { - case Serializer: - _ = set.Set(name, ff.Value.(Serializer).Serialize()) - default: - _ = set.Set(name, ff.Value.String()) - } -} - -func normalizeFlags(flags []Flag, set *flag.FlagSet) error { - visited := make(map[string]bool) - set.Visit(func(f *flag.Flag) { - visited[f.Name] = true - }) +func (cCtx *Context) checkRequiredFlags(flags []Flag) requiredFlagsErr { + var missingFlags []string for _, f := range flags { - parts := f.Names() - if len(parts) == 1 { - continue - } - var ff *flag.Flag - for _, name := range parts { - name = strings.Trim(name, " ") - if visited[name] { - if ff != nil { - return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name) + if rf, ok := f.(RequiredFlag); ok && rf.IsRequired() { + var flagPresent bool + var flagName string + + flagNames := f.Names() + flagName = flagNames[0] + + for _, key := range flagNames { + if cCtx.IsSet(strings.TrimSpace(key)) { + flagPresent = true } - ff = set.Lookup(name) } - } - if ff == nil { - continue - } - for _, name := range parts { - name = strings.Trim(name, " ") - if !visited[name] { - copyFlag(name, ff, set) + + if !flagPresent && flagName != "" { + missingFlags = append(missingFlags, flagName) } } } + + if len(missingFlags) != 0 { + return &errRequiredFlags{missingFlags: missingFlags} + } + return nil } +func (cCtx *Context) onInvalidFlag(name string) { + for cCtx != nil { + if cCtx.App != nil && cCtx.App.InvalidFlagAccessHandler != nil { + cCtx.App.InvalidFlagAccessHandler(cCtx, name) + break + } + cCtx = cCtx.parentContext + } +} + func makeFlagNameVisitor(names *[]string) func(*flag.Flag) { return func(f *flag.Flag) { nameParts := strings.Split(f.Name, ",") @@ -219,55 +270,3 @@ func makeFlagNameVisitor(names *[]string) func(*flag.Flag) { } } } - -type requiredFlagsErr interface { - error - getMissingFlags() []string -} - -type errRequiredFlags struct { - missingFlags []string -} - -func (e *errRequiredFlags) Error() string { - numberOfMissingFlags := len(e.missingFlags) - if numberOfMissingFlags == 1 { - return fmt.Sprintf("Required flag %q not set", e.missingFlags[0]) - } - joinedMissingFlags := strings.Join(e.missingFlags, ", ") - return fmt.Sprintf("Required flags %q not set", joinedMissingFlags) -} - -func (e *errRequiredFlags) getMissingFlags() []string { - return e.missingFlags -} - -func checkRequiredFlags(flags []Flag, context *Context) requiredFlagsErr { - var missingFlags []string - for _, f := range flags { - if rf, ok := f.(RequiredFlag); ok && rf.IsRequired() { - var flagPresent bool - var flagName string - - for _, key := range f.Names() { - if len(key) > 1 { - flagName = key - } - - if context.IsSet(strings.TrimSpace(key)) { - flagPresent = true - } - } - - if !flagPresent && flagName != "" { - missingFlags = append(missingFlags, flagName) - } - } - } - - if len(missingFlags) != 0 { - return &errRequiredFlags{missingFlags: missingFlags} - } - - return nil -} diff --git a/vendor/github.com/urfave/cli/v2/docs.go b/vendor/github.com/urfave/cli/v2/docs.go index dc16fc82d..6cd0624ae 100644 --- a/vendor/github.com/urfave/cli/v2/docs.go +++ b/vendor/github.com/urfave/cli/v2/docs.go @@ -1,3 +1,6 @@ +//go:build !urfave_cli_no_docs +// +build !urfave_cli_no_docs + package cli import ( @@ -15,31 +18,39 @@ import ( // The function errors if either parsing or writing of the string fails. func (a *App) ToMarkdown() (string, error) { var w bytes.Buffer - if err := a.writeDocTemplate(&w); err != nil { + if err := a.writeDocTemplate(&w, 0); err != nil { return "", err } return w.String(), nil } -// ToMan creates a man page string for the `*App` +// ToMan creates a man page string with section number for the `*App` // The function errors if either parsing or writing of the string fails. -func (a *App) ToMan() (string, error) { +func (a *App) ToManWithSection(sectionNumber int) (string, error) { var w bytes.Buffer - if err := a.writeDocTemplate(&w); err != nil { + if err := a.writeDocTemplate(&w, sectionNumber); err != nil { return "", err } man := md2man.Render(w.Bytes()) return string(man), nil } +// ToMan creates a man page string for the `*App` +// The function errors if either parsing or writing of the string fails. +func (a *App) ToMan() (string, error) { + man, err := a.ToManWithSection(8) + return man, err +} + type cliTemplate struct { App *App + SectionNum int Commands []string GlobalArgs []string SynopsisArgs []string } -func (a *App) writeDocTemplate(w io.Writer) error { +func (a *App) writeDocTemplate(w io.Writer, sectionNum int) error { const name = "cli" t, err := template.New(name).Parse(MarkdownDocTemplate) if err != nil { @@ -47,6 +58,7 @@ func (a *App) writeDocTemplate(w io.Writer) error { } return t.ExecuteTemplate(w, name, &cliTemplate{ App: a, + SectionNum: sectionNum, Commands: prepareCommands(a.Commands, 0), GlobalArgs: prepareArgsWithValues(a.VisibleFlags()), SynopsisArgs: prepareArgsSynopsis(a.VisibleFlags()), @@ -59,25 +71,26 @@ func prepareCommands(commands []*Command, level int) []string { if command.Hidden { continue } - usage := "" - if command.Usage != "" { - usage = command.Usage - } - prepared := fmt.Sprintf("%s %s\n\n%s\n", + usageText := prepareUsageText(command) + + usage := prepareUsage(command, usageText) + + prepared := fmt.Sprintf("%s %s\n\n%s%s", strings.Repeat("#", level+2), strings.Join(command.Names(), ", "), usage, + usageText, ) - flags := prepareArgsWithValues(command.Flags) + flags := prepareArgsWithValues(command.VisibleFlags()) if len(flags) > 0 { prepared += fmt.Sprintf("\n%s", strings.Join(flags, "\n")) } coms = append(coms, prepared) - // recursevly iterate subcommands + // recursively iterate subcommands if len(command.Subcommands) > 0 { coms = append( coms, @@ -140,9 +153,51 @@ func prepareFlags( // flagDetails returns a string containing the flags metadata func flagDetails(flag DocGenerationFlag) string { description := flag.GetUsage() - value := flag.GetValue() - if value != "" { - description += " (default: " + value + ")" + if flag.TakesValue() { + defaultText := flag.GetDefaultText() + if defaultText == "" { + defaultText = flag.GetValue() + } + if defaultText != "" { + description += " (default: " + defaultText + ")" + } } return ": " + description } + +func prepareUsageText(command *Command) string { + if command.UsageText == "" { + return "" + } + + // Remove leading and trailing newlines + preparedUsageText := strings.Trim(command.UsageText, "\n") + + var usageText string + if strings.Contains(preparedUsageText, "\n") { + // Format multi-line string as a code block using the 4 space schema to allow for embedded markdown such + // that it will not break the continuous code block. + for _, ln := range strings.Split(preparedUsageText, "\n") { + usageText += fmt.Sprintf(" %s\n", ln) + } + } else { + // Style a single line as a note + usageText = fmt.Sprintf(">%s\n", preparedUsageText) + } + + return usageText +} + +func prepareUsage(command *Command, usageText string) string { + if command.Usage == "" { + return "" + } + + usage := command.Usage + "\n" + // Add a newline to the Usage IFF there is a UsageText + if usageText != "" { + usage += "\n" + } + + return usage +} diff --git a/vendor/github.com/urfave/cli/v2/errors.go b/vendor/github.com/urfave/cli/v2/errors.go index 344b4361e..a818727db 100644 --- a/vendor/github.com/urfave/cli/v2/errors.go +++ b/vendor/github.com/urfave/cli/v2/errors.go @@ -17,11 +17,10 @@ var ErrWriter io.Writer = os.Stderr // MultiError is an error that wraps multiple errors. type MultiError interface { error - // Errors returns a copy of the errors slice Errors() []error } -// NewMultiError creates a new MultiError. Pass in one or more errors. +// newMultiError creates a new MultiError. Pass in one or more errors. func newMultiError(err ...error) MultiError { ret := multiError(err) return &ret @@ -48,6 +47,28 @@ func (m *multiError) Errors() []error { return errs } +type requiredFlagsErr interface { + error + getMissingFlags() []string +} + +type errRequiredFlags struct { + missingFlags []string +} + +func (e *errRequiredFlags) Error() string { + numberOfMissingFlags := len(e.missingFlags) + if numberOfMissingFlags == 1 { + return fmt.Sprintf("Required flag %q not set", e.missingFlags[0]) + } + joinedMissingFlags := strings.Join(e.missingFlags, ", ") + return fmt.Sprintf("Required flags %q not set", joinedMissingFlags) +} + +func (e *errRequiredFlags) getMissingFlags() []string { + return e.missingFlags +} + // ErrorFormatter is the interface that will suitably format the error output type ErrorFormatter interface { Format(s fmt.State, verb rune) @@ -62,35 +83,61 @@ type ExitCoder interface { type exitError struct { exitCode int - message interface{} + err error } -// NewExitError makes a new *exitError +// NewExitError calls Exit to create a new ExitCoder. +// +// Deprecated: This function is a duplicate of Exit and will eventually be removed. func NewExitError(message interface{}, exitCode int) ExitCoder { return Exit(message, exitCode) } -// Exit wraps a message and exit code into an ExitCoder suitable for handling by -// HandleExitCoder +// Exit wraps a message and exit code into an error, which by default is +// handled with a call to os.Exit during default error handling. +// +// This is the simplest way to trigger a non-zero exit code for an App without +// having to call os.Exit manually. During testing, this behavior can be avoided +// by overriding the ExitErrHandler function on an App or the package-global +// OsExiter function. func Exit(message interface{}, exitCode int) ExitCoder { + var err error + + switch e := message.(type) { + case ErrorFormatter: + err = fmt.Errorf("%+v", message) + case error: + err = e + default: + err = fmt.Errorf("%+v", message) + } + return &exitError{ - message: message, + err: err, exitCode: exitCode, } } func (ee *exitError) Error() string { - return fmt.Sprintf("%v", ee.message) + return ee.err.Error() } func (ee *exitError) ExitCode() int { return ee.exitCode } -// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if -// so prints the error to stderr (if it is non-empty) and calls OsExiter with the -// given exit code. If the given error is a MultiError, then this func is -// called on all members of the Errors slice and calls OsExiter with the last exit code. +func (ee *exitError) Unwrap() error { + return ee.err +} + +// HandleExitCoder handles errors implementing ExitCoder by printing their +// message and calling OsExiter with the given exit code. +// +// If the given error instead implements MultiError, each error will be checked +// for the ExitCoder interface, and OsExiter will be called with the last exit +// code found, or exit code 1 if no ExitCoder is found. +// +// This function is the default error-handling behavior for an App. func HandleExitCoder(err error) { if err == nil { return diff --git a/vendor/github.com/urfave/cli/v2/fish.go b/vendor/github.com/urfave/cli/v2/fish.go index 67122c9fe..909dfc5a2 100644 --- a/vendor/github.com/urfave/cli/v2/fish.go +++ b/vendor/github.com/urfave/cli/v2/fish.go @@ -95,10 +95,10 @@ func (a *App) prepareFishCommands(commands []*Command, allCommands *[]string, pr completions = append(completions, completion.String()) completions = append( completions, - a.prepareFishFlags(command.Flags, command.Names())..., + a.prepareFishFlags(command.VisibleFlags(), command.Names())..., ) - // recursevly iterate subcommands + // recursively iterate subcommands if len(command.Subcommands) > 0 { completions = append( completions, @@ -171,6 +171,10 @@ func fishAddFileFlag(flag Flag, completion *strings.Builder) { if f.TakesFile { return } + case *PathFlag: + if f.TakesFile { + return + } } completion.WriteString(" -f") } diff --git a/vendor/github.com/urfave/cli/v2/flag-spec.yaml b/vendor/github.com/urfave/cli/v2/flag-spec.yaml new file mode 100644 index 000000000..03d82e701 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag-spec.yaml @@ -0,0 +1,131 @@ +# NOTE: this file is used by the tool defined in +# ./cmd/urfave-cli-genflags/main.go which uses the +# `Spec` type that maps to this file structure. +flag_types: + bool: + struct_fields: + - name: Count + type: int + pointer: true + - name: DisableDefaultText + type: bool + - name: Action + type: "func(*Context, bool) error" + float64: + struct_fields: + - name: Action + type: "func(*Context, float64) error" + Float64Slice: + value_pointer: true + skip_interfaces: + - fmt.Stringer + struct_fields: + - name: separator + type: separatorSpec + - name: Action + type: "func(*Context, []float64) error" + int: + struct_fields: + - name: Base + type: int + - name: Action + type: "func(*Context, int) error" + IntSlice: + value_pointer: true + skip_interfaces: + - fmt.Stringer + struct_fields: + - name: separator + type: separatorSpec + - name: Action + type: "func(*Context, []int) error" + int64: + struct_fields: + - name: Base + type: int + - name: Action + type: "func(*Context, int64) error" + Int64Slice: + value_pointer: true + skip_interfaces: + - fmt.Stringer + struct_fields: + - name: separator + type: separatorSpec + - name: Action + type: "func(*Context, []int64) error" + uint: + struct_fields: + - name: Base + type: int + - name: Action + type: "func(*Context, uint) error" + UintSlice: + value_pointer: true + skip_interfaces: + - fmt.Stringer + struct_fields: + - name: separator + type: separatorSpec + - name: Action + type: "func(*Context, []uint) error" + uint64: + struct_fields: + - name: Base + type: int + - name: Action + type: "func(*Context, uint64) error" + Uint64Slice: + value_pointer: true + skip_interfaces: + - fmt.Stringer + struct_fields: + - name: separator + type: separatorSpec + - name: Action + type: "func(*Context, []uint64) error" + string: + struct_fields: + - name: TakesFile + type: bool + - name: Action + type: "func(*Context, string) error" + StringSlice: + value_pointer: true + skip_interfaces: + - fmt.Stringer + struct_fields: + - name: separator + type: separatorSpec + - name: TakesFile + type: bool + - name: Action + type: "func(*Context, []string) error" + - name: KeepSpace + type: bool + time.Duration: + struct_fields: + - name: Action + type: "func(*Context, time.Duration) error" + Timestamp: + value_pointer: true + struct_fields: + - name: Layout + type: string + - name: Timezone + type: "*time.Location" + - name: Action + type: "func(*Context, *time.Time) error" + Generic: + no_destination_pointer: true + struct_fields: + - name: TakesFile + type: bool + - name: Action + type: "func(*Context, interface{}) error" + Path: + struct_fields: + - name: TakesFile + type: bool + - name: Action + type: "func(*Context, Path) error" diff --git a/vendor/github.com/urfave/cli/v2/flag.go b/vendor/github.com/urfave/cli/v2/flag.go index ad97c2d05..4d04de3da 100644 --- a/vendor/github.com/urfave/cli/v2/flag.go +++ b/vendor/github.com/urfave/cli/v2/flag.go @@ -1,13 +1,13 @@ package cli import ( + "errors" "flag" "fmt" - "io/ioutil" - "reflect" + "io" + "os" "regexp" "runtime" - "strconv" "strings" "syscall" "time" @@ -15,6 +15,11 @@ import ( const defaultPlaceholder = "value" +const ( + defaultSliceFlagSeparator = "," + disableSliceFlagSeparator = false +) + var ( slPfx = fmt.Sprintf("sl:::%d:::", time.Now().UTC().UnixNano()) @@ -29,18 +34,20 @@ var BashCompletionFlag Flag = &BoolFlag{ // VersionFlag prints the version for the application var VersionFlag Flag = &BoolFlag{ - Name: "version", - Aliases: []string{"v"}, - Usage: "print the version", + Name: "version", + Aliases: []string{"v"}, + Usage: "print the version", + DisableDefaultText: true, } // HelpFlag prints the help for all commands and subcommands. // Set to nil to disable the flag. The subcommand // will still be added unless HideHelp or HideHelpCommand is set to true. var HelpFlag Flag = &BoolFlag{ - Name: "help", - Aliases: []string{"h"}, - Usage: "show help", + Name: "help", + Aliases: []string{"h"}, + Usage: "show help", + DisableDefaultText: true, } // FlagStringer converts a flag definition to a string. This is used by help @@ -84,6 +91,12 @@ func (f FlagsByName) Swap(i, j int) { f[i], f[j] = f[j], f[i] } +// ActionableFlag is an interface that wraps Flag interface and RunAction operation. +type ActionableFlag interface { + Flag + RunAction(*Context) error +} + // Flag is a common interface related to parsing flags in cli. // For more advanced flag parsing techniques, it is recommended that // this interface be implemented. @@ -116,25 +129,105 @@ type DocGenerationFlag interface { // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. GetValue() string + + // GetDefaultText returns the default text for this flag + GetDefaultText() string + + // GetEnvVars returns the env vars for this flag + GetEnvVars() []string } -func flagSet(name string, flags []Flag) (*flag.FlagSet, error) { +// DocGenerationSliceFlag extends DocGenerationFlag for slice-based flags. +type DocGenerationSliceFlag interface { + DocGenerationFlag + + // IsSliceFlag returns true for flags that can be given multiple times. + IsSliceFlag() bool +} + +// VisibleFlag is an interface that allows to check if a flag is visible +type VisibleFlag interface { + Flag + + // IsVisible returns true if the flag is not hidden, otherwise false + IsVisible() bool +} + +// CategorizableFlag is an interface that allows us to potentially +// use a flag in a categorized representation. +type CategorizableFlag interface { + VisibleFlag + + GetCategory() string +} + +// Countable is an interface to enable detection of flag values which support +// repetitive flags +type Countable interface { + Count() int +} + +func flagSet(name string, flags []Flag, spec separatorSpec) (*flag.FlagSet, error) { set := flag.NewFlagSet(name, flag.ContinueOnError) for _, f := range flags { + if c, ok := f.(customizedSeparator); ok { + c.WithSeparatorSpec(spec) + } if err := f.Apply(set); err != nil { return nil, err } } - set.SetOutput(ioutil.Discard) + set.SetOutput(io.Discard) return set, nil } +func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) { + switch ff.Value.(type) { + case Serializer: + _ = set.Set(name, ff.Value.(Serializer).Serialize()) + default: + _ = set.Set(name, ff.Value.String()) + } +} + +func normalizeFlags(flags []Flag, set *flag.FlagSet) error { + visited := make(map[string]bool) + set.Visit(func(f *flag.Flag) { + visited[f.Name] = true + }) + for _, f := range flags { + parts := f.Names() + if len(parts) == 1 { + continue + } + var ff *flag.Flag + for _, name := range parts { + name = strings.Trim(name, " ") + if visited[name] { + if ff != nil { + return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name) + } + ff = set.Lookup(name) + } + } + if ff == nil { + continue + } + for _, name := range parts { + name = strings.Trim(name, " ") + if !visited[name] { + copyFlag(name, ff, set) + } + } + } + return nil +} + func visibleFlags(fl []Flag) []Flag { var visible []Flag for _, f := range fl { - field := flagValue(f).FieldByName("Hidden") - if !field.IsValid() || !field.Bool() { + if vf, ok := f.(VisibleFlag); ok && vf.IsVisible() { visible = append(visible, f) } } @@ -186,24 +279,28 @@ func prefixedNames(names []string, placeholder string) string { return prefixed } +func envFormat(envVars []string, prefix, sep, suffix string) string { + if len(envVars) > 0 { + return fmt.Sprintf(" [%s%s%s]", prefix, strings.Join(envVars, sep), suffix) + } + return "" +} + +func defaultEnvFormat(envVars []string) string { + return envFormat(envVars, "$", ", $", "") +} + func withEnvHint(envVars []string, str string) string { envText := "" - if envVars != nil && len(envVars) > 0 { - prefix := "$" - suffix := "" - sep := ", $" - if runtime.GOOS == "windows" { - prefix = "%" - suffix = "%" - sep = "%, %" - } - - envText = fmt.Sprintf(" [%s%s%s]", prefix, strings.Join(envVars, sep), suffix) + if runtime.GOOS != "windows" || os.Getenv("PSHOME") != "" { + envText = defaultEnvFormat(envVars) + } else { + envText = envFormat(envVars, "%", "%, %", "%") } return str + envText } -func flagNames(name string, aliases []string) []string { +func FlagNames(name string, aliases []string) []string { var ret []string for _, part := range append([]string{name}, aliases...) { @@ -217,17 +314,6 @@ func flagNames(name string, aliases []string) []string { return ret } -func flagStringSliceField(f Flag, name string) []string { - fv := flagValue(f) - field := fv.FieldByName(name) - - if field.IsValid() { - return field.Interface().([]string) - } - - return []string{} -} - func withFileHint(filePath, str string) string { fileText := "" if filePath != "" { @@ -236,130 +322,44 @@ func withFileHint(filePath, str string) string { return str + fileText } -func flagValue(f Flag) reflect.Value { - fv := reflect.ValueOf(f) - for fv.Kind() == reflect.Ptr { - fv = reflect.Indirect(fv) - } - return fv -} - func formatDefault(format string) string { return " (default: " + format + ")" } func stringifyFlag(f Flag) string { - fv := flagValue(f) - - switch f := f.(type) { - case *IntSliceFlag: - return withEnvHint(flagStringSliceField(f, "EnvVars"), - stringifyIntSliceFlag(f)) - case *Int64SliceFlag: - return withEnvHint(flagStringSliceField(f, "EnvVars"), - stringifyInt64SliceFlag(f)) - case *Float64SliceFlag: - return withEnvHint(flagStringSliceField(f, "EnvVars"), - stringifyFloat64SliceFlag(f)) - case *StringSliceFlag: - return withEnvHint(flagStringSliceField(f, "EnvVars"), - stringifyStringSliceFlag(f)) - } - - placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String()) - - needsPlaceholder := false - defaultValueString := "" - val := fv.FieldByName("Value") - if val.IsValid() { - needsPlaceholder = val.Kind() != reflect.Bool - defaultValueString = fmt.Sprintf(formatDefault("%v"), val.Interface()) - - if val.Kind() == reflect.String && val.String() != "" { - defaultValueString = fmt.Sprintf(formatDefault("%q"), val.String()) - } + // enforce DocGeneration interface on flags to avoid reflection + df, ok := f.(DocGenerationFlag) + if !ok { + return "" } - helpText := fv.FieldByName("DefaultText") - if helpText.IsValid() && helpText.String() != "" { - needsPlaceholder = val.Kind() != reflect.Bool - defaultValueString = fmt.Sprintf(formatDefault("%s"), helpText.String()) - } - - if defaultValueString == formatDefault("") { - defaultValueString = "" - } + placeholder, usage := unquoteUsage(df.GetUsage()) + needsPlaceholder := df.TakesValue() if needsPlaceholder && placeholder == "" { placeholder = defaultPlaceholder } - usageWithDefault := strings.TrimSpace(usage + defaultValueString) - - return withEnvHint(flagStringSliceField(f, "EnvVars"), - fmt.Sprintf("%s\t%s", prefixedNames(f.Names(), placeholder), usageWithDefault)) -} - -func stringifyIntSliceFlag(f *IntSliceFlag) string { - var defaultVals []string - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, i := range f.Value.Value() { - defaultVals = append(defaultVals, strconv.Itoa(i)) - } - } - - return stringifySliceFlag(f.Usage, f.Names(), defaultVals) -} - -func stringifyInt64SliceFlag(f *Int64SliceFlag) string { - var defaultVals []string - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, i := range f.Value.Value() { - defaultVals = append(defaultVals, strconv.FormatInt(i, 10)) - } - } - - return stringifySliceFlag(f.Usage, f.Names(), defaultVals) -} - -func stringifyFloat64SliceFlag(f *Float64SliceFlag) string { - var defaultVals []string - - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, i := range f.Value.Value() { - defaultVals = append(defaultVals, strings.TrimRight(strings.TrimRight(fmt.Sprintf("%f", i), "0"), ".")) - } - } - - return stringifySliceFlag(f.Usage, f.Names(), defaultVals) -} + defaultValueString := "" -func stringifyStringSliceFlag(f *StringSliceFlag) string { - var defaultVals []string - if f.Value != nil && len(f.Value.Value()) > 0 { - for _, s := range f.Value.Value() { - if len(s) > 0 { - defaultVals = append(defaultVals, strconv.Quote(s)) - } + // set default text for all flags except bool flags + // for bool flags display default text if DisableDefaultText is not + // set + if bf, ok := f.(*BoolFlag); !ok || !bf.DisableDefaultText { + if s := df.GetDefaultText(); s != "" { + defaultValueString = fmt.Sprintf(formatDefault("%s"), s) } } - return stringifySliceFlag(f.Usage, f.Names(), defaultVals) -} - -func stringifySliceFlag(usage string, names, defaultVals []string) string { - placeholder, usage := unquoteUsage(usage) - if placeholder == "" { - placeholder = defaultPlaceholder - } + usageWithDefault := strings.TrimSpace(usage + defaultValueString) - defaultVal := "" - if len(defaultVals) > 0 { - defaultVal = fmt.Sprintf(formatDefault("%s"), strings.Join(defaultVals, ", ")) + pn := prefixedNames(df.Names(), placeholder) + sliceFlag, ok := f.(DocGenerationSliceFlag) + if ok && sliceFlag.IsSliceFlag() { + pn = pn + " [ " + pn + " ]" } - usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultVal)) - return fmt.Sprintf("%s\t%s", prefixedNames(names, placeholder), usageWithDefault) + return withEnvHint(df.GetEnvVars(), fmt.Sprintf("%s\t%s", pn, usageWithDefault)) } func hasFlag(flags []Flag, fl Flag) bool { @@ -372,17 +372,48 @@ func hasFlag(flags []Flag, fl Flag) bool { return false } -func flagFromEnvOrFile(envVars []string, filePath string) (val string, ok bool) { +// Return the first value from a list of environment variables and files +// (which may or may not exist), a description of where the value was found, +// and a boolean which is true if a value was found. +func flagFromEnvOrFile(envVars []string, filePath string) (value string, fromWhere string, found bool) { for _, envVar := range envVars { envVar = strings.TrimSpace(envVar) - if val, ok := syscall.Getenv(envVar); ok { - return val, true + if value, found := syscall.Getenv(envVar); found { + return value, fmt.Sprintf("environment variable %q", envVar), true } } for _, fileVar := range strings.Split(filePath, ",") { - if data, err := ioutil.ReadFile(fileVar); err == nil { - return string(data), true + if fileVar != "" { + if data, err := os.ReadFile(fileVar); err == nil { + return string(data), fmt.Sprintf("file %q", filePath), true + } } } - return "", false + return "", "", false +} + +type customizedSeparator interface { + WithSeparatorSpec(separatorSpec) +} + +type separatorSpec struct { + sep string + disabled bool + customized bool +} + +func (s separatorSpec) flagSplitMultiValues(val string) []string { + var ( + disabled bool = s.disabled + sep string = s.sep + ) + if !s.customized { + disabled = disableSliceFlagSeparator + sep = defaultSliceFlagSeparator + } + if disabled { + return []string{val} + } + + return strings.Split(val, sep) } diff --git a/vendor/github.com/urfave/cli/v2/flag_bool.go b/vendor/github.com/urfave/cli/v2/flag_bool.go index bc9ea35d0..01862ea76 100644 --- a/vendor/github.com/urfave/cli/v2/flag_bool.go +++ b/vendor/github.com/urfave/cli/v2/flag_bool.go @@ -1,45 +1,61 @@ package cli import ( + "errors" "flag" "fmt" "strconv" ) -// BoolFlag is a flag with type bool -type BoolFlag struct { - Name string - Aliases []string - Usage string - EnvVars []string - FilePath string - Required bool - Hidden bool - Value bool - DefaultText string - Destination *bool - HasBeenSet bool +// boolValue needs to implement the boolFlag internal interface in flag +// to be able to capture bool fields and values +// +// type boolFlag interface { +// Value +// IsBoolFlag() bool +// } +type boolValue struct { + destination *bool + count *int } -// IsSet returns whether or not the flag has been set through env or file -func (f *BoolFlag) IsSet() bool { - return f.HasBeenSet +func newBoolValue(val bool, p *bool, count *int) *boolValue { + *p = val + return &boolValue{ + destination: p, + count: count, + } } -// String returns a readable representation of this value -// (for usage defaults) -func (f *BoolFlag) String() string { - return FlagStringer(f) +func (b *boolValue) Set(s string) error { + v, err := strconv.ParseBool(s) + if err != nil { + err = errors.New("parse error") + return err + } + *b.destination = v + if b.count != nil { + *b.count = *b.count + 1 + } + return err } -// Names returns the names of the flag -func (f *BoolFlag) Names() []string { - return flagNames(f.Name, f.Aliases) +func (b *boolValue) Get() interface{} { return *b.destination } + +func (b *boolValue) String() string { + if b.destination != nil { + return strconv.FormatBool(*b.destination) + } + return strconv.FormatBool(false) } -// IsRequired returns whether or not the flag is required -func (f *BoolFlag) IsRequired() bool { - return f.Required +func (b *boolValue) IsBoolFlag() bool { return true } + +func (b *boolValue) Count() int { + if b.count != nil && *b.count > 0 { + return *b.count + } + return 0 } // TakesValue returns true of the flag takes a value, otherwise false @@ -52,42 +68,98 @@ func (f *BoolFlag) GetUsage() string { return f.Usage } +// GetCategory returns the category for the flag +func (f *BoolFlag) GetCategory() string { + return f.Category +} + // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *BoolFlag) GetValue() string { return "" } +// GetDefaultText returns the default text for this flag +func (f *BoolFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + if f.defaultValueSet { + return fmt.Sprintf("%v", f.defaultValue) + } + return fmt.Sprintf("%v", f.Value) +} + +// GetEnvVars returns the env vars for this flag +func (f *BoolFlag) GetEnvVars() []string { + return f.EnvVars +} + +// RunAction executes flag action if set +func (f *BoolFlag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.Bool(f.Name)) + } + + return nil +} + // Apply populates the flag given the flag set and environment func (f *BoolFlag) Apply(set *flag.FlagSet) error { - if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + // set default value so that environment wont be able to overwrite it + f.defaultValue = f.Value + f.defaultValueSet = true + + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { if val != "" { valBool, err := strconv.ParseBool(val) if err != nil { - return fmt.Errorf("could not parse %q as bool value for flag %s: %s", val, f.Name, err) + return fmt.Errorf("could not parse %q as bool value from %s for flag %s: %s", val, source, f.Name, err) } f.Value = valBool - f.HasBeenSet = true + } else { + // empty value implies that the env is defined but set to empty string, we have to assume that this is + // what the user wants. If user doesnt want this then the env needs to be deleted or the flag removed from + // file + f.Value = false } + f.HasBeenSet = true + } + + count := f.Count + dest := f.Destination + + if count == nil { + count = new(int) + } + + // since count will be incremented for each alias as well + // subtract number of aliases from overall count + *count -= len(f.Aliases) + + if dest == nil { + dest = new(bool) } for _, name := range f.Names() { - if f.Destination != nil { - set.BoolVar(f.Destination, name, f.Value, f.Usage) - continue - } - set.Bool(name, f.Value, f.Usage) + value := newBoolValue(f.Value, dest, count) + set.Var(value, name, f.Usage) } return nil } +// Get returns the flag’s value in the given Context. +func (f *BoolFlag) Get(ctx *Context) bool { + return ctx.Bool(f.Name) +} + // Bool looks up the value of a local BoolFlag, returns // false if not found -func (c *Context) Bool(name string) bool { - if fs := lookupFlagSet(name, c); fs != nil { +func (cCtx *Context) Bool(name string) bool { + if fs := cCtx.lookupFlagSet(name); fs != nil { return lookupBool(name, fs) } return false diff --git a/vendor/github.com/urfave/cli/v2/flag_duration.go b/vendor/github.com/urfave/cli/v2/flag_duration.go index 22a2e6720..e600cc30a 100644 --- a/vendor/github.com/urfave/cli/v2/flag_duration.go +++ b/vendor/github.com/urfave/cli/v2/flag_duration.go @@ -6,42 +6,6 @@ import ( "time" ) -// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration) -type DurationFlag struct { - Name string - Aliases []string - Usage string - EnvVars []string - FilePath string - Required bool - Hidden bool - Value time.Duration - DefaultText string - Destination *time.Duration - HasBeenSet bool -} - -// IsSet returns whether or not the flag has been set through env or file -func (f *DurationFlag) IsSet() bool { - return f.HasBeenSet -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f *DurationFlag) String() string { - return FlagStringer(f) -} - -// Names returns the names of the flag -func (f *DurationFlag) Names() []string { - return flagNames(f.Name, f.Aliases) -} - -// IsRequired returns whether or not the flag is required -func (f *DurationFlag) IsRequired() bool { - return f.Required -} - // TakesValue returns true of the flag takes a value, otherwise false func (f *DurationFlag) TakesValue() bool { return true @@ -52,20 +16,45 @@ func (f *DurationFlag) GetUsage() string { return f.Usage } +// GetCategory returns the category for the flag +func (f *DurationFlag) GetCategory() string { + return f.Category +} + // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *DurationFlag) GetValue() string { return f.Value.String() } +// GetDefaultText returns the default text for this flag +func (f *DurationFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + if f.defaultValueSet { + return f.defaultValue.String() + } + return f.Value.String() +} + +// GetEnvVars returns the env vars for this flag +func (f *DurationFlag) GetEnvVars() []string { + return f.EnvVars +} + // Apply populates the flag given the flag set and environment func (f *DurationFlag) Apply(set *flag.FlagSet) error { - if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + // set default value so that environment wont be able to overwrite it + f.defaultValue = f.Value + f.defaultValueSet = true + + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { if val != "" { valDuration, err := time.ParseDuration(val) if err != nil { - return fmt.Errorf("could not parse %q as duration value for flag %s: %s", val, f.Name, err) + return fmt.Errorf("could not parse %q as duration value from %s for flag %s: %s", val, source, f.Name, err) } f.Value = valDuration @@ -83,10 +72,24 @@ func (f *DurationFlag) Apply(set *flag.FlagSet) error { return nil } +// Get returns the flag’s value in the given Context. +func (f *DurationFlag) Get(ctx *Context) time.Duration { + return ctx.Duration(f.Name) +} + +// RunAction executes flag action if set +func (f *DurationFlag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.Duration(f.Name)) + } + + return nil +} + // Duration looks up the value of a local DurationFlag, returns // 0 if not found -func (c *Context) Duration(name string) time.Duration { - if fs := lookupFlagSet(name, c); fs != nil { +func (cCtx *Context) Duration(name string) time.Duration { + if fs := cCtx.lookupFlagSet(name); fs != nil { return lookupDuration(name, fs) } return 0 diff --git a/vendor/github.com/urfave/cli/v2/flag_ext.go b/vendor/github.com/urfave/cli/v2/flag_ext.go new file mode 100644 index 000000000..64da59ea9 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_ext.go @@ -0,0 +1,48 @@ +package cli + +import "flag" + +type extFlag struct { + f *flag.Flag +} + +func (e *extFlag) Apply(fs *flag.FlagSet) error { + fs.Var(e.f.Value, e.f.Name, e.f.Usage) + return nil +} + +func (e *extFlag) Names() []string { + return []string{e.f.Name} +} + +func (e *extFlag) IsSet() bool { + return false +} + +func (e *extFlag) String() string { + return FlagStringer(e) +} + +func (e *extFlag) IsVisible() bool { + return true +} + +func (e *extFlag) TakesValue() bool { + return false +} + +func (e *extFlag) GetUsage() string { + return e.f.Usage +} + +func (e *extFlag) GetValue() string { + return e.f.Value.String() +} + +func (e *extFlag) GetDefaultText() string { + return e.f.DefValue +} + +func (e *extFlag) GetEnvVars() []string { + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_float64.go b/vendor/github.com/urfave/cli/v2/flag_float64.go index 91c778c87..6a4de5c88 100644 --- a/vendor/github.com/urfave/cli/v2/flag_float64.go +++ b/vendor/github.com/urfave/cli/v2/flag_float64.go @@ -6,42 +6,6 @@ import ( "strconv" ) -// Float64Flag is a flag with type float64 -type Float64Flag struct { - Name string - Aliases []string - Usage string - EnvVars []string - FilePath string - Required bool - Hidden bool - Value float64 - DefaultText string - Destination *float64 - HasBeenSet bool -} - -// IsSet returns whether or not the flag has been set through env or file -func (f *Float64Flag) IsSet() bool { - return f.HasBeenSet -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f *Float64Flag) String() string { - return FlagStringer(f) -} - -// Names returns the names of the flag -func (f *Float64Flag) Names() []string { - return flagNames(f.Name, f.Aliases) -} - -// IsRequired returns whether or not the flag is required -func (f *Float64Flag) IsRequired() bool { - return f.Required -} - // TakesValue returns true of the flag takes a value, otherwise false func (f *Float64Flag) TakesValue() bool { return true @@ -52,20 +16,43 @@ func (f *Float64Flag) GetUsage() string { return f.Usage } +// GetCategory returns the category for the flag +func (f *Float64Flag) GetCategory() string { + return f.Category +} + // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *Float64Flag) GetValue() string { - return fmt.Sprintf("%f", f.Value) + return fmt.Sprintf("%v", f.Value) +} + +// GetDefaultText returns the default text for this flag +func (f *Float64Flag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + if f.defaultValueSet { + return fmt.Sprintf("%v", f.defaultValue) + } + return fmt.Sprintf("%v", f.Value) +} + +// GetEnvVars returns the env vars for this flag +func (f *Float64Flag) GetEnvVars() []string { + return f.EnvVars } // Apply populates the flag given the flag set and environment func (f *Float64Flag) Apply(set *flag.FlagSet) error { - if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { - if val != "" { - valFloat, err := strconv.ParseFloat(val, 10) + f.defaultValue = f.Value + f.defaultValueSet = true + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + if val != "" { + valFloat, err := strconv.ParseFloat(val, 64) if err != nil { - return fmt.Errorf("could not parse %q as float64 value for flag %s: %s", val, f.Name, err) + return fmt.Errorf("could not parse %q as float64 value from %s for flag %s: %s", val, source, f.Name, err) } f.Value = valFloat @@ -84,10 +71,24 @@ func (f *Float64Flag) Apply(set *flag.FlagSet) error { return nil } +// Get returns the flag’s value in the given Context. +func (f *Float64Flag) Get(ctx *Context) float64 { + return ctx.Float64(f.Name) +} + +// RunAction executes flag action if set +func (f *Float64Flag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.Float64(f.Name)) + } + + return nil +} + // Float64 looks up the value of a local Float64Flag, returns // 0 if not found -func (c *Context) Float64(name string) float64 { - if fs := lookupFlagSet(name, c); fs != nil { +func (cCtx *Context) Float64(name string) float64 { + if fs := cCtx.lookupFlagSet(name); fs != nil { return lookupFloat64(name, fs) } return 0 diff --git a/vendor/github.com/urfave/cli/v2/flag_float64_slice.go b/vendor/github.com/urfave/cli/v2/flag_float64_slice.go index 706ee6cd4..0bc4612c8 100644 --- a/vendor/github.com/urfave/cli/v2/flag_float64_slice.go +++ b/vendor/github.com/urfave/cli/v2/flag_float64_slice.go @@ -11,6 +11,7 @@ import ( // Float64Slice wraps []float64 to satisfy flag.Value type Float64Slice struct { slice []float64 + separator separatorSpec hasBeenSet bool } @@ -19,6 +20,20 @@ func NewFloat64Slice(defaults ...float64) *Float64Slice { return &Float64Slice{slice: append([]float64{}, defaults...)} } +// clone allocate a copy of self object +func (f *Float64Slice) clone() *Float64Slice { + n := &Float64Slice{ + slice: make([]float64, len(f.slice)), + hasBeenSet: f.hasBeenSet, + } + copy(n.slice, f.slice) + return n +} + +func (f *Float64Slice) WithSeparatorSpec(spec separatorSpec) { + f.separator = spec +} + // Set parses the value into a float64 and appends it to the list of values func (f *Float64Slice) Set(value string) error { if !f.hasBeenSet { @@ -33,18 +48,25 @@ func (f *Float64Slice) Set(value string) error { return nil } - tmp, err := strconv.ParseFloat(value, 64) - if err != nil { - return err - } + for _, s := range f.separator.flagSplitMultiValues(value) { + tmp, err := strconv.ParseFloat(strings.TrimSpace(s), 64) + if err != nil { + return err + } - f.slice = append(f.slice, tmp) + f.slice = append(f.slice, tmp) + } return nil } // String returns a readable representation of this value (for usage defaults) func (f *Float64Slice) String() string { - return fmt.Sprintf("%#v", f.slice) + v := f.slice + if v == nil { + // treat nil the same as zero length non-nil + v = make([]float64, 0) + } + return fmt.Sprintf("%#v", v) } // Serialize allows Float64Slice to fulfill Serializer @@ -63,41 +85,12 @@ func (f *Float64Slice) Get() interface{} { return *f } -// Float64SliceFlag is a flag with type *Float64Slice -type Float64SliceFlag struct { - Name string - Aliases []string - Usage string - EnvVars []string - FilePath string - Required bool - Hidden bool - Value *Float64Slice - DefaultText string - HasBeenSet bool -} - -// IsSet returns whether or not the flag has been set through env or file -func (f *Float64SliceFlag) IsSet() bool { - return f.HasBeenSet -} - // String returns a readable representation of this value // (for usage defaults) func (f *Float64SliceFlag) String() string { return FlagStringer(f) } -// Names returns the names of the flag -func (f *Float64SliceFlag) Names() []string { - return flagNames(f.Name, f.Aliases) -} - -// IsRequired returns whether or not the flag is required -func (f *Float64SliceFlag) IsRequired() bool { - return f.Required -} - // TakesValue returns true if the flag takes a value, otherwise false func (f *Float64SliceFlag) TakesValue() bool { return true @@ -108,36 +101,96 @@ func (f *Float64SliceFlag) GetUsage() string { return f.Usage } +// GetCategory returns the category for the flag +func (f *Float64SliceFlag) GetCategory() string { + return f.Category +} + // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *Float64SliceFlag) GetValue() string { - if f.Value != nil { - return f.Value.String() + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strings.TrimRight(strings.TrimRight(fmt.Sprintf("%f", i), "0"), ".")) + } } - return "" + return strings.Join(defaultVals, ", ") +} + +// GetDefaultText returns the default text for this flag +func (f *Float64SliceFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *Float64SliceFlag) GetEnvVars() []string { + return f.EnvVars +} + +// IsSliceFlag implements DocGenerationSliceFlag. +func (f *Float64SliceFlag) IsSliceFlag() bool { + return true } // Apply populates the flag given the flag set and environment func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error { - if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { - if val != "" { - f.Value = &Float64Slice{} + // apply any default + if f.Destination != nil && f.Value != nil { + f.Destination.slice = make([]float64, len(f.Value.slice)) + copy(f.Destination.slice, f.Value.slice) + } - for _, s := range strings.Split(val, ",") { - if err := f.Value.Set(strings.TrimSpace(s)); err != nil { - return fmt.Errorf("could not parse %q as float64 slice value for flag %s: %s", f.Value, f.Name, err) + // resolve setValue (what we will assign to the set) + var setValue *Float64Slice + switch { + case f.Destination != nil: + setValue = f.Destination + case f.Value != nil: + setValue = f.Value.clone() + default: + setValue = new(Float64Slice) + setValue.WithSeparatorSpec(f.separator) + } + + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + if val != "" { + for _, s := range f.separator.flagSplitMultiValues(val) { + if err := setValue.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as float64 slice value from %s for flag %s: %s", val, source, f.Name, err) } } + // Set this to false so that we reset the slice if we then set values from + // flags that have already been set by the environment. + setValue.hasBeenSet = false f.HasBeenSet = true } } for _, name := range f.Names() { - if f.Value == nil { - f.Value = &Float64Slice{} - } - set.Var(f.Value, name, f.Usage) + set.Var(setValue, name, f.Usage) + } + + return nil +} + +func (f *Float64SliceFlag) WithSeparatorSpec(spec separatorSpec) { + f.separator = spec +} + +// Get returns the flag’s value in the given Context. +func (f *Float64SliceFlag) Get(ctx *Context) []float64 { + return ctx.Float64Slice(f.Name) +} + +// RunAction executes flag action if set +func (f *Float64SliceFlag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.Float64Slice(f.Name)) } return nil @@ -145,8 +198,8 @@ func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error { // Float64Slice looks up the value of a local Float64SliceFlag, returns // nil if not found -func (c *Context) Float64Slice(name string) []float64 { - if fs := lookupFlagSet(name, c); fs != nil { +func (cCtx *Context) Float64Slice(name string) []float64 { + if fs := cCtx.lookupFlagSet(name); fs != nil { return lookupFloat64Slice(name, fs) } return nil @@ -155,7 +208,7 @@ func (c *Context) Float64Slice(name string) []float64 { func lookupFloat64Slice(name string, set *flag.FlagSet) []float64 { f := set.Lookup(name) if f != nil { - if slice, ok := f.Value.(*Float64Slice); ok { + if slice, ok := unwrapFlagValue(f.Value).(*Float64Slice); ok { return slice.Value() } } diff --git a/vendor/github.com/urfave/cli/v2/flag_generic.go b/vendor/github.com/urfave/cli/v2/flag_generic.go index b0c8ff44d..7528c934c 100644 --- a/vendor/github.com/urfave/cli/v2/flag_generic.go +++ b/vendor/github.com/urfave/cli/v2/flag_generic.go @@ -11,40 +11,17 @@ type Generic interface { String() string } -// GenericFlag is a flag with type Generic -type GenericFlag struct { - Name string - Aliases []string - Usage string - EnvVars []string - FilePath string - Required bool - Hidden bool - TakesFile bool - Value Generic - DefaultText string - HasBeenSet bool +type stringGeneric struct { + value string } -// IsSet returns whether or not the flag has been set through env or file -func (f *GenericFlag) IsSet() bool { - return f.HasBeenSet -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f *GenericFlag) String() string { - return FlagStringer(f) -} - -// Names returns the names of the flag -func (f *GenericFlag) Names() []string { - return flagNames(f.Name, f.Aliases) +func (s *stringGeneric) Set(value string) error { + s.value = value + return nil } -// IsRequired returns whether or not the flag is required -func (f *GenericFlag) IsRequired() bool { - return f.Required +func (s *stringGeneric) String() string { + return s.value } // TakesValue returns true of the flag takes a value, otherwise false @@ -57,6 +34,11 @@ func (f *GenericFlag) GetUsage() string { return f.Usage } +// GetCategory returns the category for the flag +func (f *GenericFlag) GetCategory() string { + return f.Category +} + // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *GenericFlag) GetValue() string { @@ -66,13 +48,41 @@ func (f *GenericFlag) GetValue() string { return "" } +// GetDefaultText returns the default text for this flag +func (f *GenericFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + val := f.Value + if f.defaultValueSet { + val = f.defaultValue + } + + if val != nil { + return val.String() + } + + return "" +} + +// GetEnvVars returns the env vars for this flag +func (f *GenericFlag) GetEnvVars() []string { + return f.EnvVars +} + // Apply takes the flagset and calls Set on the generic flag with the value // provided by the user for parsing by the flag -func (f GenericFlag) Apply(set *flag.FlagSet) error { - if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { +func (f *GenericFlag) Apply(set *flag.FlagSet) error { + // set default value so that environment wont be able to overwrite it + if f.Value != nil { + f.defaultValue = &stringGeneric{value: f.Value.String()} + f.defaultValueSet = true + } + + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { if val != "" { if err := f.Value.Set(val); err != nil { - return fmt.Errorf("could not parse %q as value for flag %s: %s", val, f.Name, err) + return fmt.Errorf("could not parse %q from %s as value for flag %s: %s", val, source, f.Name, err) } f.HasBeenSet = true @@ -80,29 +90,42 @@ func (f GenericFlag) Apply(set *flag.FlagSet) error { } for _, name := range f.Names() { + if f.Destination != nil { + set.Var(f.Destination, name, f.Usage) + continue + } set.Var(f.Value, name, f.Usage) } return nil } +// Get returns the flag’s value in the given Context. +func (f *GenericFlag) Get(ctx *Context) interface{} { + return ctx.Generic(f.Name) +} + +// RunAction executes flag action if set +func (f *GenericFlag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.Generic(f.Name)) + } + + return nil +} + // Generic looks up the value of a local GenericFlag, returns // nil if not found -func (c *Context) Generic(name string) interface{} { - if fs := lookupFlagSet(name, c); fs != nil { +func (cCtx *Context) Generic(name string) interface{} { + if fs := cCtx.lookupFlagSet(name); fs != nil { return lookupGeneric(name, fs) } return nil } func lookupGeneric(name string, set *flag.FlagSet) interface{} { - f := set.Lookup(name) - if f != nil { - parsed, err := f.Value, error(nil) - if err != nil { - return nil - } - return parsed + if f := set.Lookup(name); f != nil { + return f.Value } return nil } diff --git a/vendor/github.com/urfave/cli/v2/flag_int.go b/vendor/github.com/urfave/cli/v2/flag_int.go index ac39d4a9e..750e7ebfc 100644 --- a/vendor/github.com/urfave/cli/v2/flag_int.go +++ b/vendor/github.com/urfave/cli/v2/flag_int.go @@ -6,42 +6,6 @@ import ( "strconv" ) -// IntFlag is a flag with type int -type IntFlag struct { - Name string - Aliases []string - Usage string - EnvVars []string - FilePath string - Required bool - Hidden bool - Value int - DefaultText string - Destination *int - HasBeenSet bool -} - -// IsSet returns whether or not the flag has been set through env or file -func (f *IntFlag) IsSet() bool { - return f.HasBeenSet -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f *IntFlag) String() string { - return FlagStringer(f) -} - -// Names returns the names of the flag -func (f *IntFlag) Names() []string { - return flagNames(f.Name, f.Aliases) -} - -// IsRequired returns whether or not the flag is required -func (f *IntFlag) IsRequired() bool { - return f.Required -} - // TakesValue returns true of the flag takes a value, otherwise false func (f *IntFlag) TakesValue() bool { return true @@ -52,20 +16,45 @@ func (f *IntFlag) GetUsage() string { return f.Usage } +// GetCategory returns the category for the flag +func (f *IntFlag) GetCategory() string { + return f.Category +} + // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *IntFlag) GetValue() string { return fmt.Sprintf("%d", f.Value) } +// GetDefaultText returns the default text for this flag +func (f *IntFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + if f.defaultValueSet { + return fmt.Sprintf("%d", f.defaultValue) + } + return fmt.Sprintf("%d", f.Value) +} + +// GetEnvVars returns the env vars for this flag +func (f *IntFlag) GetEnvVars() []string { + return f.EnvVars +} + // Apply populates the flag given the flag set and environment func (f *IntFlag) Apply(set *flag.FlagSet) error { - if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + // set default value so that environment wont be able to overwrite it + f.defaultValue = f.Value + f.defaultValueSet = true + + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { if val != "" { - valInt, err := strconv.ParseInt(val, 0, 64) + valInt, err := strconv.ParseInt(val, f.Base, 64) if err != nil { - return fmt.Errorf("could not parse %q as int value for flag %s: %s", val, f.Name, err) + return fmt.Errorf("could not parse %q as int value from %s for flag %s: %s", val, source, f.Name, err) } f.Value = int(valInt) @@ -84,10 +73,24 @@ func (f *IntFlag) Apply(set *flag.FlagSet) error { return nil } +// Get returns the flag’s value in the given Context. +func (f *IntFlag) Get(ctx *Context) int { + return ctx.Int(f.Name) +} + +// RunAction executes flag action if set +func (f *IntFlag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.Int(f.Name)) + } + + return nil +} + // Int looks up the value of a local IntFlag, returns // 0 if not found -func (c *Context) Int(name string) int { - if fs := lookupFlagSet(name, c); fs != nil { +func (cCtx *Context) Int(name string) int { + if fs := cCtx.lookupFlagSet(name); fs != nil { return lookupInt(name, fs) } return 0 diff --git a/vendor/github.com/urfave/cli/v2/flag_int64.go b/vendor/github.com/urfave/cli/v2/flag_int64.go index e09991269..688c26716 100644 --- a/vendor/github.com/urfave/cli/v2/flag_int64.go +++ b/vendor/github.com/urfave/cli/v2/flag_int64.go @@ -6,42 +6,6 @@ import ( "strconv" ) -// Int64Flag is a flag with type int64 -type Int64Flag struct { - Name string - Aliases []string - Usage string - EnvVars []string - FilePath string - Required bool - Hidden bool - Value int64 - DefaultText string - Destination *int64 - HasBeenSet bool -} - -// IsSet returns whether or not the flag has been set through env or file -func (f *Int64Flag) IsSet() bool { - return f.HasBeenSet -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f *Int64Flag) String() string { - return FlagStringer(f) -} - -// Names returns the names of the flag -func (f *Int64Flag) Names() []string { - return flagNames(f.Name, f.Aliases) -} - -// IsRequired returns whether or not the flag is required -func (f *Int64Flag) IsRequired() bool { - return f.Required -} - // TakesValue returns true of the flag takes a value, otherwise false func (f *Int64Flag) TakesValue() bool { return true @@ -52,20 +16,45 @@ func (f *Int64Flag) GetUsage() string { return f.Usage } +// GetCategory returns the category for the flag +func (f *Int64Flag) GetCategory() string { + return f.Category +} + // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *Int64Flag) GetValue() string { return fmt.Sprintf("%d", f.Value) } +// GetDefaultText returns the default text for this flag +func (f *Int64Flag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + if f.defaultValueSet { + return fmt.Sprintf("%d", f.defaultValue) + } + return fmt.Sprintf("%d", f.Value) +} + +// GetEnvVars returns the env vars for this flag +func (f *Int64Flag) GetEnvVars() []string { + return f.EnvVars +} + // Apply populates the flag given the flag set and environment func (f *Int64Flag) Apply(set *flag.FlagSet) error { - if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + // set default value so that environment wont be able to overwrite it + f.defaultValue = f.Value + f.defaultValueSet = true + + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { if val != "" { - valInt, err := strconv.ParseInt(val, 0, 64) + valInt, err := strconv.ParseInt(val, f.Base, 64) if err != nil { - return fmt.Errorf("could not parse %q as int value for flag %s: %s", val, f.Name, err) + return fmt.Errorf("could not parse %q as int value from %s for flag %s: %s", val, source, f.Name, err) } f.Value = valInt @@ -83,10 +72,24 @@ func (f *Int64Flag) Apply(set *flag.FlagSet) error { return nil } +// Get returns the flag’s value in the given Context. +func (f *Int64Flag) Get(ctx *Context) int64 { + return ctx.Int64(f.Name) +} + +// RunAction executes flag action if set +func (f *Int64Flag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.Int64(f.Name)) + } + + return nil +} + // Int64 looks up the value of a local Int64Flag, returns // 0 if not found -func (c *Context) Int64(name string) int64 { - if fs := lookupFlagSet(name, c); fs != nil { +func (cCtx *Context) Int64(name string) int64 { + if fs := cCtx.lookupFlagSet(name); fs != nil { return lookupInt64(name, fs) } return 0 diff --git a/vendor/github.com/urfave/cli/v2/flag_int64_slice.go b/vendor/github.com/urfave/cli/v2/flag_int64_slice.go index 6c7fd9376..d45c2dd44 100644 --- a/vendor/github.com/urfave/cli/v2/flag_int64_slice.go +++ b/vendor/github.com/urfave/cli/v2/flag_int64_slice.go @@ -11,6 +11,7 @@ import ( // Int64Slice wraps []int64 to satisfy flag.Value type Int64Slice struct { slice []int64 + separator separatorSpec hasBeenSet bool } @@ -19,6 +20,20 @@ func NewInt64Slice(defaults ...int64) *Int64Slice { return &Int64Slice{slice: append([]int64{}, defaults...)} } +// clone allocate a copy of self object +func (i *Int64Slice) clone() *Int64Slice { + n := &Int64Slice{ + slice: make([]int64, len(i.slice)), + hasBeenSet: i.hasBeenSet, + } + copy(n.slice, i.slice) + return n +} + +func (i *Int64Slice) WithSeparatorSpec(spec separatorSpec) { + i.separator = spec +} + // Set parses the value into an integer and appends it to the list of values func (i *Int64Slice) Set(value string) error { if !i.hasBeenSet { @@ -33,19 +48,26 @@ func (i *Int64Slice) Set(value string) error { return nil } - tmp, err := strconv.ParseInt(value, 0, 64) - if err != nil { - return err - } + for _, s := range i.separator.flagSplitMultiValues(value) { + tmp, err := strconv.ParseInt(strings.TrimSpace(s), 0, 64) + if err != nil { + return err + } - i.slice = append(i.slice, tmp) + i.slice = append(i.slice, tmp) + } return nil } // String returns a readable representation of this value (for usage defaults) func (i *Int64Slice) String() string { - return fmt.Sprintf("%#v", i.slice) + v := i.slice + if v == nil { + // treat nil the same as zero length non-nil + v = make([]int64, 0) + } + return fmt.Sprintf("%#v", v) } // Serialize allows Int64Slice to fulfill Serializer @@ -64,79 +86,110 @@ func (i *Int64Slice) Get() interface{} { return *i } -// Int64SliceFlag is a flag with type *Int64Slice -type Int64SliceFlag struct { - Name string - Aliases []string - Usage string - EnvVars []string - FilePath string - Required bool - Hidden bool - Value *Int64Slice - DefaultText string - HasBeenSet bool -} - -// IsSet returns whether or not the flag has been set through env or file -func (f *Int64SliceFlag) IsSet() bool { - return f.HasBeenSet -} - // String returns a readable representation of this value // (for usage defaults) func (f *Int64SliceFlag) String() string { return FlagStringer(f) } -// Names returns the names of the flag -func (f *Int64SliceFlag) Names() []string { - return flagNames(f.Name, f.Aliases) -} - -// IsRequired returns whether or not the flag is required -func (f *Int64SliceFlag) IsRequired() bool { - return f.Required -} - // TakesValue returns true of the flag takes a value, otherwise false func (f *Int64SliceFlag) TakesValue() bool { return true } // GetUsage returns the usage string for the flag -func (f Int64SliceFlag) GetUsage() string { +func (f *Int64SliceFlag) GetUsage() string { return f.Usage } +// GetCategory returns the category for the flag +func (f *Int64SliceFlag) GetCategory() string { + return f.Category +} + // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *Int64SliceFlag) GetValue() string { - if f.Value != nil { - return f.Value.String() + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strconv.FormatInt(i, 10)) + } } - return "" + return strings.Join(defaultVals, ", ") +} + +// GetDefaultText returns the default text for this flag +func (f *Int64SliceFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *Int64SliceFlag) GetEnvVars() []string { + return f.EnvVars +} + +// IsSliceFlag implements DocGenerationSliceFlag. +func (f *Int64SliceFlag) IsSliceFlag() bool { + return true } // Apply populates the flag given the flag set and environment func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error { - if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { - f.Value = &Int64Slice{} + // apply any default + if f.Destination != nil && f.Value != nil { + f.Destination.slice = make([]int64, len(f.Value.slice)) + copy(f.Destination.slice, f.Value.slice) + } + + // resolve setValue (what we will assign to the set) + var setValue *Int64Slice + switch { + case f.Destination != nil: + setValue = f.Destination + case f.Value != nil: + setValue = f.Value.clone() + default: + setValue = new(Int64Slice) + setValue.WithSeparatorSpec(f.separator) + } - for _, s := range strings.Split(val, ",") { - if err := f.Value.Set(strings.TrimSpace(s)); err != nil { - return fmt.Errorf("could not parse %q as int64 slice value for flag %s: %s", val, f.Name, err) + if val, source, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok && val != "" { + for _, s := range f.separator.flagSplitMultiValues(val) { + if err := setValue.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as int64 slice value from %s for flag %s: %s", val, source, f.Name, err) } } + // Set this to false so that we reset the slice if we then set values from + // flags that have already been set by the environment. + setValue.hasBeenSet = false f.HasBeenSet = true } for _, name := range f.Names() { - if f.Value == nil { - f.Value = &Int64Slice{} - } - set.Var(f.Value, name, f.Usage) + set.Var(setValue, name, f.Usage) + } + + return nil +} + +func (f *Int64SliceFlag) WithSeparatorSpec(spec separatorSpec) { + f.separator = spec +} + +// Get returns the flag’s value in the given Context. +func (f *Int64SliceFlag) Get(ctx *Context) []int64 { + return ctx.Int64Slice(f.Name) +} + +// RunAction executes flag action if set +func (f *Int64SliceFlag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.Int64Slice(f.Name)) } return nil @@ -144,14 +197,17 @@ func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error { // Int64Slice looks up the value of a local Int64SliceFlag, returns // nil if not found -func (c *Context) Int64Slice(name string) []int64 { - return lookupInt64Slice(name, c.flagSet) +func (cCtx *Context) Int64Slice(name string) []int64 { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupInt64Slice(name, fs) + } + return nil } func lookupInt64Slice(name string, set *flag.FlagSet) []int64 { f := set.Lookup(name) if f != nil { - if slice, ok := f.Value.(*Int64Slice); ok { + if slice, ok := unwrapFlagValue(f.Value).(*Int64Slice); ok { return slice.Value() } } diff --git a/vendor/github.com/urfave/cli/v2/flag_int_slice.go b/vendor/github.com/urfave/cli/v2/flag_int_slice.go index 4e0afc021..da9c09bc7 100644 --- a/vendor/github.com/urfave/cli/v2/flag_int_slice.go +++ b/vendor/github.com/urfave/cli/v2/flag_int_slice.go @@ -11,6 +11,7 @@ import ( // IntSlice wraps []int to satisfy flag.Value type IntSlice struct { slice []int + separator separatorSpec hasBeenSet bool } @@ -19,6 +20,16 @@ func NewIntSlice(defaults ...int) *IntSlice { return &IntSlice{slice: append([]int{}, defaults...)} } +// clone allocate a copy of self object +func (i *IntSlice) clone() *IntSlice { + n := &IntSlice{ + slice: make([]int, len(i.slice)), + hasBeenSet: i.hasBeenSet, + } + copy(n.slice, i.slice) + return n +} + // TODO: Consistently have specific Set function for Int64 and Float64 ? // SetInt directly adds an integer to the list of values func (i *IntSlice) SetInt(value int) { @@ -30,6 +41,10 @@ func (i *IntSlice) SetInt(value int) { i.slice = append(i.slice, value) } +func (i *IntSlice) WithSeparatorSpec(spec separatorSpec) { + i.separator = spec +} + // Set parses the value into an integer and appends it to the list of values func (i *IntSlice) Set(value string) error { if !i.hasBeenSet { @@ -44,19 +59,26 @@ func (i *IntSlice) Set(value string) error { return nil } - tmp, err := strconv.ParseInt(value, 0, 64) - if err != nil { - return err - } + for _, s := range i.separator.flagSplitMultiValues(value) { + tmp, err := strconv.ParseInt(strings.TrimSpace(s), 0, 64) + if err != nil { + return err + } - i.slice = append(i.slice, int(tmp)) + i.slice = append(i.slice, int(tmp)) + } return nil } // String returns a readable representation of this value (for usage defaults) func (i *IntSlice) String() string { - return fmt.Sprintf("%#v", i.slice) + v := i.slice + if v == nil { + // treat nil the same as zero length non-nil + v = make([]int, 0) + } + return fmt.Sprintf("%#v", v) } // Serialize allows IntSlice to fulfill Serializer @@ -75,79 +97,110 @@ func (i *IntSlice) Get() interface{} { return *i } -// IntSliceFlag is a flag with type *IntSlice -type IntSliceFlag struct { - Name string - Aliases []string - Usage string - EnvVars []string - FilePath string - Required bool - Hidden bool - Value *IntSlice - DefaultText string - HasBeenSet bool -} - -// IsSet returns whether or not the flag has been set through env or file -func (f *IntSliceFlag) IsSet() bool { - return f.HasBeenSet -} - // String returns a readable representation of this value // (for usage defaults) func (f *IntSliceFlag) String() string { return FlagStringer(f) } -// Names returns the names of the flag -func (f *IntSliceFlag) Names() []string { - return flagNames(f.Name, f.Aliases) -} - -// IsRequired returns whether or not the flag is required -func (f *IntSliceFlag) IsRequired() bool { - return f.Required -} - // TakesValue returns true of the flag takes a value, otherwise false func (f *IntSliceFlag) TakesValue() bool { return true } // GetUsage returns the usage string for the flag -func (f IntSliceFlag) GetUsage() string { +func (f *IntSliceFlag) GetUsage() string { return f.Usage } +// GetCategory returns the category for the flag +func (f *IntSliceFlag) GetCategory() string { + return f.Category +} + // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *IntSliceFlag) GetValue() string { - if f.Value != nil { - return f.Value.String() + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strconv.Itoa(i)) + } } - return "" + return strings.Join(defaultVals, ", ") +} + +// GetDefaultText returns the default text for this flag +func (f *IntSliceFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *IntSliceFlag) GetEnvVars() []string { + return f.EnvVars +} + +// IsSliceFlag implements DocGenerationSliceFlag. +func (f *IntSliceFlag) IsSliceFlag() bool { + return true } // Apply populates the flag given the flag set and environment func (f *IntSliceFlag) Apply(set *flag.FlagSet) error { - if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { - f.Value = &IntSlice{} + // apply any default + if f.Destination != nil && f.Value != nil { + f.Destination.slice = make([]int, len(f.Value.slice)) + copy(f.Destination.slice, f.Value.slice) + } + + // resolve setValue (what we will assign to the set) + var setValue *IntSlice + switch { + case f.Destination != nil: + setValue = f.Destination + case f.Value != nil: + setValue = f.Value.clone() + default: + setValue = new(IntSlice) + setValue.WithSeparatorSpec(f.separator) + } - for _, s := range strings.Split(val, ",") { - if err := f.Value.Set(strings.TrimSpace(s)); err != nil { - return fmt.Errorf("could not parse %q as int slice value for flag %s: %s", val, f.Name, err) + if val, source, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok && val != "" { + for _, s := range f.separator.flagSplitMultiValues(val) { + if err := setValue.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as int slice value from %s for flag %s: %s", val, source, f.Name, err) } } + // Set this to false so that we reset the slice if we then set values from + // flags that have already been set by the environment. + setValue.hasBeenSet = false f.HasBeenSet = true } for _, name := range f.Names() { - if f.Value == nil { - f.Value = &IntSlice{} - } - set.Var(f.Value, name, f.Usage) + set.Var(setValue, name, f.Usage) + } + + return nil +} + +func (f *IntSliceFlag) WithSeparatorSpec(spec separatorSpec) { + f.separator = spec +} + +// Get returns the flag’s value in the given Context. +func (f *IntSliceFlag) Get(ctx *Context) []int { + return ctx.IntSlice(f.Name) +} + +// RunAction executes flag action if set +func (f *IntSliceFlag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.IntSlice(f.Name)) } return nil @@ -155,9 +208,9 @@ func (f *IntSliceFlag) Apply(set *flag.FlagSet) error { // IntSlice looks up the value of a local IntSliceFlag, returns // nil if not found -func (c *Context) IntSlice(name string) []int { - if fs := lookupFlagSet(name, c); fs != nil { - return lookupIntSlice(name, c.flagSet) +func (cCtx *Context) IntSlice(name string) []int { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupIntSlice(name, fs) } return nil } @@ -165,7 +218,7 @@ func (c *Context) IntSlice(name string) []int { func lookupIntSlice(name string, set *flag.FlagSet) []int { f := set.Lookup(name) if f != nil { - if slice, ok := f.Value.(*IntSlice); ok { + if slice, ok := unwrapFlagValue(f.Value).(*IntSlice); ok { return slice.Value() } } diff --git a/vendor/github.com/urfave/cli/v2/flag_path.go b/vendor/github.com/urfave/cli/v2/flag_path.go index 8070dc4b0..76cb35248 100644 --- a/vendor/github.com/urfave/cli/v2/flag_path.go +++ b/vendor/github.com/urfave/cli/v2/flag_path.go @@ -1,42 +1,11 @@ package cli -import "flag" - -type PathFlag struct { - Name string - Aliases []string - Usage string - EnvVars []string - FilePath string - Required bool - Hidden bool - TakesFile bool - Value string - DefaultText string - Destination *string - HasBeenSet bool -} - -// IsSet returns whether or not the flag has been set through env or file -func (f *PathFlag) IsSet() bool { - return f.HasBeenSet -} +import ( + "flag" + "fmt" +) -// String returns a readable representation of this value -// (for usage defaults) -func (f *PathFlag) String() string { - return FlagStringer(f) -} - -// Names returns the names of the flag -func (f *PathFlag) Names() []string { - return flagNames(f.Name, f.Aliases) -} - -// IsRequired returns whether or not the flag is required -func (f *PathFlag) IsRequired() bool { - return f.Required -} +type Path = string // TakesValue returns true of the flag takes a value, otherwise false func (f *PathFlag) TakesValue() bool { @@ -48,15 +17,44 @@ func (f *PathFlag) GetUsage() string { return f.Usage } +// GetCategory returns the category for the flag +func (f *PathFlag) GetCategory() string { + return f.Category +} + // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *PathFlag) GetValue() string { return f.Value } +// GetDefaultText returns the default text for this flag +func (f *PathFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + val := f.Value + if f.defaultValueSet { + val = f.defaultValue + } + if val == "" { + return val + } + return fmt.Sprintf("%q", val) +} + +// GetEnvVars returns the env vars for this flag +func (f *PathFlag) GetEnvVars() []string { + return f.EnvVars +} + // Apply populates the flag given the flag set and environment func (f *PathFlag) Apply(set *flag.FlagSet) error { - if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + // set default value so that environment wont be able to overwrite it + f.defaultValue = f.Value + f.defaultValueSet = true + + if val, _, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { f.Value = val f.HasBeenSet = true } @@ -72,10 +70,24 @@ func (f *PathFlag) Apply(set *flag.FlagSet) error { return nil } +// Get returns the flag’s value in the given Context. +func (f *PathFlag) Get(ctx *Context) string { + return ctx.Path(f.Name) +} + +// RunAction executes flag action if set +func (f *PathFlag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.Path(f.Name)) + } + + return nil +} + // Path looks up the value of a local PathFlag, returns // "" if not found -func (c *Context) Path(name string) string { - if fs := lookupFlagSet(name, c); fs != nil { +func (cCtx *Context) Path(name string) string { + if fs := cCtx.lookupFlagSet(name); fs != nil { return lookupPath(name, fs) } @@ -83,13 +95,8 @@ func (c *Context) Path(name string) string { } func lookupPath(name string, set *flag.FlagSet) string { - f := set.Lookup(name) - if f != nil { - parsed, err := f.Value.String(), error(nil) - if err != nil { - return "" - } - return parsed + if f := set.Lookup(name); f != nil { + return f.Value.String() } return "" } diff --git a/vendor/github.com/urfave/cli/v2/flag_string.go b/vendor/github.com/urfave/cli/v2/flag_string.go index 400bb532e..0f73e0621 100644 --- a/vendor/github.com/urfave/cli/v2/flag_string.go +++ b/vendor/github.com/urfave/cli/v2/flag_string.go @@ -1,43 +1,9 @@ package cli -import "flag" - -// StringFlag is a flag with type string -type StringFlag struct { - Name string - Aliases []string - Usage string - EnvVars []string - FilePath string - Required bool - Hidden bool - TakesFile bool - Value string - DefaultText string - Destination *string - HasBeenSet bool -} - -// IsSet returns whether or not the flag has been set through env or file -func (f *StringFlag) IsSet() bool { - return f.HasBeenSet -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f *StringFlag) String() string { - return FlagStringer(f) -} - -// Names returns the names of the flag -func (f *StringFlag) Names() []string { - return flagNames(f.Name, f.Aliases) -} - -// IsRequired returns whether or not the flag is required -func (f *StringFlag) IsRequired() bool { - return f.Required -} +import ( + "flag" + "fmt" +) // TakesValue returns true of the flag takes a value, otherwise false func (f *StringFlag) TakesValue() bool { @@ -49,15 +15,45 @@ func (f *StringFlag) GetUsage() string { return f.Usage } +// GetCategory returns the category for the flag +func (f *StringFlag) GetCategory() string { + return f.Category +} + // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *StringFlag) GetValue() string { return f.Value } +// GetDefaultText returns the default text for this flag +func (f *StringFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + val := f.Value + if f.defaultValueSet { + val = f.defaultValue + } + + if val == "" { + return val + } + return fmt.Sprintf("%q", val) +} + +// GetEnvVars returns the env vars for this flag +func (f *StringFlag) GetEnvVars() []string { + return f.EnvVars +} + // Apply populates the flag given the flag set and environment func (f *StringFlag) Apply(set *flag.FlagSet) error { - if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + // set default value so that environment wont be able to overwrite it + f.defaultValue = f.Value + f.defaultValueSet = true + + if val, _, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { f.Value = val f.HasBeenSet = true } @@ -73,23 +69,32 @@ func (f *StringFlag) Apply(set *flag.FlagSet) error { return nil } +// Get returns the flag’s value in the given Context. +func (f *StringFlag) Get(ctx *Context) string { + return ctx.String(f.Name) +} + +// RunAction executes flag action if set +func (f *StringFlag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.String(f.Name)) + } + + return nil +} + // String looks up the value of a local StringFlag, returns // "" if not found -func (c *Context) String(name string) string { - if fs := lookupFlagSet(name, c); fs != nil { +func (cCtx *Context) String(name string) string { + if fs := cCtx.lookupFlagSet(name); fs != nil { return lookupString(name, fs) } return "" } func lookupString(name string, set *flag.FlagSet) string { - f := set.Lookup(name) - if f != nil { - parsed, err := f.Value.String(), error(nil) - if err != nil { - return "" - } - return parsed + if f := set.Lookup(name); f != nil { + return f.Value.String() } return "" } diff --git a/vendor/github.com/urfave/cli/v2/flag_string_slice.go b/vendor/github.com/urfave/cli/v2/flag_string_slice.go index ac363bf60..28f4798f5 100644 --- a/vendor/github.com/urfave/cli/v2/flag_string_slice.go +++ b/vendor/github.com/urfave/cli/v2/flag_string_slice.go @@ -4,13 +4,16 @@ import ( "encoding/json" "flag" "fmt" + "strconv" "strings" ) // StringSlice wraps a []string to satisfy flag.Value type StringSlice struct { slice []string + separator separatorSpec hasBeenSet bool + keepSpace bool } // NewStringSlice creates a *StringSlice with default values @@ -18,6 +21,16 @@ func NewStringSlice(defaults ...string) *StringSlice { return &StringSlice{slice: append([]string{}, defaults...)} } +// clone allocate a copy of self object +func (s *StringSlice) clone() *StringSlice { + n := &StringSlice{ + slice: make([]string, len(s.slice)), + hasBeenSet: s.hasBeenSet, + } + copy(n.slice, s.slice) + return n +} + // Set appends the string value to the list of values func (s *StringSlice) Set(value string) error { if !s.hasBeenSet { @@ -32,11 +45,20 @@ func (s *StringSlice) Set(value string) error { return nil } - s.slice = append(s.slice, value) + for _, t := range s.separator.flagSplitMultiValues(value) { + if !s.keepSpace { + t = strings.TrimSpace(t) + } + s.slice = append(s.slice, t) + } return nil } +func (s *StringSlice) WithSeparatorSpec(spec separatorSpec) { + s.separator = spec +} + // String returns a readable representation of this value (for usage defaults) func (s *StringSlice) String() string { return fmt.Sprintf("%s", s.slice) @@ -58,43 +80,12 @@ func (s *StringSlice) Get() interface{} { return *s } -// StringSliceFlag is a flag with type *StringSlice -type StringSliceFlag struct { - Name string - Aliases []string - Usage string - EnvVars []string - FilePath string - Required bool - Hidden bool - TakesFile bool - Value *StringSlice - DefaultText string - HasBeenSet bool - Destination *StringSlice -} - -// IsSet returns whether or not the flag has been set through env or file -func (f *StringSliceFlag) IsSet() bool { - return f.HasBeenSet -} - // String returns a readable representation of this value // (for usage defaults) func (f *StringSliceFlag) String() string { return FlagStringer(f) } -// Names returns the names of the flag -func (f *StringSliceFlag) Names() []string { - return flagNames(f.Name, f.Aliases) -} - -// IsRequired returns whether or not the flag is required -func (f *StringSliceFlag) IsRequired() bool { - return f.Required -} - // TakesValue returns true of the flag takes a value, otherwise false func (f *StringSliceFlag) TakesValue() bool { return true @@ -105,47 +96,101 @@ func (f *StringSliceFlag) GetUsage() string { return f.Usage } +// GetCategory returns the category for the flag +func (f *StringSliceFlag) GetCategory() string { + return f.Category +} + // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *StringSliceFlag) GetValue() string { - if f.Value != nil { - return f.Value.String() + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, s := range f.Value.Value() { + if len(s) > 0 { + defaultVals = append(defaultVals, strconv.Quote(s)) + } + } + } + return strings.Join(defaultVals, ", ") +} + +// GetDefaultText returns the default text for this flag +func (f *StringSliceFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText } - return "" + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *StringSliceFlag) GetEnvVars() []string { + return f.EnvVars +} + +// IsSliceFlag implements DocGenerationSliceFlag. +func (f *StringSliceFlag) IsSliceFlag() bool { + return true } // Apply populates the flag given the flag set and environment func (f *StringSliceFlag) Apply(set *flag.FlagSet) error { - if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { - f.Value = &StringSlice{} - destination := f.Value - if f.Destination != nil { - destination = f.Destination - } + // apply any default + if f.Destination != nil && f.Value != nil { + f.Destination.slice = make([]string, len(f.Value.slice)) + copy(f.Destination.slice, f.Value.slice) + } + + // resolve setValue (what we will assign to the set) + var setValue *StringSlice + switch { + case f.Destination != nil: + setValue = f.Destination + case f.Value != nil: + setValue = f.Value.clone() + default: + setValue = new(StringSlice) + setValue.WithSeparatorSpec(f.separator) + } + + setValue.keepSpace = f.KeepSpace - for _, s := range strings.Split(val, ",") { - if err := destination.Set(strings.TrimSpace(s)); err != nil { - return fmt.Errorf("could not parse %q as string value for flag %s: %s", val, f.Name, err) + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { + for _, s := range f.separator.flagSplitMultiValues(val) { + if !f.KeepSpace { + s = strings.TrimSpace(s) + } + if err := setValue.Set(s); err != nil { + return fmt.Errorf("could not parse %q as string value from %s for flag %s: %s", val, source, f.Name, err) } } // Set this to false so that we reset the slice if we then set values from // flags that have already been set by the environment. - destination.hasBeenSet = false + setValue.hasBeenSet = false f.HasBeenSet = true } for _, name := range f.Names() { - if f.Value == nil { - f.Value = &StringSlice{} - } + set.Var(setValue, name, f.Usage) + } - if f.Destination != nil { - set.Var(f.Destination, name, f.Usage) - continue - } + return nil +} + +func (f *StringSliceFlag) WithSeparatorSpec(spec separatorSpec) { + f.separator = spec +} + +// Get returns the flag’s value in the given Context. +func (f *StringSliceFlag) Get(ctx *Context) []string { + return ctx.StringSlice(f.Name) +} - set.Var(f.Value, name, f.Usage) +// RunAction executes flag action if set +func (f *StringSliceFlag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.StringSlice(f.Name)) } return nil @@ -153,8 +198,8 @@ func (f *StringSliceFlag) Apply(set *flag.FlagSet) error { // StringSlice looks up the value of a local StringSliceFlag, returns // nil if not found -func (c *Context) StringSlice(name string) []string { - if fs := lookupFlagSet(name, c); fs != nil { +func (cCtx *Context) StringSlice(name string) []string { + if fs := cCtx.lookupFlagSet(name); fs != nil { return lookupStringSlice(name, fs) } return nil @@ -163,7 +208,7 @@ func (c *Context) StringSlice(name string) []string { func lookupStringSlice(name string, set *flag.FlagSet) []string { f := set.Lookup(name) if f != nil { - if slice, ok := f.Value.(*StringSlice); ok { + if slice, ok := unwrapFlagValue(f.Value).(*StringSlice); ok { return slice.Value() } } diff --git a/vendor/github.com/urfave/cli/v2/flag_timestamp.go b/vendor/github.com/urfave/cli/v2/flag_timestamp.go index 9fac1d1e2..b90123087 100644 --- a/vendor/github.com/urfave/cli/v2/flag_timestamp.go +++ b/vendor/github.com/urfave/cli/v2/flag_timestamp.go @@ -11,6 +11,7 @@ type Timestamp struct { timestamp *time.Time hasBeenSet bool layout string + location *time.Location } // Timestamp constructor @@ -31,9 +32,22 @@ func (t *Timestamp) SetLayout(layout string) { t.layout = layout } +// Set perceived timezone of the to-be parsed time string +func (t *Timestamp) SetLocation(loc *time.Location) { + t.location = loc +} + // Parses the string value to timestamp func (t *Timestamp) Set(value string) error { - timestamp, err := time.Parse(t.layout, value) + var timestamp time.Time + var err error + + if t.location != nil { + timestamp, err = time.ParseInLocation(t.layout, value, t.location) + } else { + timestamp, err = time.Parse(t.layout, value) + } + if err != nil { return err } @@ -58,40 +72,23 @@ func (t *Timestamp) Get() interface{} { return *t } -// TimestampFlag is a flag with type time -type TimestampFlag struct { - Name string - Aliases []string - Usage string - EnvVars []string - FilePath string - Required bool - Hidden bool - Layout string - Value *Timestamp - DefaultText string - HasBeenSet bool -} - -// IsSet returns whether or not the flag has been set through env or file -func (f *TimestampFlag) IsSet() bool { - return f.HasBeenSet -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f *TimestampFlag) String() string { - return FlagStringer(f) -} - -// Names returns the names of the flag -func (f *TimestampFlag) Names() []string { - return flagNames(f.Name, f.Aliases) -} - -// IsRequired returns whether or not the flag is required -func (f *TimestampFlag) IsRequired() bool { - return f.Required +// clone timestamp +func (t *Timestamp) clone() *Timestamp { + tc := &Timestamp{ + timestamp: nil, + hasBeenSet: t.hasBeenSet, + layout: t.layout, + location: nil, + } + if t.timestamp != nil { + tts := *t.timestamp + tc.timestamp = &tts + } + if t.location != nil { + loc := *t.location + tc.location = &loc + } + return tc } // TakesValue returns true of the flag takes a value, otherwise false @@ -104,39 +101,95 @@ func (f *TimestampFlag) GetUsage() string { return f.Usage } +// GetCategory returns the category for the flag +func (f *TimestampFlag) GetCategory() string { + return f.Category +} + // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *TimestampFlag) GetValue() string { - if f.Value != nil { + if f.Value != nil && f.Value.timestamp != nil { return f.Value.timestamp.String() } return "" } +// GetDefaultText returns the default text for this flag +func (f *TimestampFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + val := f.Value + if f.defaultValueSet { + val = f.defaultValue + } + + if val != nil && val.timestamp != nil { + return val.timestamp.String() + } + + return "" +} + +// GetEnvVars returns the env vars for this flag +func (f *TimestampFlag) GetEnvVars() []string { + return f.EnvVars +} + // Apply populates the flag given the flag set and environment func (f *TimestampFlag) Apply(set *flag.FlagSet) error { if f.Layout == "" { return fmt.Errorf("timestamp Layout is required") } - f.Value = &Timestamp{} + if f.Value == nil { + f.Value = &Timestamp{} + } f.Value.SetLayout(f.Layout) + f.Value.SetLocation(f.Timezone) - if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + f.defaultValue = f.Value.clone() + f.defaultValueSet = true + + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { if err := f.Value.Set(val); err != nil { - return fmt.Errorf("could not parse %q as timestamp value for flag %s: %s", val, f.Name, err) + return fmt.Errorf("could not parse %q as timestamp value from %s for flag %s: %s", val, source, f.Name, err) } f.HasBeenSet = true } + if f.Destination != nil { + *f.Destination = *f.Value + } + for _, name := range f.Names() { + if f.Destination != nil { + set.Var(f.Destination, name, f.Usage) + continue + } + set.Var(f.Value, name, f.Usage) } return nil } +// Get returns the flag’s value in the given Context. +func (f *TimestampFlag) Get(ctx *Context) *time.Time { + return ctx.Timestamp(f.Name) +} + +// RunAction executes flag action if set +func (f *TimestampFlag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.Timestamp(f.Name)) + } + + return nil +} + // Timestamp gets the timestamp from a flag name -func (c *Context) Timestamp(name string) *time.Time { - if fs := lookupFlagSet(name, c); fs != nil { +func (cCtx *Context) Timestamp(name string) *time.Time { + if fs := cCtx.lookupFlagSet(name); fs != nil { return lookupTimestamp(name, fs) } return nil diff --git a/vendor/github.com/urfave/cli/v2/flag_uint.go b/vendor/github.com/urfave/cli/v2/flag_uint.go index 2e5e76b0e..8d5b85458 100644 --- a/vendor/github.com/urfave/cli/v2/flag_uint.go +++ b/vendor/github.com/urfave/cli/v2/flag_uint.go @@ -6,42 +6,6 @@ import ( "strconv" ) -// UintFlag is a flag with type uint -type UintFlag struct { - Name string - Aliases []string - Usage string - EnvVars []string - FilePath string - Required bool - Hidden bool - Value uint - DefaultText string - Destination *uint - HasBeenSet bool -} - -// IsSet returns whether or not the flag has been set through env or file -func (f *UintFlag) IsSet() bool { - return f.HasBeenSet -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f *UintFlag) String() string { - return FlagStringer(f) -} - -// Names returns the names of the flag -func (f *UintFlag) Names() []string { - return flagNames(f.Name, f.Aliases) -} - -// IsRequired returns whether or not the flag is required -func (f *UintFlag) IsRequired() bool { - return f.Required -} - // TakesValue returns true of the flag takes a value, otherwise false func (f *UintFlag) TakesValue() bool { return true @@ -52,13 +16,22 @@ func (f *UintFlag) GetUsage() string { return f.Usage } +// GetCategory returns the category for the flag +func (f *UintFlag) GetCategory() string { + return f.Category +} + // Apply populates the flag given the flag set and environment func (f *UintFlag) Apply(set *flag.FlagSet) error { - if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + // set default value so that environment wont be able to overwrite it + f.defaultValue = f.Value + f.defaultValueSet = true + + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { if val != "" { - valInt, err := strconv.ParseUint(val, 0, 64) + valInt, err := strconv.ParseUint(val, f.Base, 64) if err != nil { - return fmt.Errorf("could not parse %q as uint value for flag %s: %s", val, f.Name, err) + return fmt.Errorf("could not parse %q as uint value from %s for flag %s: %s", val, source, f.Name, err) } f.Value = uint(valInt) @@ -77,16 +50,46 @@ func (f *UintFlag) Apply(set *flag.FlagSet) error { return nil } +// RunAction executes flag action if set +func (f *UintFlag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.Uint(f.Name)) + } + + return nil +} + // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *UintFlag) GetValue() string { return fmt.Sprintf("%d", f.Value) } +// GetDefaultText returns the default text for this flag +func (f *UintFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + if f.defaultValueSet { + return fmt.Sprintf("%d", f.defaultValue) + } + return fmt.Sprintf("%d", f.Value) +} + +// GetEnvVars returns the env vars for this flag +func (f *UintFlag) GetEnvVars() []string { + return f.EnvVars +} + +// Get returns the flag’s value in the given Context. +func (f *UintFlag) Get(ctx *Context) uint { + return ctx.Uint(f.Name) +} + // Uint looks up the value of a local UintFlag, returns // 0 if not found -func (c *Context) Uint(name string) uint { - if fs := lookupFlagSet(name, c); fs != nil { +func (cCtx *Context) Uint(name string) uint { + if fs := cCtx.lookupFlagSet(name); fs != nil { return lookupUint(name, fs) } return 0 diff --git a/vendor/github.com/urfave/cli/v2/flag_uint64.go b/vendor/github.com/urfave/cli/v2/flag_uint64.go index 8fc3289d8..c356e533b 100644 --- a/vendor/github.com/urfave/cli/v2/flag_uint64.go +++ b/vendor/github.com/urfave/cli/v2/flag_uint64.go @@ -6,42 +6,6 @@ import ( "strconv" ) -// Uint64Flag is a flag with type uint64 -type Uint64Flag struct { - Name string - Aliases []string - Usage string - EnvVars []string - FilePath string - Required bool - Hidden bool - Value uint64 - DefaultText string - Destination *uint64 - HasBeenSet bool -} - -// IsSet returns whether or not the flag has been set through env or file -func (f *Uint64Flag) IsSet() bool { - return f.HasBeenSet -} - -// String returns a readable representation of this value -// (for usage defaults) -func (f *Uint64Flag) String() string { - return FlagStringer(f) -} - -// Names returns the names of the flag -func (f *Uint64Flag) Names() []string { - return flagNames(f.Name, f.Aliases) -} - -// IsRequired returns whether or not the flag is required -func (f *Uint64Flag) IsRequired() bool { - return f.Required -} - // TakesValue returns true of the flag takes a value, otherwise false func (f *Uint64Flag) TakesValue() bool { return true @@ -52,13 +16,22 @@ func (f *Uint64Flag) GetUsage() string { return f.Usage } +// GetCategory returns the category for the flag +func (f *Uint64Flag) GetCategory() string { + return f.Category +} + // Apply populates the flag given the flag set and environment func (f *Uint64Flag) Apply(set *flag.FlagSet) error { - if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { + // set default value so that environment wont be able to overwrite it + f.defaultValue = f.Value + f.defaultValueSet = true + + if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found { if val != "" { - valInt, err := strconv.ParseUint(val, 0, 64) + valInt, err := strconv.ParseUint(val, f.Base, 64) if err != nil { - return fmt.Errorf("could not parse %q as uint64 value for flag %s: %s", val, f.Name, err) + return fmt.Errorf("could not parse %q as uint64 value from %s for flag %s: %s", val, source, f.Name, err) } f.Value = valInt @@ -77,16 +50,46 @@ func (f *Uint64Flag) Apply(set *flag.FlagSet) error { return nil } +// RunAction executes flag action if set +func (f *Uint64Flag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.Uint64(f.Name)) + } + + return nil +} + // GetValue returns the flags value as string representation and an empty // string if the flag takes no value at all. func (f *Uint64Flag) GetValue() string { return fmt.Sprintf("%d", f.Value) } +// GetDefaultText returns the default text for this flag +func (f *Uint64Flag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + if f.defaultValueSet { + return fmt.Sprintf("%d", f.defaultValue) + } + return fmt.Sprintf("%d", f.Value) +} + +// GetEnvVars returns the env vars for this flag +func (f *Uint64Flag) GetEnvVars() []string { + return f.EnvVars +} + +// Get returns the flag’s value in the given Context. +func (f *Uint64Flag) Get(ctx *Context) uint64 { + return ctx.Uint64(f.Name) +} + // Uint64 looks up the value of a local Uint64Flag, returns // 0 if not found -func (c *Context) Uint64(name string) uint64 { - if fs := lookupFlagSet(name, c); fs != nil { +func (cCtx *Context) Uint64(name string) uint64 { + if fs := cCtx.lookupFlagSet(name); fs != nil { return lookupUint64(name, fs) } return 0 diff --git a/vendor/github.com/urfave/cli/v2/flag_uint64_slice.go b/vendor/github.com/urfave/cli/v2/flag_uint64_slice.go new file mode 100644 index 000000000..d34201868 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_uint64_slice.go @@ -0,0 +1,219 @@ +package cli + +import ( + "encoding/json" + "flag" + "fmt" + "strconv" + "strings" +) + +// Uint64Slice wraps []int64 to satisfy flag.Value +type Uint64Slice struct { + slice []uint64 + separator separatorSpec + hasBeenSet bool +} + +// NewUint64Slice makes an *Uint64Slice with default values +func NewUint64Slice(defaults ...uint64) *Uint64Slice { + return &Uint64Slice{slice: append([]uint64{}, defaults...)} +} + +// clone allocate a copy of self object +func (i *Uint64Slice) clone() *Uint64Slice { + n := &Uint64Slice{ + slice: make([]uint64, len(i.slice)), + hasBeenSet: i.hasBeenSet, + } + copy(n.slice, i.slice) + return n +} + +// Set parses the value into an integer and appends it to the list of values +func (i *Uint64Slice) Set(value string) error { + if !i.hasBeenSet { + i.slice = []uint64{} + i.hasBeenSet = true + } + + if strings.HasPrefix(value, slPfx) { + // Deserializing assumes overwrite + _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &i.slice) + i.hasBeenSet = true + return nil + } + + for _, s := range i.separator.flagSplitMultiValues(value) { + tmp, err := strconv.ParseUint(strings.TrimSpace(s), 0, 64) + if err != nil { + return err + } + + i.slice = append(i.slice, tmp) + } + + return nil +} + +func (i *Uint64Slice) WithSeparatorSpec(spec separatorSpec) { + i.separator = spec +} + +// String returns a readable representation of this value (for usage defaults) +func (i *Uint64Slice) String() string { + v := i.slice + if v == nil { + // treat nil the same as zero length non-nil + v = make([]uint64, 0) + } + str := fmt.Sprintf("%d", v) + str = strings.Replace(str, " ", ", ", -1) + str = strings.Replace(str, "[", "{", -1) + str = strings.Replace(str, "]", "}", -1) + return fmt.Sprintf("[]uint64%s", str) +} + +// Serialize allows Uint64Slice to fulfill Serializer +func (i *Uint64Slice) Serialize() string { + jsonBytes, _ := json.Marshal(i.slice) + return fmt.Sprintf("%s%s", slPfx, string(jsonBytes)) +} + +// Value returns the slice of ints set by this flag +func (i *Uint64Slice) Value() []uint64 { + return i.slice +} + +// Get returns the slice of ints set by this flag +func (i *Uint64Slice) Get() interface{} { + return *i +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *Uint64SliceFlag) String() string { + return FlagStringer(f) +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *Uint64SliceFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *Uint64SliceFlag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *Uint64SliceFlag) GetCategory() string { + return f.Category +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *Uint64SliceFlag) GetValue() string { + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strconv.FormatUint(i, 10)) + } + } + return strings.Join(defaultVals, ", ") +} + +// GetDefaultText returns the default text for this flag +func (f *Uint64SliceFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *Uint64SliceFlag) GetEnvVars() []string { + return f.EnvVars +} + +// IsSliceFlag implements DocGenerationSliceFlag. +func (f *Uint64SliceFlag) IsSliceFlag() bool { + return true +} + +// Apply populates the flag given the flag set and environment +func (f *Uint64SliceFlag) Apply(set *flag.FlagSet) error { + // apply any default + if f.Destination != nil && f.Value != nil { + f.Destination.slice = make([]uint64, len(f.Value.slice)) + copy(f.Destination.slice, f.Value.slice) + } + + // resolve setValue (what we will assign to the set) + var setValue *Uint64Slice + switch { + case f.Destination != nil: + setValue = f.Destination + case f.Value != nil: + setValue = f.Value.clone() + default: + setValue = new(Uint64Slice) + setValue.WithSeparatorSpec(f.separator) + } + + if val, source, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok && val != "" { + for _, s := range f.separator.flagSplitMultiValues(val) { + if err := setValue.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as uint64 slice value from %s for flag %s: %s", val, source, f.Name, err) + } + } + + // Set this to false so that we reset the slice if we then set values from + // flags that have already been set by the environment. + setValue.hasBeenSet = false + f.HasBeenSet = true + } + + for _, name := range f.Names() { + set.Var(setValue, name, f.Usage) + } + + return nil +} + +func (f *Uint64SliceFlag) WithSeparatorSpec(spec separatorSpec) { + f.separator = spec +} + +// Get returns the flag’s value in the given Context. +func (f *Uint64SliceFlag) Get(ctx *Context) []uint64 { + return ctx.Uint64Slice(f.Name) +} + +// RunAction executes flag action if set +func (f *Uint64SliceFlag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.Uint64Slice(f.Name)) + } + + return nil +} + +// Uint64Slice looks up the value of a local Uint64SliceFlag, returns +// nil if not found +func (cCtx *Context) Uint64Slice(name string) []uint64 { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupUint64Slice(name, fs) + } + return nil +} + +func lookupUint64Slice(name string, set *flag.FlagSet) []uint64 { + f := set.Lookup(name) + if f != nil { + if slice, ok := unwrapFlagValue(f.Value).(*Uint64Slice); ok { + return slice.Value() + } + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/flag_uint_slice.go b/vendor/github.com/urfave/cli/v2/flag_uint_slice.go new file mode 100644 index 000000000..4dc13e126 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/flag_uint_slice.go @@ -0,0 +1,230 @@ +package cli + +import ( + "encoding/json" + "flag" + "fmt" + "strconv" + "strings" +) + +// UintSlice wraps []int to satisfy flag.Value +type UintSlice struct { + slice []uint + separator separatorSpec + hasBeenSet bool +} + +// NewUintSlice makes an *UintSlice with default values +func NewUintSlice(defaults ...uint) *UintSlice { + return &UintSlice{slice: append([]uint{}, defaults...)} +} + +// clone allocate a copy of self object +func (i *UintSlice) clone() *UintSlice { + n := &UintSlice{ + slice: make([]uint, len(i.slice)), + hasBeenSet: i.hasBeenSet, + } + copy(n.slice, i.slice) + return n +} + +// TODO: Consistently have specific Set function for Int64 and Float64 ? +// SetInt directly adds an integer to the list of values +func (i *UintSlice) SetUint(value uint) { + if !i.hasBeenSet { + i.slice = []uint{} + i.hasBeenSet = true + } + + i.slice = append(i.slice, value) +} + +// Set parses the value into an integer and appends it to the list of values +func (i *UintSlice) Set(value string) error { + if !i.hasBeenSet { + i.slice = []uint{} + i.hasBeenSet = true + } + + if strings.HasPrefix(value, slPfx) { + // Deserializing assumes overwrite + _ = json.Unmarshal([]byte(strings.Replace(value, slPfx, "", 1)), &i.slice) + i.hasBeenSet = true + return nil + } + + for _, s := range i.separator.flagSplitMultiValues(value) { + tmp, err := strconv.ParseUint(strings.TrimSpace(s), 0, 32) + if err != nil { + return err + } + + i.slice = append(i.slice, uint(tmp)) + } + + return nil +} + +func (i *UintSlice) WithSeparatorSpec(spec separatorSpec) { + i.separator = spec +} + +// String returns a readable representation of this value (for usage defaults) +func (i *UintSlice) String() string { + v := i.slice + if v == nil { + // treat nil the same as zero length non-nil + v = make([]uint, 0) + } + str := fmt.Sprintf("%d", v) + str = strings.Replace(str, " ", ", ", -1) + str = strings.Replace(str, "[", "{", -1) + str = strings.Replace(str, "]", "}", -1) + return fmt.Sprintf("[]uint%s", str) +} + +// Serialize allows UintSlice to fulfill Serializer +func (i *UintSlice) Serialize() string { + jsonBytes, _ := json.Marshal(i.slice) + return fmt.Sprintf("%s%s", slPfx, string(jsonBytes)) +} + +// Value returns the slice of ints set by this flag +func (i *UintSlice) Value() []uint { + return i.slice +} + +// Get returns the slice of ints set by this flag +func (i *UintSlice) Get() interface{} { + return *i +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f *UintSliceFlag) String() string { + return FlagStringer(f) +} + +// TakesValue returns true of the flag takes a value, otherwise false +func (f *UintSliceFlag) TakesValue() bool { + return true +} + +// GetUsage returns the usage string for the flag +func (f *UintSliceFlag) GetUsage() string { + return f.Usage +} + +// GetCategory returns the category for the flag +func (f *UintSliceFlag) GetCategory() string { + return f.Category +} + +// GetValue returns the flags value as string representation and an empty +// string if the flag takes no value at all. +func (f *UintSliceFlag) GetValue() string { + var defaultVals []string + if f.Value != nil && len(f.Value.Value()) > 0 { + for _, i := range f.Value.Value() { + defaultVals = append(defaultVals, strconv.FormatUint(uint64(i), 10)) + } + } + return strings.Join(defaultVals, ", ") +} + +// GetDefaultText returns the default text for this flag +func (f *UintSliceFlag) GetDefaultText() string { + if f.DefaultText != "" { + return f.DefaultText + } + return f.GetValue() +} + +// GetEnvVars returns the env vars for this flag +func (f *UintSliceFlag) GetEnvVars() []string { + return f.EnvVars +} + +// IsSliceFlag implements DocGenerationSliceFlag. +func (f *UintSliceFlag) IsSliceFlag() bool { + return true +} + +// Apply populates the flag given the flag set and environment +func (f *UintSliceFlag) Apply(set *flag.FlagSet) error { + // apply any default + if f.Destination != nil && f.Value != nil { + f.Destination.slice = make([]uint, len(f.Value.slice)) + copy(f.Destination.slice, f.Value.slice) + } + + // resolve setValue (what we will assign to the set) + var setValue *UintSlice + switch { + case f.Destination != nil: + setValue = f.Destination + case f.Value != nil: + setValue = f.Value.clone() + default: + setValue = new(UintSlice) + setValue.WithSeparatorSpec(f.separator) + } + + if val, source, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok && val != "" { + for _, s := range f.separator.flagSplitMultiValues(val) { + if err := setValue.Set(strings.TrimSpace(s)); err != nil { + return fmt.Errorf("could not parse %q as uint slice value from %s for flag %s: %s", val, source, f.Name, err) + } + } + + // Set this to false so that we reset the slice if we then set values from + // flags that have already been set by the environment. + setValue.hasBeenSet = false + f.HasBeenSet = true + } + + for _, name := range f.Names() { + set.Var(setValue, name, f.Usage) + } + + return nil +} + +func (f *UintSliceFlag) WithSeparatorSpec(spec separatorSpec) { + f.separator = spec +} + +// Get returns the flag’s value in the given Context. +func (f *UintSliceFlag) Get(ctx *Context) []uint { + return ctx.UintSlice(f.Name) +} + +// RunAction executes flag action if set +func (f *UintSliceFlag) RunAction(c *Context) error { + if f.Action != nil { + return f.Action(c, c.UintSlice(f.Name)) + } + + return nil +} + +// UintSlice looks up the value of a local UintSliceFlag, returns +// nil if not found +func (cCtx *Context) UintSlice(name string) []uint { + if fs := cCtx.lookupFlagSet(name); fs != nil { + return lookupUintSlice(name, fs) + } + return nil +} + +func lookupUintSlice(name string, set *flag.FlagSet) []uint { + f := set.Lookup(name) + if f != nil { + if slice, ok := unwrapFlagValue(f.Value).(*UintSlice); ok { + return slice.Value() + } + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/funcs.go b/vendor/github.com/urfave/cli/v2/funcs.go index 474c48faf..e77b0d0a1 100644 --- a/vendor/github.com/urfave/cli/v2/funcs.go +++ b/vendor/github.com/urfave/cli/v2/funcs.go @@ -17,15 +17,18 @@ type ActionFunc func(*Context) error // CommandNotFoundFunc is executed if the proper command cannot be found type CommandNotFoundFunc func(*Context, string) -// OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying +// OnUsageErrorFunc is executed if a usage error occurs. This is useful for displaying // customized usage error messages. This function is able to replace the // original error messages. If this function is not set, the "Incorrect usage" // is displayed and the execution is interrupted. -type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error +type OnUsageErrorFunc func(cCtx *Context, err error, isSubcommand bool) error + +// InvalidFlagAccessFunc is executed when an invalid flag is accessed from the context. +type InvalidFlagAccessFunc func(*Context, string) // ExitErrHandlerFunc is executed if provided in order to handle exitError values // returned by Actions and Before/After functions. -type ExitErrHandlerFunc func(context *Context, err error) +type ExitErrHandlerFunc func(cCtx *Context, err error) // FlagStringFunc is used by the help generation to display a flag, which is // expected to be a single line. diff --git a/vendor/github.com/urfave/cli/v2/godoc-current.txt b/vendor/github.com/urfave/cli/v2/godoc-current.txt new file mode 100644 index 000000000..4b620feeb --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/godoc-current.txt @@ -0,0 +1,2724 @@ +package cli // import "github.com/urfave/cli/v2" + +Package cli provides a minimal framework for creating and organizing command +line Go applications. cli is designed to be easy to understand and write, +the most simple cli application can be written as follows: + + func main() { + (&cli.App{}).Run(os.Args) + } + +Of course this application does not do much, so let's make this an actual +application: + + func main() { + app := &cli.App{ + Name: "greet", + Usage: "say a greeting", + Action: func(c *cli.Context) error { + fmt.Println("Greetings") + return nil + }, + } + + app.Run(os.Args) + } + +VARIABLES + +var ( + SuggestFlag SuggestFlagFunc = nil // initialized in suggestions.go unless built with urfave_cli_no_suggest + SuggestCommand SuggestCommandFunc = nil // initialized in suggestions.go unless built with urfave_cli_no_suggest + SuggestDidYouMeanTemplate string = suggestDidYouMeanTemplate +) +var AppHelpTemplate = `NAME: + {{template "helpNameTemplate" .}} + +USAGE: + {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}{{if .Args}}[arguments...]{{end}}{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} + +VERSION: + {{.Version}}{{end}}{{end}}{{if .Description}} + +DESCRIPTION: + {{template "descriptionTemplate" .}}{{end}} +{{- if len .Authors}} + +AUTHOR{{template "authorsTemplate" .}}{{end}}{{if .VisibleCommands}} + +COMMANDS:{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}} + +GLOBAL OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} + +GLOBAL OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}{{if .Copyright}} + +COPYRIGHT: + {{template "copyrightTemplate" .}}{{end}} +` + AppHelpTemplate is the text template for the Default help topic. cli.go + uses text/template to render templates. You can render custom help text by + setting this variable. + +var CommandHelpTemplate = `NAME: + {{template "helpNameTemplate" .}} + +USAGE: + {{template "usageTemplate" .}}{{if .Category}} + +CATEGORY: + {{.Category}}{{end}}{{if .Description}} + +DESCRIPTION: + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleFlagCategories}} + +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} + +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}} +` + CommandHelpTemplate is the text template for the command help topic. cli.go + uses text/template to render templates. You can render custom help text by + setting this variable. + +var ErrWriter io.Writer = os.Stderr + ErrWriter is used to write errors to the user. This can be anything + implementing the io.Writer interface and defaults to os.Stderr. + +var FishCompletionTemplate = `# {{ .App.Name }} fish shell completion + +function __fish_{{ .App.Name }}_no_subcommand --description 'Test if there has been any subcommand yet' + for i in (commandline -opc) + if contains -- $i{{ range $v := .AllCommands }} {{ $v }}{{ end }} + return 1 + end + end + return 0 +end + +{{ range $v := .Completions }}{{ $v }} +{{ end }}` +var MarkdownDocTemplate = `{{if gt .SectionNum 0}}% {{ .App.Name }} {{ .SectionNum }} + +{{end}}# NAME + +{{ .App.Name }}{{ if .App.Usage }} - {{ .App.Usage }}{{ end }} + +# SYNOPSIS + +{{ .App.Name }} +{{ if .SynopsisArgs }} +` + "```" + ` +{{ range $v := .SynopsisArgs }}{{ $v }}{{ end }}` + "```" + ` +{{ end }}{{ if .App.Description }} +# DESCRIPTION + +{{ .App.Description }} +{{ end }} +**Usage**: + +` + "```" + `{{ if .App.UsageText }} +{{ .App.UsageText }} +{{ else }} +{{ .App.Name }} [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] +{{ end }}` + "```" + ` +{{ if .GlobalArgs }} +# GLOBAL OPTIONS +{{ range $v := .GlobalArgs }} +{{ $v }}{{ end }} +{{ end }}{{ if .Commands }} +# COMMANDS +{{ range $v := .Commands }} +{{ $v }}{{ end }}{{ end }}` +var OsExiter = os.Exit + OsExiter is the function used when the app exits. If not set defaults to + os.Exit. + +var SubcommandHelpTemplate = `NAME: + {{template "helpNameTemplate" .}} + +USAGE: + {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}{{if .Args}}[arguments...]{{end}}{{end}}{{end}}{{if .Description}} + +DESCRIPTION: + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}} + +COMMANDS:{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}} + +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} + +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}} +` + SubcommandHelpTemplate is the text template for the subcommand help topic. + cli.go uses text/template to render templates. You can render custom help + text by setting this variable. + +var VersionPrinter = printVersion + VersionPrinter prints the version for the App + +var HelpPrinter helpPrinter = printHelp + HelpPrinter is a function that writes the help output. If not set + explicitly, this calls HelpPrinterCustom using only the default template + functions. + + If custom logic for printing help is required, this function can be + overridden. If the ExtraInfo field is defined on an App, this function + should not be modified, as HelpPrinterCustom will be used directly in order + to capture the extra information. + +var HelpPrinterCustom helpPrinterCustom = printHelpCustom + HelpPrinterCustom is a function that writes the help output. It is used as + the default implementation of HelpPrinter, and may be called directly if the + ExtraInfo field is set on an App. + + In the default implementation, if the customFuncs argument contains a + "wrapAt" key, which is a function which takes no arguments and returns an + int, this int value will be used to produce a "wrap" function used by the + default template to wrap long lines. + + +FUNCTIONS + +func DefaultAppComplete(cCtx *Context) + DefaultAppComplete prints the list of subcommands as the default app + completion method + +func DefaultCompleteWithFlags(cmd *Command) func(cCtx *Context) +func FlagNames(name string, aliases []string) []string +func HandleAction(action interface{}, cCtx *Context) (err error) + HandleAction attempts to figure out which Action signature was used. + If it's an ActionFunc or a func with the legacy signature for Action, + the func is run! + +func HandleExitCoder(err error) + HandleExitCoder handles errors implementing ExitCoder by printing their + message and calling OsExiter with the given exit code. + + If the given error instead implements MultiError, each error will be checked + for the ExitCoder interface, and OsExiter will be called with the last exit + code found, or exit code 1 if no ExitCoder is found. + + This function is the default error-handling behavior for an App. + +func ShowAppHelp(cCtx *Context) error + ShowAppHelp is an action that displays the help. + +func ShowAppHelpAndExit(c *Context, exitCode int) + ShowAppHelpAndExit - Prints the list of subcommands for the app and exits + with exit code. + +func ShowCommandCompletions(ctx *Context, command string) + ShowCommandCompletions prints the custom completions for a given command + +func ShowCommandHelp(ctx *Context, command string) error + ShowCommandHelp prints help for the given command + +func ShowCommandHelpAndExit(c *Context, command string, code int) + ShowCommandHelpAndExit - exits with code after showing help + +func ShowCompletions(cCtx *Context) + ShowCompletions prints the lists of commands within a given context + +func ShowSubcommandHelp(cCtx *Context) error + ShowSubcommandHelp prints help for the given subcommand + +func ShowSubcommandHelpAndExit(c *Context, exitCode int) + ShowSubcommandHelpAndExit - Prints help for the given subcommand and exits + with exit code. + +func ShowVersion(cCtx *Context) + ShowVersion prints the version number of the App + + +TYPES + +type ActionFunc func(*Context) error + ActionFunc is the action to execute when no subcommands are specified + +type ActionableFlag interface { + Flag + RunAction(*Context) error +} + ActionableFlag is an interface that wraps Flag interface and RunAction + operation. + +type AfterFunc func(*Context) error + AfterFunc is an action to execute after any subcommands are run, but after + the subcommand has finished it is run even if Action() panics + +type App struct { + // The name of the program. Defaults to path.Base(os.Args[0]) + Name string + // Full name of command for help, defaults to Name + HelpName string + // Description of the program. + Usage string + // Text to override the USAGE section of help + UsageText string + // Whether this command supports arguments + Args bool + // Description of the program argument format. + ArgsUsage string + // Version of the program + Version string + // Description of the program + Description string + // DefaultCommand is the (optional) name of a command + // to run if no command names are passed as CLI arguments. + DefaultCommand string + // List of commands to execute + Commands []*Command + // List of flags to parse + Flags []Flag + // Boolean to enable bash completion commands + EnableBashCompletion bool + // Boolean to hide built-in help command and help flag + HideHelp bool + // Boolean to hide built-in help command but keep help flag. + // Ignored if HideHelp is true. + HideHelpCommand bool + // Boolean to hide built-in version flag and the VERSION section of help + HideVersion bool + + // An action to execute when the shell completion flag is set + BashComplete BashCompleteFunc + // An action to execute before any subcommands are run, but after the context is ready + // If a non-nil error is returned, no subcommands are run + Before BeforeFunc + // An action to execute after any subcommands are run, but after the subcommand has finished + // It is run even if Action() panics + After AfterFunc + // The action to execute when no subcommands are specified + Action ActionFunc + // Execute this function if the proper command cannot be found + CommandNotFound CommandNotFoundFunc + // Execute this function if a usage error occurs + OnUsageError OnUsageErrorFunc + // Execute this function when an invalid flag is accessed from the context + InvalidFlagAccessHandler InvalidFlagAccessFunc + // Compilation date + Compiled time.Time + // List of all authors who contributed + Authors []*Author + // Copyright of the binary if any + Copyright string + // Reader reader to write input to (useful for tests) + Reader io.Reader + // Writer writer to write output to + Writer io.Writer + // ErrWriter writes error output + ErrWriter io.Writer + // ExitErrHandler processes any error encountered while running an App before + // it is returned to the caller. If no function is provided, HandleExitCoder + // is used as the default behavior. + ExitErrHandler ExitErrHandlerFunc + // Other custom info + Metadata map[string]interface{} + // Carries a function which returns app specific info. + ExtraInfo func() map[string]string + // CustomAppHelpTemplate the text template for app help topic. + // cli.go uses text/template to render templates. You can + // render custom help text by setting this variable. + CustomAppHelpTemplate string + // SliceFlagSeparator is used to customize the separator for SliceFlag, the default is "," + SliceFlagSeparator string + // DisableSliceFlagSeparator is used to disable SliceFlagSeparator, the default is false + DisableSliceFlagSeparator bool + // Boolean to enable short-option handling so user can combine several + // single-character bool arguments into one + // i.e. foobar -o -v -> foobar -ov + UseShortOptionHandling bool + // Enable suggestions for commands and flags + Suggest bool + // Allows global flags set by libraries which use flag.XXXVar(...) directly + // to be parsed through this library + AllowExtFlags bool + // Treat all flags as normal arguments if true + SkipFlagParsing bool + + // Has unexported fields. +} + App is the main structure of a cli application. It is recommended that an + app be created with the cli.NewApp() function + +func NewApp() *App + NewApp creates a new cli Application with some reasonable defaults for Name, + Usage, Version and Action. + +func (a *App) Command(name string) *Command + Command returns the named command on App. Returns nil if the command does + not exist + +func (a *App) Run(arguments []string) (err error) + Run is the entry point to the cli app. Parses the arguments slice and routes + to the proper flag/args combination + +func (a *App) RunAndExitOnError() + RunAndExitOnError calls .Run() and exits non-zero if an error was returned + + Deprecated: instead you should return an error that fulfills cli.ExitCoder + to cli.App.Run. This will cause the application to exit with the given error + code in the cli.ExitCoder + +func (a *App) RunAsSubcommand(ctx *Context) (err error) + RunAsSubcommand is for legacy/compatibility purposes only. New code should + only use App.RunContext. This function is slated to be removed in v3. + +func (a *App) RunContext(ctx context.Context, arguments []string) (err error) + RunContext is like Run except it takes a Context that will be passed to + its commands and sub-commands. Through this, you can propagate timeouts and + cancellation requests + +func (a *App) Setup() + Setup runs initialization code to ensure all data structures are ready + for `Run` or inspection prior to `Run`. It is internally called by `Run`, + but will return early if setup has already happened. + +func (a *App) ToFishCompletion() (string, error) + ToFishCompletion creates a fish completion string for the `*App` The + function errors if either parsing or writing of the string fails. + +func (a *App) ToMan() (string, error) + ToMan creates a man page string for the `*App` The function errors if either + parsing or writing of the string fails. + +func (a *App) ToManWithSection(sectionNumber int) (string, error) + ToMan creates a man page string with section number for the `*App` The + function errors if either parsing or writing of the string fails. + +func (a *App) ToMarkdown() (string, error) + ToMarkdown creates a markdown string for the `*App` The function errors if + either parsing or writing of the string fails. + +func (a *App) VisibleCategories() []CommandCategory + VisibleCategories returns a slice of categories and commands that are + Hidden=false + +func (a *App) VisibleCommands() []*Command + VisibleCommands returns a slice of the Commands with Hidden=false + +func (a *App) VisibleFlagCategories() []VisibleFlagCategory + VisibleFlagCategories returns a slice containing all the categories with the + flags they contain + +func (a *App) VisibleFlags() []Flag + VisibleFlags returns a slice of the Flags with Hidden=false + +type Args interface { + // Get returns the nth argument, or else a blank string + Get(n int) string + // First returns the first argument, or else a blank string + First() string + // Tail returns the rest of the arguments (not the first one) + // or else an empty string slice + Tail() []string + // Len returns the length of the wrapped slice + Len() int + // Present checks if there are any arguments present + Present() bool + // Slice returns a copy of the internal slice + Slice() []string +} + +type Author struct { + Name string // The Authors name + Email string // The Authors email +} + Author represents someone who has contributed to a cli project. + +func (a *Author) String() string + String makes Author comply to the Stringer interface, to allow an easy print + in the templating process + +type BashCompleteFunc func(*Context) + BashCompleteFunc is an action to execute when the shell completion flag is + set + +type BeforeFunc func(*Context) error + BeforeFunc is an action to execute before any subcommands are run, but after + the context is ready if a non-nil error is returned, no subcommands are run + +type BoolFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value bool + Destination *bool + + Aliases []string + EnvVars []string + + Count *int + + DisableDefaultText bool + + Action func(*Context, bool) error + // Has unexported fields. +} + BoolFlag is a flag with type bool + +func (f *BoolFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *BoolFlag) Get(ctx *Context) bool + Get returns the flag’s value in the given Context. + +func (f *BoolFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *BoolFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *BoolFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *BoolFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *BoolFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *BoolFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *BoolFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *BoolFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *BoolFlag) Names() []string + Names returns the names of the flag + +func (f *BoolFlag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *BoolFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *BoolFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type CategorizableFlag interface { + VisibleFlag + + GetCategory() string +} + CategorizableFlag is an interface that allows us to potentially use a flag + in a categorized representation. + +type Command struct { + // The name of the command + Name string + // A list of aliases for the command + Aliases []string + // A short description of the usage of this command + Usage string + // Custom text to show on USAGE section of help + UsageText string + // A longer explanation of how the command works + Description string + // Whether this command supports arguments + Args bool + // A short description of the arguments of this command + ArgsUsage string + // The category the command is part of + Category string + // The function to call when checking for bash command completions + BashComplete BashCompleteFunc + // An action to execute before any sub-subcommands are run, but after the context is ready + // If a non-nil error is returned, no sub-subcommands are run + Before BeforeFunc + // An action to execute after any subcommands are run, but after the subcommand has finished + // It is run even if Action() panics + After AfterFunc + // The function to call when this command is invoked + Action ActionFunc + // Execute this function if a usage error occurs. + OnUsageError OnUsageErrorFunc + // List of child commands + Subcommands []*Command + // List of flags to parse + Flags []Flag + + // Treat all flags as normal arguments if true + SkipFlagParsing bool + // Boolean to hide built-in help command and help flag + HideHelp bool + // Boolean to hide built-in help command but keep help flag + // Ignored if HideHelp is true. + HideHelpCommand bool + // Boolean to hide this command from help or completion + Hidden bool + // Boolean to enable short-option handling so user can combine several + // single-character bool arguments into one + // i.e. foobar -o -v -> foobar -ov + UseShortOptionHandling bool + + // Full name of command for help, defaults to full command name, including parent commands. + HelpName string + + // CustomHelpTemplate the text template for the command help topic. + // cli.go uses text/template to render templates. You can + // render custom help text by setting this variable. + CustomHelpTemplate string + + // Has unexported fields. +} + Command is a subcommand for a cli.App. + +func (cmd *Command) Command(name string) *Command + +func (c *Command) FullName() string + FullName returns the full name of the command. For subcommands this ensures + that parent commands are part of the command path + +func (c *Command) HasName(name string) bool + HasName returns true if Command.Name matches given name + +func (c *Command) Names() []string + Names returns the names including short names and aliases. + +func (c *Command) Run(cCtx *Context, arguments ...string) (err error) + +func (c *Command) VisibleCategories() []CommandCategory + VisibleCategories returns a slice of categories and commands that are + Hidden=false + +func (c *Command) VisibleCommands() []*Command + VisibleCommands returns a slice of the Commands with Hidden=false + +func (c *Command) VisibleFlagCategories() []VisibleFlagCategory + VisibleFlagCategories returns a slice containing all the visible flag + categories with the flags they contain + +func (c *Command) VisibleFlags() []Flag + VisibleFlags returns a slice of the Flags with Hidden=false + +type CommandCategories interface { + // AddCommand adds a command to a category, creating a new category if necessary. + AddCommand(category string, command *Command) + // Categories returns a slice of categories sorted by name + Categories() []CommandCategory +} + CommandCategories interface allows for category manipulation + +type CommandCategory interface { + // Name returns the category name string + Name() string + // VisibleCommands returns a slice of the Commands with Hidden=false + VisibleCommands() []*Command +} + CommandCategory is a category containing commands. + +type CommandNotFoundFunc func(*Context, string) + CommandNotFoundFunc is executed if the proper command cannot be found + +type Commands []*Command + +type CommandsByName []*Command + +func (c CommandsByName) Len() int + +func (c CommandsByName) Less(i, j int) bool + +func (c CommandsByName) Swap(i, j int) + +type Context struct { + context.Context + App *App + Command *Command + + // Has unexported fields. +} + Context is a type that is passed through to each Handler action in a cli + application. Context can be used to retrieve context-specific args and + parsed command-line options. + +func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context + NewContext creates a new context. For use in when invoking an App or Command + action. + +func (cCtx *Context) Args() Args + Args returns the command line arguments associated with the context. + +func (cCtx *Context) Bool(name string) bool + Bool looks up the value of a local BoolFlag, returns false if not found + +func (cCtx *Context) Count(name string) int + Count returns the num of occurrences of this flag + +func (cCtx *Context) Duration(name string) time.Duration + Duration looks up the value of a local DurationFlag, returns 0 if not found + +func (cCtx *Context) FlagNames() []string + FlagNames returns a slice of flag names used by the this context and all of + its parent contexts. + +func (cCtx *Context) Float64(name string) float64 + Float64 looks up the value of a local Float64Flag, returns 0 if not found + +func (cCtx *Context) Float64Slice(name string) []float64 + Float64Slice looks up the value of a local Float64SliceFlag, returns nil if + not found + +func (cCtx *Context) Generic(name string) interface{} + Generic looks up the value of a local GenericFlag, returns nil if not found + +func (cCtx *Context) Int(name string) int + Int looks up the value of a local IntFlag, returns 0 if not found + +func (cCtx *Context) Int64(name string) int64 + Int64 looks up the value of a local Int64Flag, returns 0 if not found + +func (cCtx *Context) Int64Slice(name string) []int64 + Int64Slice looks up the value of a local Int64SliceFlag, returns nil if not + found + +func (cCtx *Context) IntSlice(name string) []int + IntSlice looks up the value of a local IntSliceFlag, returns nil if not + found + +func (cCtx *Context) IsSet(name string) bool + IsSet determines if the flag was actually set + +func (cCtx *Context) Lineage() []*Context + Lineage returns *this* context and all of its ancestor contexts in order + from child to parent + +func (cCtx *Context) LocalFlagNames() []string + LocalFlagNames returns a slice of flag names used in this context. + +func (cCtx *Context) NArg() int + NArg returns the number of the command line arguments. + +func (cCtx *Context) NumFlags() int + NumFlags returns the number of flags set + +func (cCtx *Context) Path(name string) string + Path looks up the value of a local PathFlag, returns "" if not found + +func (cCtx *Context) Set(name, value string) error + Set sets a context flag to a value. + +func (cCtx *Context) String(name string) string + String looks up the value of a local StringFlag, returns "" if not found + +func (cCtx *Context) StringSlice(name string) []string + StringSlice looks up the value of a local StringSliceFlag, returns nil if + not found + +func (cCtx *Context) Timestamp(name string) *time.Time + Timestamp gets the timestamp from a flag name + +func (cCtx *Context) Uint(name string) uint + Uint looks up the value of a local UintFlag, returns 0 if not found + +func (cCtx *Context) Uint64(name string) uint64 + Uint64 looks up the value of a local Uint64Flag, returns 0 if not found + +func (cCtx *Context) Uint64Slice(name string) []uint64 + Uint64Slice looks up the value of a local Uint64SliceFlag, returns nil if + not found + +func (cCtx *Context) UintSlice(name string) []uint + UintSlice looks up the value of a local UintSliceFlag, returns nil if not + found + +func (cCtx *Context) Value(name string) interface{} + Value returns the value of the flag corresponding to `name` + +type Countable interface { + Count() int +} + Countable is an interface to enable detection of flag values which support + repetitive flags + +type DocGenerationFlag interface { + Flag + + // TakesValue returns true if the flag takes a value, otherwise false + TakesValue() bool + + // GetUsage returns the usage string for the flag + GetUsage() string + + // GetValue returns the flags value as string representation and an empty + // string if the flag takes no value at all. + GetValue() string + + // GetDefaultText returns the default text for this flag + GetDefaultText() string + + // GetEnvVars returns the env vars for this flag + GetEnvVars() []string +} + DocGenerationFlag is an interface that allows documentation generation for + the flag + +type DocGenerationSliceFlag interface { + DocGenerationFlag + + // IsSliceFlag returns true for flags that can be given multiple times. + IsSliceFlag() bool +} + DocGenerationSliceFlag extends DocGenerationFlag for slice-based flags. + +type DurationFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value time.Duration + Destination *time.Duration + + Aliases []string + EnvVars []string + + Action func(*Context, time.Duration) error + // Has unexported fields. +} + DurationFlag is a flag with type time.Duration + +func (f *DurationFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *DurationFlag) Get(ctx *Context) time.Duration + Get returns the flag’s value in the given Context. + +func (f *DurationFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *DurationFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *DurationFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *DurationFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *DurationFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *DurationFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *DurationFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *DurationFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *DurationFlag) Names() []string + Names returns the names of the flag + +func (f *DurationFlag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *DurationFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *DurationFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type ErrorFormatter interface { + Format(s fmt.State, verb rune) +} + ErrorFormatter is the interface that will suitably format the error output + +type ExitCoder interface { + error + ExitCode() int +} + ExitCoder is the interface checked by `App` and `Command` for a custom exit + code + +func Exit(message interface{}, exitCode int) ExitCoder + Exit wraps a message and exit code into an error, which by default is + handled with a call to os.Exit during default error handling. + + This is the simplest way to trigger a non-zero exit code for an App + without having to call os.Exit manually. During testing, this behavior + can be avoided by overriding the ExitErrHandler function on an App or the + package-global OsExiter function. + +func NewExitError(message interface{}, exitCode int) ExitCoder + NewExitError calls Exit to create a new ExitCoder. + + Deprecated: This function is a duplicate of Exit and will eventually be + removed. + +type ExitErrHandlerFunc func(cCtx *Context, err error) + ExitErrHandlerFunc is executed if provided in order to handle exitError + values returned by Actions and Before/After functions. + +type Flag interface { + fmt.Stringer + // Apply Flag settings to the given flag set + Apply(*flag.FlagSet) error + Names() []string + IsSet() bool +} + Flag is a common interface related to parsing flags in cli. For more + advanced flag parsing techniques, it is recommended that this interface be + implemented. + +var BashCompletionFlag Flag = &BoolFlag{ + Name: "generate-bash-completion", + Hidden: true, +} + BashCompletionFlag enables bash-completion for all commands and subcommands + +var HelpFlag Flag = &BoolFlag{ + Name: "help", + Aliases: []string{"h"}, + Usage: "show help", + DisableDefaultText: true, +} + HelpFlag prints the help for all commands and subcommands. Set to nil to + disable the flag. The subcommand will still be added unless HideHelp or + HideHelpCommand is set to true. + +var VersionFlag Flag = &BoolFlag{ + Name: "version", + Aliases: []string{"v"}, + Usage: "print the version", + DisableDefaultText: true, +} + VersionFlag prints the version for the application + +type FlagCategories interface { + // AddFlags adds a flag to a category, creating a new category if necessary. + AddFlag(category string, fl Flag) + // VisibleCategories returns a slice of visible flag categories sorted by name + VisibleCategories() []VisibleFlagCategory +} + FlagCategories interface allows for category manipulation + +type FlagEnvHintFunc func(envVars []string, str string) string + FlagEnvHintFunc is used by the default FlagStringFunc to annotate flag help + with the environment variable details. + +var FlagEnvHinter FlagEnvHintFunc = withEnvHint + FlagEnvHinter annotates flag help message with the environment variable + details. This is used by the default FlagStringer. + +type FlagFileHintFunc func(filePath, str string) string + FlagFileHintFunc is used by the default FlagStringFunc to annotate flag help + with the file path details. + +var FlagFileHinter FlagFileHintFunc = withFileHint + FlagFileHinter annotates flag help message with the environment variable + details. This is used by the default FlagStringer. + +type FlagNamePrefixFunc func(fullName []string, placeholder string) string + FlagNamePrefixFunc is used by the default FlagStringFunc to create prefix + text for a flag's full name. + +var FlagNamePrefixer FlagNamePrefixFunc = prefixedNames + FlagNamePrefixer converts a full flag name and its placeholder into the help + message flag prefix. This is used by the default FlagStringer. + +type FlagStringFunc func(Flag) string + FlagStringFunc is used by the help generation to display a flag, which is + expected to be a single line. + +var FlagStringer FlagStringFunc = stringifyFlag + FlagStringer converts a flag definition to a string. This is used by help to + display a flag. + +type FlagsByName []Flag + FlagsByName is a slice of Flag. + +func (f FlagsByName) Len() int + +func (f FlagsByName) Less(i, j int) bool + +func (f FlagsByName) Swap(i, j int) + +type Float64Flag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value float64 + Destination *float64 + + Aliases []string + EnvVars []string + + Action func(*Context, float64) error + // Has unexported fields. +} + Float64Flag is a flag with type float64 + +func (f *Float64Flag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *Float64Flag) Get(ctx *Context) float64 + Get returns the flag’s value in the given Context. + +func (f *Float64Flag) GetCategory() string + GetCategory returns the category for the flag + +func (f *Float64Flag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *Float64Flag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *Float64Flag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *Float64Flag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *Float64Flag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *Float64Flag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *Float64Flag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *Float64Flag) Names() []string + Names returns the names of the flag + +func (f *Float64Flag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *Float64Flag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *Float64Flag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type Float64Slice struct { + // Has unexported fields. +} + Float64Slice wraps []float64 to satisfy flag.Value + +func NewFloat64Slice(defaults ...float64) *Float64Slice + NewFloat64Slice makes a *Float64Slice with default values + +func (f *Float64Slice) Get() interface{} + Get returns the slice of float64s set by this flag + +func (f *Float64Slice) Serialize() string + Serialize allows Float64Slice to fulfill Serializer + +func (f *Float64Slice) Set(value string) error + Set parses the value into a float64 and appends it to the list of values + +func (f *Float64Slice) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *Float64Slice) Value() []float64 + Value returns the slice of float64s set by this flag + +func (f *Float64Slice) WithSeparatorSpec(spec separatorSpec) + +type Float64SliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *Float64Slice + Destination *Float64Slice + + Aliases []string + EnvVars []string + + Action func(*Context, []float64) error + // Has unexported fields. +} + Float64SliceFlag is a flag with type *Float64Slice + +func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *Float64SliceFlag) Get(ctx *Context) []float64 + Get returns the flag’s value in the given Context. + +func (f *Float64SliceFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *Float64SliceFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *Float64SliceFlag) GetDestination() []float64 + +func (f *Float64SliceFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *Float64SliceFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *Float64SliceFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *Float64SliceFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *Float64SliceFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *Float64SliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + +func (f *Float64SliceFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *Float64SliceFlag) Names() []string + Names returns the names of the flag + +func (f *Float64SliceFlag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *Float64SliceFlag) SetDestination(slice []float64) + +func (f *Float64SliceFlag) SetValue(slice []float64) + +func (f *Float64SliceFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *Float64SliceFlag) TakesValue() bool + TakesValue returns true if the flag takes a value, otherwise false + +func (f *Float64SliceFlag) WithSeparatorSpec(spec separatorSpec) + +type Generic interface { + Set(value string) error + String() string +} + Generic is a generic parseable type identified by a specific flag + +type GenericFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value Generic + Destination Generic + + Aliases []string + EnvVars []string + + TakesFile bool + + Action func(*Context, interface{}) error + // Has unexported fields. +} + GenericFlag is a flag with type Generic + +func (f *GenericFlag) Apply(set *flag.FlagSet) error + Apply takes the flagset and calls Set on the generic flag with the value + provided by the user for parsing by the flag + +func (f *GenericFlag) Get(ctx *Context) interface{} + Get returns the flag’s value in the given Context. + +func (f *GenericFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *GenericFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *GenericFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *GenericFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *GenericFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *GenericFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *GenericFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *GenericFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *GenericFlag) Names() []string + Names returns the names of the flag + +func (f *GenericFlag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *GenericFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *GenericFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type Int64Flag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value int64 + Destination *int64 + + Aliases []string + EnvVars []string + + Base int + + Action func(*Context, int64) error + // Has unexported fields. +} + Int64Flag is a flag with type int64 + +func (f *Int64Flag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *Int64Flag) Get(ctx *Context) int64 + Get returns the flag’s value in the given Context. + +func (f *Int64Flag) GetCategory() string + GetCategory returns the category for the flag + +func (f *Int64Flag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *Int64Flag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *Int64Flag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *Int64Flag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *Int64Flag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *Int64Flag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *Int64Flag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *Int64Flag) Names() []string + Names returns the names of the flag + +func (f *Int64Flag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *Int64Flag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *Int64Flag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type Int64Slice struct { + // Has unexported fields. +} + Int64Slice wraps []int64 to satisfy flag.Value + +func NewInt64Slice(defaults ...int64) *Int64Slice + NewInt64Slice makes an *Int64Slice with default values + +func (i *Int64Slice) Get() interface{} + Get returns the slice of ints set by this flag + +func (i *Int64Slice) Serialize() string + Serialize allows Int64Slice to fulfill Serializer + +func (i *Int64Slice) Set(value string) error + Set parses the value into an integer and appends it to the list of values + +func (i *Int64Slice) String() string + String returns a readable representation of this value (for usage defaults) + +func (i *Int64Slice) Value() []int64 + Value returns the slice of ints set by this flag + +func (i *Int64Slice) WithSeparatorSpec(spec separatorSpec) + +type Int64SliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *Int64Slice + Destination *Int64Slice + + Aliases []string + EnvVars []string + + Action func(*Context, []int64) error + // Has unexported fields. +} + Int64SliceFlag is a flag with type *Int64Slice + +func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *Int64SliceFlag) Get(ctx *Context) []int64 + Get returns the flag’s value in the given Context. + +func (f *Int64SliceFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *Int64SliceFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *Int64SliceFlag) GetDestination() []int64 + +func (f *Int64SliceFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *Int64SliceFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *Int64SliceFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *Int64SliceFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *Int64SliceFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *Int64SliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + +func (f *Int64SliceFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *Int64SliceFlag) Names() []string + Names returns the names of the flag + +func (f *Int64SliceFlag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *Int64SliceFlag) SetDestination(slice []int64) + +func (f *Int64SliceFlag) SetValue(slice []int64) + +func (f *Int64SliceFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *Int64SliceFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +func (f *Int64SliceFlag) WithSeparatorSpec(spec separatorSpec) + +type IntFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value int + Destination *int + + Aliases []string + EnvVars []string + + Base int + + Action func(*Context, int) error + // Has unexported fields. +} + IntFlag is a flag with type int + +func (f *IntFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *IntFlag) Get(ctx *Context) int + Get returns the flag’s value in the given Context. + +func (f *IntFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *IntFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *IntFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *IntFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *IntFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *IntFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *IntFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *IntFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *IntFlag) Names() []string + Names returns the names of the flag + +func (f *IntFlag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *IntFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *IntFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type IntSlice struct { + // Has unexported fields. +} + IntSlice wraps []int to satisfy flag.Value + +func NewIntSlice(defaults ...int) *IntSlice + NewIntSlice makes an *IntSlice with default values + +func (i *IntSlice) Get() interface{} + Get returns the slice of ints set by this flag + +func (i *IntSlice) Serialize() string + Serialize allows IntSlice to fulfill Serializer + +func (i *IntSlice) Set(value string) error + Set parses the value into an integer and appends it to the list of values + +func (i *IntSlice) SetInt(value int) + TODO: Consistently have specific Set function for Int64 and Float64 ? SetInt + directly adds an integer to the list of values + +func (i *IntSlice) String() string + String returns a readable representation of this value (for usage defaults) + +func (i *IntSlice) Value() []int + Value returns the slice of ints set by this flag + +func (i *IntSlice) WithSeparatorSpec(spec separatorSpec) + +type IntSliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *IntSlice + Destination *IntSlice + + Aliases []string + EnvVars []string + + Action func(*Context, []int) error + // Has unexported fields. +} + IntSliceFlag is a flag with type *IntSlice + +func (f *IntSliceFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *IntSliceFlag) Get(ctx *Context) []int + Get returns the flag’s value in the given Context. + +func (f *IntSliceFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *IntSliceFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *IntSliceFlag) GetDestination() []int + +func (f *IntSliceFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *IntSliceFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *IntSliceFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *IntSliceFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *IntSliceFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *IntSliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + +func (f *IntSliceFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *IntSliceFlag) Names() []string + Names returns the names of the flag + +func (f *IntSliceFlag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *IntSliceFlag) SetDestination(slice []int) + +func (f *IntSliceFlag) SetValue(slice []int) + +func (f *IntSliceFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *IntSliceFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +func (f *IntSliceFlag) WithSeparatorSpec(spec separatorSpec) + +type InvalidFlagAccessFunc func(*Context, string) + InvalidFlagAccessFunc is executed when an invalid flag is accessed from the + context. + +type MultiError interface { + error + Errors() []error +} + MultiError is an error that wraps multiple errors. + +type MultiFloat64Flag = SliceFlag[*Float64SliceFlag, []float64, float64] + MultiFloat64Flag extends Float64SliceFlag with support for using slices + directly, as Value and/or Destination. See also SliceFlag. + +type MultiInt64Flag = SliceFlag[*Int64SliceFlag, []int64, int64] + MultiInt64Flag extends Int64SliceFlag with support for using slices + directly, as Value and/or Destination. See also SliceFlag. + +type MultiIntFlag = SliceFlag[*IntSliceFlag, []int, int] + MultiIntFlag extends IntSliceFlag with support for using slices directly, + as Value and/or Destination. See also SliceFlag. + +type MultiStringFlag = SliceFlag[*StringSliceFlag, []string, string] + MultiStringFlag extends StringSliceFlag with support for using slices + directly, as Value and/or Destination. See also SliceFlag. + +type OnUsageErrorFunc func(cCtx *Context, err error, isSubcommand bool) error + OnUsageErrorFunc is executed if a usage error occurs. This is useful for + displaying customized usage error messages. This function is able to replace + the original error messages. If this function is not set, the "Incorrect + usage" is displayed and the execution is interrupted. + +type Path = string + +type PathFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value Path + Destination *Path + + Aliases []string + EnvVars []string + + TakesFile bool + + Action func(*Context, Path) error + // Has unexported fields. +} + PathFlag is a flag with type Path + +func (f *PathFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *PathFlag) Get(ctx *Context) string + Get returns the flag’s value in the given Context. + +func (f *PathFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *PathFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *PathFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *PathFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *PathFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *PathFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *PathFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *PathFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *PathFlag) Names() []string + Names returns the names of the flag + +func (f *PathFlag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *PathFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *PathFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type RequiredFlag interface { + Flag + + IsRequired() bool +} + RequiredFlag is an interface that allows us to mark flags as required + it allows flags required flags to be backwards compatible with the Flag + interface + +type Serializer interface { + Serialize() string +} + Serializer is used to circumvent the limitations of flag.FlagSet.Set + +type SliceFlag[T SliceFlagTarget[E], S ~[]E, E any] struct { + Target T + Value S + Destination *S +} + SliceFlag extends implementations like StringSliceFlag and IntSliceFlag + with support for using slices directly, as Value and/or Destination. + See also SliceFlagTarget, MultiStringFlag, MultiFloat64Flag, MultiInt64Flag, + MultiIntFlag. + +func (x *SliceFlag[T, S, E]) Apply(set *flag.FlagSet) error + +func (x *SliceFlag[T, S, E]) GetCategory() string + +func (x *SliceFlag[T, S, E]) GetDefaultText() string + +func (x *SliceFlag[T, S, E]) GetDestination() S + +func (x *SliceFlag[T, S, E]) GetEnvVars() []string + +func (x *SliceFlag[T, S, E]) GetUsage() string + +func (x *SliceFlag[T, S, E]) GetValue() string + +func (x *SliceFlag[T, S, E]) IsRequired() bool + +func (x *SliceFlag[T, S, E]) IsSet() bool + +func (x *SliceFlag[T, S, E]) IsVisible() bool + +func (x *SliceFlag[T, S, E]) Names() []string + +func (x *SliceFlag[T, S, E]) SetDestination(slice S) + +func (x *SliceFlag[T, S, E]) SetValue(slice S) + +func (x *SliceFlag[T, S, E]) String() string + +func (x *SliceFlag[T, S, E]) TakesValue() bool + +type SliceFlagTarget[E any] interface { + Flag + RequiredFlag + DocGenerationFlag + VisibleFlag + CategorizableFlag + + // SetValue should propagate the given slice to the target, ideally as a new value. + // Note that a nil slice should nil/clear any existing value (modelled as ~[]E). + SetValue(slice []E) + // SetDestination should propagate the given slice to the target, ideally as a new value. + // Note that a nil slice should nil/clear any existing value (modelled as ~*[]E). + SetDestination(slice []E) + // GetDestination should return the current value referenced by any destination, or nil if nil/unset. + GetDestination() []E +} + SliceFlagTarget models a target implementation for use with SliceFlag. The + three methods, SetValue, SetDestination, and GetDestination, are necessary + to propagate Value and Destination, where Value is propagated inwards + (initially), and Destination is propagated outwards (on every update). + +type StringFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value string + Destination *string + + Aliases []string + EnvVars []string + + TakesFile bool + + Action func(*Context, string) error + // Has unexported fields. +} + StringFlag is a flag with type string + +func (f *StringFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *StringFlag) Get(ctx *Context) string + Get returns the flag’s value in the given Context. + +func (f *StringFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *StringFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *StringFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *StringFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *StringFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *StringFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *StringFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *StringFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *StringFlag) Names() []string + Names returns the names of the flag + +func (f *StringFlag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *StringFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *StringFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type StringSlice struct { + // Has unexported fields. +} + StringSlice wraps a []string to satisfy flag.Value + +func NewStringSlice(defaults ...string) *StringSlice + NewStringSlice creates a *StringSlice with default values + +func (s *StringSlice) Get() interface{} + Get returns the slice of strings set by this flag + +func (s *StringSlice) Serialize() string + Serialize allows StringSlice to fulfill Serializer + +func (s *StringSlice) Set(value string) error + Set appends the string value to the list of values + +func (s *StringSlice) String() string + String returns a readable representation of this value (for usage defaults) + +func (s *StringSlice) Value() []string + Value returns the slice of strings set by this flag + +func (s *StringSlice) WithSeparatorSpec(spec separatorSpec) + +type StringSliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *StringSlice + Destination *StringSlice + + Aliases []string + EnvVars []string + + TakesFile bool + + Action func(*Context, []string) error + + KeepSpace bool + // Has unexported fields. +} + StringSliceFlag is a flag with type *StringSlice + +func (f *StringSliceFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *StringSliceFlag) Get(ctx *Context) []string + Get returns the flag’s value in the given Context. + +func (f *StringSliceFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *StringSliceFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *StringSliceFlag) GetDestination() []string + +func (f *StringSliceFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *StringSliceFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *StringSliceFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *StringSliceFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *StringSliceFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *StringSliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + +func (f *StringSliceFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *StringSliceFlag) Names() []string + Names returns the names of the flag + +func (f *StringSliceFlag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *StringSliceFlag) SetDestination(slice []string) + +func (f *StringSliceFlag) SetValue(slice []string) + +func (f *StringSliceFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *StringSliceFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +func (f *StringSliceFlag) WithSeparatorSpec(spec separatorSpec) + +type SuggestCommandFunc func(commands []*Command, provided string) string + +type SuggestFlagFunc func(flags []Flag, provided string, hideHelp bool) string + +type Timestamp struct { + // Has unexported fields. +} + Timestamp wrap to satisfy golang's flag interface. + +func NewTimestamp(timestamp time.Time) *Timestamp + Timestamp constructor + +func (t *Timestamp) Get() interface{} + Get returns the flag structure + +func (t *Timestamp) Set(value string) error + Parses the string value to timestamp + +func (t *Timestamp) SetLayout(layout string) + Set the timestamp string layout for future parsing + +func (t *Timestamp) SetLocation(loc *time.Location) + Set perceived timezone of the to-be parsed time string + +func (t *Timestamp) SetTimestamp(value time.Time) + Set the timestamp value directly + +func (t *Timestamp) String() string + String returns a readable representation of this value (for usage defaults) + +func (t *Timestamp) Value() *time.Time + Value returns the timestamp value stored in the flag + +type TimestampFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *Timestamp + Destination *Timestamp + + Aliases []string + EnvVars []string + + Layout string + + Timezone *time.Location + + Action func(*Context, *time.Time) error + // Has unexported fields. +} + TimestampFlag is a flag with type *Timestamp + +func (f *TimestampFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *TimestampFlag) Get(ctx *Context) *time.Time + Get returns the flag’s value in the given Context. + +func (f *TimestampFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *TimestampFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *TimestampFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *TimestampFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *TimestampFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *TimestampFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *TimestampFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *TimestampFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *TimestampFlag) Names() []string + Names returns the names of the flag + +func (f *TimestampFlag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *TimestampFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *TimestampFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type Uint64Flag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value uint64 + Destination *uint64 + + Aliases []string + EnvVars []string + + Base int + + Action func(*Context, uint64) error + // Has unexported fields. +} + Uint64Flag is a flag with type uint64 + +func (f *Uint64Flag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *Uint64Flag) Get(ctx *Context) uint64 + Get returns the flag’s value in the given Context. + +func (f *Uint64Flag) GetCategory() string + GetCategory returns the category for the flag + +func (f *Uint64Flag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *Uint64Flag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *Uint64Flag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *Uint64Flag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *Uint64Flag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *Uint64Flag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *Uint64Flag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *Uint64Flag) Names() []string + Names returns the names of the flag + +func (f *Uint64Flag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *Uint64Flag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *Uint64Flag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type Uint64Slice struct { + // Has unexported fields. +} + Uint64Slice wraps []int64 to satisfy flag.Value + +func NewUint64Slice(defaults ...uint64) *Uint64Slice + NewUint64Slice makes an *Uint64Slice with default values + +func (i *Uint64Slice) Get() interface{} + Get returns the slice of ints set by this flag + +func (i *Uint64Slice) Serialize() string + Serialize allows Uint64Slice to fulfill Serializer + +func (i *Uint64Slice) Set(value string) error + Set parses the value into an integer and appends it to the list of values + +func (i *Uint64Slice) String() string + String returns a readable representation of this value (for usage defaults) + +func (i *Uint64Slice) Value() []uint64 + Value returns the slice of ints set by this flag + +func (i *Uint64Slice) WithSeparatorSpec(spec separatorSpec) + +type Uint64SliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *Uint64Slice + Destination *Uint64Slice + + Aliases []string + EnvVars []string + + Action func(*Context, []uint64) error + // Has unexported fields. +} + Uint64SliceFlag is a flag with type *Uint64Slice + +func (f *Uint64SliceFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *Uint64SliceFlag) Get(ctx *Context) []uint64 + Get returns the flag’s value in the given Context. + +func (f *Uint64SliceFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *Uint64SliceFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *Uint64SliceFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *Uint64SliceFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *Uint64SliceFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *Uint64SliceFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *Uint64SliceFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *Uint64SliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + +func (f *Uint64SliceFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *Uint64SliceFlag) Names() []string + Names returns the names of the flag + +func (f *Uint64SliceFlag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *Uint64SliceFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *Uint64SliceFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +func (f *Uint64SliceFlag) WithSeparatorSpec(spec separatorSpec) + +type UintFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value uint + Destination *uint + + Aliases []string + EnvVars []string + + Base int + + Action func(*Context, uint) error + // Has unexported fields. +} + UintFlag is a flag with type uint + +func (f *UintFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *UintFlag) Get(ctx *Context) uint + Get returns the flag’s value in the given Context. + +func (f *UintFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *UintFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *UintFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *UintFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *UintFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *UintFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *UintFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *UintFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *UintFlag) Names() []string + Names returns the names of the flag + +func (f *UintFlag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *UintFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *UintFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +type UintSlice struct { + // Has unexported fields. +} + UintSlice wraps []int to satisfy flag.Value + +func NewUintSlice(defaults ...uint) *UintSlice + NewUintSlice makes an *UintSlice with default values + +func (i *UintSlice) Get() interface{} + Get returns the slice of ints set by this flag + +func (i *UintSlice) Serialize() string + Serialize allows UintSlice to fulfill Serializer + +func (i *UintSlice) Set(value string) error + Set parses the value into an integer and appends it to the list of values + +func (i *UintSlice) SetUint(value uint) + TODO: Consistently have specific Set function for Int64 and Float64 ? SetInt + directly adds an integer to the list of values + +func (i *UintSlice) String() string + String returns a readable representation of this value (for usage defaults) + +func (i *UintSlice) Value() []uint + Value returns the slice of ints set by this flag + +func (i *UintSlice) WithSeparatorSpec(spec separatorSpec) + +type UintSliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *UintSlice + Destination *UintSlice + + Aliases []string + EnvVars []string + + Action func(*Context, []uint) error + // Has unexported fields. +} + UintSliceFlag is a flag with type *UintSlice + +func (f *UintSliceFlag) Apply(set *flag.FlagSet) error + Apply populates the flag given the flag set and environment + +func (f *UintSliceFlag) Get(ctx *Context) []uint + Get returns the flag’s value in the given Context. + +func (f *UintSliceFlag) GetCategory() string + GetCategory returns the category for the flag + +func (f *UintSliceFlag) GetDefaultText() string + GetDefaultText returns the default text for this flag + +func (f *UintSliceFlag) GetEnvVars() []string + GetEnvVars returns the env vars for this flag + +func (f *UintSliceFlag) GetUsage() string + GetUsage returns the usage string for the flag + +func (f *UintSliceFlag) GetValue() string + GetValue returns the flags value as string representation and an empty + string if the flag takes no value at all. + +func (f *UintSliceFlag) IsRequired() bool + IsRequired returns whether or not the flag is required + +func (f *UintSliceFlag) IsSet() bool + IsSet returns whether or not the flag has been set through env or file + +func (f *UintSliceFlag) IsSliceFlag() bool + IsSliceFlag implements DocGenerationSliceFlag. + +func (f *UintSliceFlag) IsVisible() bool + IsVisible returns true if the flag is not hidden, otherwise false + +func (f *UintSliceFlag) Names() []string + Names returns the names of the flag + +func (f *UintSliceFlag) RunAction(c *Context) error + RunAction executes flag action if set + +func (f *UintSliceFlag) String() string + String returns a readable representation of this value (for usage defaults) + +func (f *UintSliceFlag) TakesValue() bool + TakesValue returns true of the flag takes a value, otherwise false + +func (f *UintSliceFlag) WithSeparatorSpec(spec separatorSpec) + +type VisibleFlag interface { + Flag + + // IsVisible returns true if the flag is not hidden, otherwise false + IsVisible() bool +} + VisibleFlag is an interface that allows to check if a flag is visible + +type VisibleFlagCategory interface { + // Name returns the category name string + Name() string + // Flags returns a slice of VisibleFlag sorted by name + Flags() []VisibleFlag +} + VisibleFlagCategory is a category containing flags. + +package altsrc // import "github.com/urfave/cli/v2/altsrc" + + +FUNCTIONS + +func ApplyInputSourceValues(cCtx *cli.Context, inputSourceContext InputSourceContext, flags []cli.Flag) error + ApplyInputSourceValues iterates over all provided flags and executes + ApplyInputSourceValue on flags implementing the FlagInputSourceExtension + interface to initialize these flags to an alternate input source. + +func InitInputSource(flags []cli.Flag, createInputSource func() (InputSourceContext, error)) cli.BeforeFunc + InitInputSource is used to to setup an InputSourceContext on a cli.Command + Before method. It will create a new input source based on the func provided. + If there is no error it will then apply the new input source to any flags + that are supported by the input source + +func InitInputSourceWithContext(flags []cli.Flag, createInputSource func(cCtx *cli.Context) (InputSourceContext, error)) cli.BeforeFunc + InitInputSourceWithContext is used to to setup an InputSourceContext on + a cli.Command Before method. It will create a new input source based on + the func provided with potentially using existing cli.Context values to + initialize itself. If there is no error it will then apply the new input + source to any flags that are supported by the input source + +func NewJSONSourceFromFlagFunc(flag string) func(c *cli.Context) (InputSourceContext, error) + NewJSONSourceFromFlagFunc returns a func that takes a cli.Context and + returns an InputSourceContext suitable for retrieving config variables from + a file containing JSON data with the file name defined by the given flag. + +func NewTomlSourceFromFlagFunc(flagFileName string) func(cCtx *cli.Context) (InputSourceContext, error) + NewTomlSourceFromFlagFunc creates a new TOML InputSourceContext from a + provided flag name and source context. + +func NewYamlSourceFromFlagFunc(flagFileName string) func(cCtx *cli.Context) (InputSourceContext, error) + NewYamlSourceFromFlagFunc creates a new Yaml InputSourceContext from a + provided flag name and source context. + + +TYPES + +type BoolFlag struct { + *cli.BoolFlag + // Has unexported fields. +} + BoolFlag is the flag type that wraps cli.BoolFlag to allow for other values + to be specified + +func NewBoolFlag(fl *cli.BoolFlag) *BoolFlag + NewBoolFlag creates a new BoolFlag + +func (f *BoolFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + BoolFlag.Apply + +func (f *BoolFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a Bool value to the flagSet if required + +type DurationFlag struct { + *cli.DurationFlag + // Has unexported fields. +} + DurationFlag is the flag type that wraps cli.DurationFlag to allow for other + values to be specified + +func NewDurationFlag(fl *cli.DurationFlag) *DurationFlag + NewDurationFlag creates a new DurationFlag + +func (f *DurationFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + DurationFlag.Apply + +func (f *DurationFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a Duration value to the flagSet if required + +type FlagInputSourceExtension interface { + cli.Flag + ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error +} + FlagInputSourceExtension is an extension interface of cli.Flag that allows a + value to be set on the existing parsed flags. + +type Float64Flag struct { + *cli.Float64Flag + // Has unexported fields. +} + Float64Flag is the flag type that wraps cli.Float64Flag to allow for other + values to be specified + +func NewFloat64Flag(fl *cli.Float64Flag) *Float64Flag + NewFloat64Flag creates a new Float64Flag + +func (f *Float64Flag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + Float64Flag.Apply + +func (f *Float64Flag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a Float64 value to the flagSet if required + +type Float64SliceFlag struct { + *cli.Float64SliceFlag + // Has unexported fields. +} + Float64SliceFlag is the flag type that wraps cli.Float64SliceFlag to allow + for other values to be specified + +func NewFloat64SliceFlag(fl *cli.Float64SliceFlag) *Float64SliceFlag + NewFloat64SliceFlag creates a new Float64SliceFlag + +func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + Float64SliceFlag.Apply + +func (f *Float64SliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a Float64Slice value if required + +type GenericFlag struct { + *cli.GenericFlag + // Has unexported fields. +} + GenericFlag is the flag type that wraps cli.GenericFlag to allow for other + values to be specified + +func NewGenericFlag(fl *cli.GenericFlag) *GenericFlag + NewGenericFlag creates a new GenericFlag + +func (f *GenericFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + GenericFlag.Apply + +func (f *GenericFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a generic value to the flagSet if required + +type InputSourceContext interface { + Source() string + + Int(name string) (int, error) + Int64(name string) (int64, error) + Uint(name string) (uint, error) + Uint64(name string) (uint64, error) + Duration(name string) (time.Duration, error) + Float64(name string) (float64, error) + String(name string) (string, error) + StringSlice(name string) ([]string, error) + IntSlice(name string) ([]int, error) + Int64Slice(name string) ([]int64, error) + Float64Slice(name string) ([]float64, error) + Generic(name string) (cli.Generic, error) + Bool(name string) (bool, error) + + // Has unexported methods. +} + InputSourceContext is an interface used to allow other input sources to be + implemented as needed. + + Source returns an identifier for the input source. In case of file source it + should return path to the file. + +func NewJSONSource(data []byte) (InputSourceContext, error) + NewJSONSource returns an InputSourceContext suitable for retrieving config + variables from raw JSON data. + +func NewJSONSourceFromFile(f string) (InputSourceContext, error) + NewJSONSourceFromFile returns an InputSourceContext suitable for retrieving + config variables from a file (or url) containing JSON data. + +func NewJSONSourceFromReader(r io.Reader) (InputSourceContext, error) + NewJSONSourceFromReader returns an InputSourceContext suitable for + retrieving config variables from an io.Reader that returns JSON data. + +func NewTomlSourceFromFile(file string) (InputSourceContext, error) + NewTomlSourceFromFile creates a new TOML InputSourceContext from a filepath. + +func NewYamlSourceFromFile(file string) (InputSourceContext, error) + NewYamlSourceFromFile creates a new Yaml InputSourceContext from a filepath. + +type Int64Flag struct { + *cli.Int64Flag + // Has unexported fields. +} + Int64Flag is the flag type that wraps cli.Int64Flag to allow for other + values to be specified + +func NewInt64Flag(fl *cli.Int64Flag) *Int64Flag + NewInt64Flag creates a new Int64Flag + +func (f *Int64Flag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + Int64Flag.Apply + +func (f *Int64Flag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + +type Int64SliceFlag struct { + *cli.Int64SliceFlag + // Has unexported fields. +} + Int64SliceFlag is the flag type that wraps cli.Int64SliceFlag to allow for + other values to be specified + +func NewInt64SliceFlag(fl *cli.Int64SliceFlag) *Int64SliceFlag + NewInt64SliceFlag creates a new Int64SliceFlag + +func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + Int64SliceFlag.Apply + +func (f *Int64SliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a Int64Slice value if required + +type IntFlag struct { + *cli.IntFlag + // Has unexported fields. +} + IntFlag is the flag type that wraps cli.IntFlag to allow for other values to + be specified + +func NewIntFlag(fl *cli.IntFlag) *IntFlag + NewIntFlag creates a new IntFlag + +func (f *IntFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + IntFlag.Apply + +func (f *IntFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a int value to the flagSet if required + +type IntSliceFlag struct { + *cli.IntSliceFlag + // Has unexported fields. +} + IntSliceFlag is the flag type that wraps cli.IntSliceFlag to allow for other + values to be specified + +func NewIntSliceFlag(fl *cli.IntSliceFlag) *IntSliceFlag + NewIntSliceFlag creates a new IntSliceFlag + +func (f *IntSliceFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + IntSliceFlag.Apply + +func (f *IntSliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a IntSlice value if required + +type MapInputSource struct { + // Has unexported fields. +} + MapInputSource implements InputSourceContext to return data from the map + that is loaded. + +func NewMapInputSource(file string, valueMap map[interface{}]interface{}) *MapInputSource + NewMapInputSource creates a new MapInputSource for implementing custom input + sources. + +func (fsm *MapInputSource) Bool(name string) (bool, error) + Bool returns an bool from the map otherwise returns false + +func (fsm *MapInputSource) Duration(name string) (time.Duration, error) + Duration returns a duration from the map if it exists otherwise returns 0 + +func (fsm *MapInputSource) Float64(name string) (float64, error) + Float64 returns an float64 from the map if it exists otherwise returns 0 + +func (fsm *MapInputSource) Float64Slice(name string) ([]float64, error) + Float64Slice returns an []float64 from the map if it exists otherwise + returns nil + +func (fsm *MapInputSource) Generic(name string) (cli.Generic, error) + Generic returns an cli.Generic from the map if it exists otherwise returns + nil + +func (fsm *MapInputSource) Int(name string) (int, error) + Int returns an int from the map if it exists otherwise returns 0 + +func (fsm *MapInputSource) Int64(name string) (int64, error) + Int64 returns an int64 from the map if it exists otherwise returns 0 + +func (fsm *MapInputSource) Int64Slice(name string) ([]int64, error) + Int64Slice returns an []int64 from the map if it exists otherwise returns + nil + +func (fsm *MapInputSource) IntSlice(name string) ([]int, error) + IntSlice returns an []int from the map if it exists otherwise returns nil + +func (fsm *MapInputSource) Source() string + Source returns the path of the source file + +func (fsm *MapInputSource) String(name string) (string, error) + String returns a string from the map if it exists otherwise returns an empty + string + +func (fsm *MapInputSource) StringSlice(name string) ([]string, error) + StringSlice returns an []string from the map if it exists otherwise returns + nil + +func (fsm *MapInputSource) Uint(name string) (uint, error) + Int64 returns an int64 from the map if it exists otherwise returns 0 + +func (fsm *MapInputSource) Uint64(name string) (uint64, error) + UInt64 returns an uint64 from the map if it exists otherwise returns 0 + +type PathFlag struct { + *cli.PathFlag + // Has unexported fields. +} + PathFlag is the flag type that wraps cli.PathFlag to allow for other values + to be specified + +func NewPathFlag(fl *cli.PathFlag) *PathFlag + NewPathFlag creates a new PathFlag + +func (f *PathFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + PathFlag.Apply + +func (f *PathFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a Path value to the flagSet if required + +type StringFlag struct { + *cli.StringFlag + // Has unexported fields. +} + StringFlag is the flag type that wraps cli.StringFlag to allow for other + values to be specified + +func NewStringFlag(fl *cli.StringFlag) *StringFlag + NewStringFlag creates a new StringFlag + +func (f *StringFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + StringFlag.Apply + +func (f *StringFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a String value to the flagSet if required + +type StringSliceFlag struct { + *cli.StringSliceFlag + // Has unexported fields. +} + StringSliceFlag is the flag type that wraps cli.StringSliceFlag to allow for + other values to be specified + +func NewStringSliceFlag(fl *cli.StringSliceFlag) *StringSliceFlag + NewStringSliceFlag creates a new StringSliceFlag + +func (f *StringSliceFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + StringSliceFlag.Apply + +func (f *StringSliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a StringSlice value to the flagSet if required + +type Uint64Flag struct { + *cli.Uint64Flag + // Has unexported fields. +} + Uint64Flag is the flag type that wraps cli.Uint64Flag to allow for other + values to be specified + +func NewUint64Flag(fl *cli.Uint64Flag) *Uint64Flag + NewUint64Flag creates a new Uint64Flag + +func (f *Uint64Flag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + Uint64Flag.Apply + +func (f *Uint64Flag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + +type UintFlag struct { + *cli.UintFlag + // Has unexported fields. +} + UintFlag is the flag type that wraps cli.UintFlag to allow for other values + to be specified + +func NewUintFlag(fl *cli.UintFlag) *UintFlag + NewUintFlag creates a new UintFlag + +func (f *UintFlag) Apply(set *flag.FlagSet) error + Apply saves the flagSet for later usage calls, then calls the wrapped + UintFlag.Apply + +func (f *UintFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + diff --git a/vendor/github.com/urfave/cli/v2/help.go b/vendor/github.com/urfave/cli/v2/help.go index c1e974a48..640e29045 100644 --- a/vendor/github.com/urfave/cli/v2/help.go +++ b/vendor/github.com/urfave/cli/v2/help.go @@ -10,34 +10,77 @@ import ( "unicode/utf8" ) -var helpCommand = &Command{ - Name: "help", - Aliases: []string{"h"}, +const ( + helpName = "help" + helpAlias = "h" +) + +// this instance is to avoid recursion in the ShowCommandHelp which can +// add a help command again +var helpCommandDontUse = &Command{ + Name: helpName, + Aliases: []string{helpAlias}, Usage: "Shows a list of commands or help for one command", ArgsUsage: "[command]", - Action: func(c *Context) error { - args := c.Args() - if args.Present() { - return ShowCommandHelp(c, args.First()) - } - - _ = ShowAppHelp(c) - return nil - }, } -var helpSubcommand = &Command{ - Name: "help", - Aliases: []string{"h"}, +var helpCommand = &Command{ + Name: helpName, + Aliases: []string{helpAlias}, Usage: "Shows a list of commands or help for one command", ArgsUsage: "[command]", - Action: func(c *Context) error { - args := c.Args() - if args.Present() { - return ShowCommandHelp(c, args.First()) + Action: func(cCtx *Context) error { + args := cCtx.Args() + argsPresent := args.First() != "" + firstArg := args.First() + + // This action can be triggered by a "default" action of a command + // or via cmd.Run when cmd == helpCmd. So we have following possibilities + // + // 1 $ app + // 2 $ app help + // 3 $ app foo + // 4 $ app help foo + // 5 $ app foo help + // 6 $ app foo -h (with no other sub-commands nor flags defined) + + // Case 4. when executing a help command set the context to parent + // to allow resolution of subsequent args. This will transform + // $ app help foo + // to + // $ app foo + // which will then be handled as case 3 + if cCtx.Command.Name == helpName || cCtx.Command.Name == helpAlias { + cCtx = cCtx.parentContext + } + + // Case 4. $ app hello foo + // foo is the command for which help needs to be shown + if argsPresent { + return ShowCommandHelp(cCtx, firstArg) } - return ShowSubcommandHelp(c) + // Case 1 & 2 + // Special case when running help on main app itself as opposed to individual + // commands/subcommands + if cCtx.parentContext.App == nil { + _ = ShowAppHelp(cCtx) + return nil + } + + // Case 3, 5 + if (len(cCtx.Command.Subcommands) == 1 && !cCtx.Command.HideHelp && !cCtx.Command.HideHelpCommand) || + (len(cCtx.Command.Subcommands) == 0 && cCtx.Command.HideHelp) { + templ := cCtx.Command.CustomHelpTemplate + if templ == "" { + templ = CommandHelpTemplate + } + HelpPrinter(cCtx.App.Writer, templ, cCtx.Command) + return nil + } + + // Case 6, handling incorporated in the callee itself + return ShowSubcommandHelp(cCtx) }, } @@ -59,6 +102,11 @@ var HelpPrinter helpPrinter = printHelp // HelpPrinterCustom is a function that writes the help output. It is used as // the default implementation of HelpPrinter, and may be called directly if // the ExtraInfo field is set on an App. +// +// In the default implementation, if the customFuncs argument contains a +// "wrapAt" key, which is a function which takes no arguments and returns +// an int, this int value will be used to produce a "wrap" function used +// by the default template to wrap long lines. var HelpPrinterCustom helpPrinterCustom = printHelpCustom // VersionPrinter prints the version for the App @@ -71,30 +119,30 @@ func ShowAppHelpAndExit(c *Context, exitCode int) { } // ShowAppHelp is an action that displays the help. -func ShowAppHelp(c *Context) error { - template := c.App.CustomAppHelpTemplate - if template == "" { - template = AppHelpTemplate +func ShowAppHelp(cCtx *Context) error { + tpl := cCtx.App.CustomAppHelpTemplate + if tpl == "" { + tpl = AppHelpTemplate } - if c.App.ExtraInfo == nil { - HelpPrinter(c.App.Writer, template, c.App) + if cCtx.App.ExtraInfo == nil { + HelpPrinter(cCtx.App.Writer, tpl, cCtx.App) return nil } customAppData := func() map[string]interface{} { return map[string]interface{}{ - "ExtraInfo": c.App.ExtraInfo, + "ExtraInfo": cCtx.App.ExtraInfo, } } - HelpPrinterCustom(c.App.Writer, template, c.App, customAppData()) + HelpPrinterCustom(cCtx.App.Writer, tpl, cCtx.App, customAppData()) return nil } // DefaultAppComplete prints the list of subcommands as the default app completion method -func DefaultAppComplete(c *Context) { - DefaultCompleteWithFlags(nil)(c) +func DefaultAppComplete(cCtx *Context) { + DefaultCompleteWithFlags(nil)(cCtx) } func printCommandSuggestions(commands []*Command, writer io.Writer) { @@ -102,7 +150,7 @@ func printCommandSuggestions(commands []*Command, writer io.Writer) { if command.Hidden { continue } - if os.Getenv("_CLI_ZSH_AUTOCOMPLETE_HACK") == "1" { + if strings.HasSuffix(os.Getenv("SHELL"), "zsh") { for _, name := range command.Names() { _, _ = fmt.Fprintf(writer, "%s:%s\n", name, command.Usage) } @@ -143,7 +191,7 @@ func printFlagSuggestions(lastArg string, flags []Flag, writer io.Writer) { // this will get total count utf8 letters in flag name count := utf8.RuneCountInString(name) if count > 2 { - count = 2 // resuse this count to generate single - or -- in flag completion + count = 2 // reuse this count to generate single - or -- in flag completion } // if flag name has more than one utf8 letter and last argument in cli has -- prefix then // skip flag completion for short flags example -v or -x @@ -159,23 +207,36 @@ func printFlagSuggestions(lastArg string, flags []Flag, writer io.Writer) { } } -func DefaultCompleteWithFlags(cmd *Command) func(c *Context) { - return func(c *Context) { +func DefaultCompleteWithFlags(cmd *Command) func(cCtx *Context) { + return func(cCtx *Context) { + var lastArg string + + // TODO: This shouldnt depend on os.Args rather it should + // depend on root arguments passed to App if len(os.Args) > 2 { - lastArg := os.Args[len(os.Args)-2] + lastArg = os.Args[len(os.Args)-2] + } + + if lastArg != "" { if strings.HasPrefix(lastArg, "-") { - printFlagSuggestions(lastArg, c.App.Flags, c.App.Writer) if cmd != nil { - printFlagSuggestions(lastArg, cmd.Flags, c.App.Writer) + printFlagSuggestions(lastArg, cmd.Flags, cCtx.App.Writer) + + return } + + printFlagSuggestions(lastArg, cCtx.App.Flags, cCtx.App.Writer) + return } } + if cmd != nil { - printCommandSuggestions(cmd.Subcommands, c.App.Writer) - } else { - printCommandSuggestions(c.App.Commands, c.App.Writer) + printCommandSuggestions(cmd.Subcommands, cCtx.App.Writer) + return } + + printCommandSuggestions(cCtx.Command.Subcommands, cCtx.App.Writer) } } @@ -187,17 +248,26 @@ func ShowCommandHelpAndExit(c *Context, command string, code int) { // ShowCommandHelp prints help for the given command func ShowCommandHelp(ctx *Context, command string) error { - // show the subcommand help for a command with subcommands - if command == "" { - HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App) - return nil - } - for _, c := range ctx.App.Commands { + commands := ctx.App.Commands + if ctx.Command.Subcommands != nil { + commands = ctx.Command.Subcommands + } + for _, c := range commands { if c.HasName(command) { + if !ctx.App.HideHelpCommand && !c.HasName(helpName) && len(c.Subcommands) != 0 && c.Command(helpName) == nil { + c.Subcommands = append(c.Subcommands, helpCommandDontUse) + } + if !ctx.App.HideHelp && HelpFlag != nil { + c.appendFlag(HelpFlag) + } templ := c.CustomHelpTemplate if templ == "" { - templ = CommandHelpTemplate + if len(c.Subcommands) == 0 { + templ = CommandHelpTemplate + } else { + templ = SubcommandHelpTemplate + } } HelpPrinter(ctx.App.Writer, templ, c) @@ -207,46 +277,59 @@ func ShowCommandHelp(ctx *Context, command string) error { } if ctx.App.CommandNotFound == nil { - return Exit(fmt.Sprintf("No help topic for '%v'", command), 3) + errMsg := fmt.Sprintf("No help topic for '%v'", command) + if ctx.App.Suggest && SuggestCommand != nil { + if suggestion := SuggestCommand(ctx.Command.Subcommands, command); suggestion != "" { + errMsg += ". " + suggestion + } + } + return Exit(errMsg, 3) } ctx.App.CommandNotFound(ctx, command) return nil } +// ShowSubcommandHelpAndExit - Prints help for the given subcommand and exits with exit code. +func ShowSubcommandHelpAndExit(c *Context, exitCode int) { + _ = ShowSubcommandHelp(c) + os.Exit(exitCode) +} + // ShowSubcommandHelp prints help for the given subcommand -func ShowSubcommandHelp(c *Context) error { - if c == nil { +func ShowSubcommandHelp(cCtx *Context) error { + if cCtx == nil { return nil } - - if c.Command != nil { - return ShowCommandHelp(c, c.Command.Name) + // use custom template when provided (fixes #1703) + templ := SubcommandHelpTemplate + if cCtx.Command != nil && cCtx.Command.CustomHelpTemplate != "" { + templ = cCtx.Command.CustomHelpTemplate } - - return ShowCommandHelp(c, "") + HelpPrinter(cCtx.App.Writer, templ, cCtx.Command) + return nil } // ShowVersion prints the version number of the App -func ShowVersion(c *Context) { - VersionPrinter(c) +func ShowVersion(cCtx *Context) { + VersionPrinter(cCtx) } -func printVersion(c *Context) { - _, _ = fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version) +func printVersion(cCtx *Context) { + _, _ = fmt.Fprintf(cCtx.App.Writer, "%v version %v\n", cCtx.App.Name, cCtx.App.Version) } // ShowCompletions prints the lists of commands within a given context -func ShowCompletions(c *Context) { - a := c.App - if a != nil && a.BashComplete != nil { - a.BashComplete(c) +func ShowCompletions(cCtx *Context) { + c := cCtx.Command + if c != nil && c.BashComplete != nil { + c.BashComplete(cCtx) } } // ShowCommandCompletions prints the custom completions for a given command func ShowCommandCompletions(ctx *Context, command string) { - c := ctx.App.Command(command) + c := ctx.Command.Command(command) if c != nil { if c.BashComplete != nil { c.BashComplete(ctx) @@ -262,15 +345,57 @@ func ShowCommandCompletions(ctx *Context, command string) { // The customFuncs map will be combined with a default template.FuncMap to // allow using arbitrary functions in template rendering. func printHelpCustom(out io.Writer, templ string, data interface{}, customFuncs map[string]interface{}) { + + const maxLineLength = 10000 + funcMap := template.FuncMap{ - "join": strings.Join, + "join": strings.Join, + "subtract": subtract, + "indent": indent, + "nindent": nindent, + "trim": strings.TrimSpace, + "wrap": func(input string, offset int) string { return wrap(input, offset, maxLineLength) }, + "offset": offset, + "offsetCommands": offsetCommands, } + + if customFuncs["wrapAt"] != nil { + if wa, ok := customFuncs["wrapAt"]; ok { + if waf, ok := wa.(func() int); ok { + wrapAt := waf() + customFuncs["wrap"] = func(input string, offset int) string { + return wrap(input, offset, wrapAt) + } + } + } + } + for key, value := range customFuncs { funcMap[key] = value } w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0) t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) + templates := map[string]string{ + "helpNameTemplate": helpNameTemplate, + "usageTemplate": usageTemplate, + "descriptionTemplate": descriptionTemplate, + "visibleCommandTemplate": visibleCommandTemplate, + "copyrightTemplate": copyrightTemplate, + "versionTemplate": versionTemplate, + "visibleFlagCategoryTemplate": visibleFlagCategoryTemplate, + "visibleFlagTemplate": visibleFlagTemplate, + "visibleGlobalFlagCategoryTemplate": strings.Replace(visibleFlagCategoryTemplate, "OPTIONS", "GLOBAL OPTIONS", -1), + "authorsTemplate": authorsTemplate, + "visibleCommandCategoryTemplate": visibleCommandCategoryTemplate, + } + for name, value := range templates { + if _, err := t.New(name).Parse(value); err != nil { + if os.Getenv("CLI_TEMPLATE_ERROR_DEBUG") != "" { + _, _ = fmt.Fprintf(ErrWriter, "CLI TEMPLATE ERROR: %#v\n", err) + } + } + } err := t.Execute(w, data) if err != nil { @@ -288,42 +413,29 @@ func printHelp(out io.Writer, templ string, data interface{}) { HelpPrinterCustom(out, templ, data, nil) } -func checkVersion(c *Context) bool { +func checkVersion(cCtx *Context) bool { found := false for _, name := range VersionFlag.Names() { - if c.Bool(name) { + if cCtx.Bool(name) { found = true } } return found } -func checkHelp(c *Context) bool { +func checkHelp(cCtx *Context) bool { + if HelpFlag == nil { + return false + } found := false for _, name := range HelpFlag.Names() { - if c.Bool(name) { + if cCtx.Bool(name) { found = true + break } } - return found -} - -func checkCommandHelp(c *Context, name string) bool { - if c.Bool("h") || c.Bool("help") { - _ = ShowCommandHelp(c, name) - return true - } - - return false -} - -func checkSubcommandHelp(c *Context) bool { - if c.Bool("h") || c.Bool("help") { - _ = ShowSubcommandHelp(c) - return true - } - return false + return found } func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) { @@ -341,28 +453,112 @@ func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) { return true, arguments[:pos] } -func checkCompletions(c *Context) bool { - if !c.shellComplete { +func checkCompletions(cCtx *Context) bool { + if !cCtx.shellComplete { return false } - if args := c.Args(); args.Present() { + if args := cCtx.Args(); args.Present() { name := args.First() - if cmd := c.App.Command(name); cmd != nil { + if cmd := cCtx.Command.Command(name); cmd != nil { // let the command handle the completion return false } } - ShowCompletions(c) + ShowCompletions(cCtx) return true } -func checkCommandCompletions(c *Context, name string) bool { - if !c.shellComplete { - return false +func subtract(a, b int) int { + return a - b +} + +func indent(spaces int, v string) string { + pad := strings.Repeat(" ", spaces) + return pad + strings.Replace(v, "\n", "\n"+pad, -1) +} + +func nindent(spaces int, v string) string { + return "\n" + indent(spaces, v) +} + +func wrap(input string, offset int, wrapAt int) string { + var ss []string + + lines := strings.Split(input, "\n") + + padding := strings.Repeat(" ", offset) + + for i, line := range lines { + if line == "" { + ss = append(ss, line) + } else { + wrapped := wrapLine(line, offset, wrapAt, padding) + if i == 0 { + ss = append(ss, wrapped) + } else { + ss = append(ss, padding+wrapped) + + } + + } } - ShowCommandCompletions(c, name) - return true + return strings.Join(ss, "\n") +} + +func wrapLine(input string, offset int, wrapAt int, padding string) string { + if wrapAt <= offset || len(input) <= wrapAt-offset { + return input + } + + lineWidth := wrapAt - offset + words := strings.Fields(input) + if len(words) == 0 { + return input + } + + wrapped := words[0] + spaceLeft := lineWidth - len(wrapped) + for _, word := range words[1:] { + if len(word)+1 > spaceLeft { + wrapped += "\n" + padding + word + spaceLeft = lineWidth - len(word) + } else { + wrapped += " " + word + spaceLeft -= 1 + len(word) + } + } + + return wrapped +} + +func offset(input string, fixed int) int { + return len(input) + fixed +} + +// this function tries to find the max width of the names column +// so say we have the following rows for help +// +// foo1, foo2, foo3 some string here +// bar1, b2 some other string here +// +// We want to offset the 2nd row usage by some amount so that everything +// is aligned +// +// foo1, foo2, foo3 some string here +// bar1, b2 some other string here +// +// to find that offset we find the length of all the rows and use the max +// to calculate the offset +func offsetCommands(cmds []*Command, fixed int) int { + var max int = 0 + for _, cmd := range cmds { + s := strings.Join(cmd.Names(), ", ") + if len(s) > max { + max = len(s) + } + } + return max + fixed } diff --git a/vendor/github.com/urfave/cli/v2/mkdocs-reqs.txt b/vendor/github.com/urfave/cli/v2/mkdocs-reqs.txt new file mode 100644 index 000000000..482ad0622 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/mkdocs-reqs.txt @@ -0,0 +1,5 @@ +mkdocs-git-revision-date-localized-plugin~=1.0 +mkdocs-material-extensions~=1.0 +mkdocs-material~=8.2 +mkdocs~=1.3 +pygments~=2.12 diff --git a/vendor/github.com/urfave/cli/v2/mkdocs.yml b/vendor/github.com/urfave/cli/v2/mkdocs.yml new file mode 100644 index 000000000..f7bfd419e --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/mkdocs.yml @@ -0,0 +1,107 @@ +# NOTE: the mkdocs dependencies will need to be installed out of +# band until this whole thing gets more automated: +# +# pip install -r mkdocs-reqs.txt +# + +site_name: urfave/cli +site_url: https://cli.urfave.org/ +repo_url: https://github.com/urfave/cli +edit_uri: edit/main/docs/ +nav: + - Home: + - Welcome: index.md + - Contributing: CONTRIBUTING.md + - Code of Conduct: CODE_OF_CONDUCT.md + - Releasing: RELEASING.md + - Security: SECURITY.md + - Migrate v1 to v2: migrate-v1-to-v2.md + - v2 Manual: + - Getting Started: v2/getting-started.md + - Migrating From Older Releases: v2/migrating-from-older-releases.md + - Examples: + - Greet: v2/examples/greet.md + - Arguments: v2/examples/arguments.md + - Flags: v2/examples/flags.md + - Subcommands: v2/examples/subcommands.md + - Subcommands Categories: v2/examples/subcommands-categories.md + - Exit Codes: v2/examples/exit-codes.md + - Combining Short Options: v2/examples/combining-short-options.md + - Bash Completions: v2/examples/bash-completions.md + - Generated Help Text: v2/examples/generated-help-text.md + - Version Flag: v2/examples/version-flag.md + - Timestamp Flag: v2/examples/timestamp-flag.md + - Suggestions: v2/examples/suggestions.md + - Full API Example: v2/examples/full-api-example.md + - v1 Manual: + - Getting Started: v1/getting-started.md + - Migrating to v2: v1/migrating-to-v2.md + - Examples: + - Greet: v1/examples/greet.md + - Arguments: v1/examples/arguments.md + - Flags: v1/examples/flags.md + - Subcommands: v1/examples/subcommands.md + - Subcommands (Categories): v1/examples/subcommands-categories.md + - Exit Codes: v1/examples/exit-codes.md + - Combining Short Options: v1/examples/combining-short-options.md + - Bash Completions: v1/examples/bash-completions.md + - Generated Help Text: v1/examples/generated-help-text.md + - Version Flag: v1/examples/version-flag.md + +theme: + name: material + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/brightness-4 + name: dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/brightness-7 + name: light mode + features: + - content.code.annotate + - navigation.top + - navigation.instant + - navigation.expand + - navigation.sections + - navigation.tabs + - navigation.tabs.sticky +plugins: + - git-revision-date-localized + - search + - tags +# NOTE: this is the recommended configuration from +# https://squidfunk.github.io/mkdocs-material/setup/extensions/#recommended-configuration +markdown_extensions: + - abbr + - admonition + - attr_list + - def_list + - footnotes + - meta + - md_in_html + - toc: + permalink: true + - pymdownx.arithmatex: + generic: true + - pymdownx.betterem: + smart_enable: all + - pymdownx.caret + - pymdownx.details + - pymdownx.emoji: + emoji_index: !!python/name:materialx.emoji.twemoji + emoji_generator: !!python/name:materialx.emoji.to_svg + - pymdownx.highlight + - pymdownx.inlinehilite + - pymdownx.keys + - pymdownx.mark + - pymdownx.smartsymbols + - pymdownx.superfences + - pymdownx.tabbed: + alternate_style: true + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.tilde diff --git a/vendor/github.com/urfave/cli/v2/parse.go b/vendor/github.com/urfave/cli/v2/parse.go index 7df17296a..d79f15a18 100644 --- a/vendor/github.com/urfave/cli/v2/parse.go +++ b/vendor/github.com/urfave/cli/v2/parse.go @@ -26,9 +26,8 @@ func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComple return err } - errStr := err.Error() - trimmed := strings.TrimPrefix(errStr, "flag provided but not defined: -") - if errStr == trimmed { + trimmed, trimErr := flagFromError(err) + if trimErr != nil { return err } @@ -47,7 +46,10 @@ func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComple } // swap current argument with the split version - args = append(args[:i], append(shortOpts, args[i+1:]...)...) + // do not include args that parsed correctly so far as it would + // trigger Value.Set() on those args and would result in + // duplicates for slice type flags + args = append(shortOpts, args[i+1:]...) argsWereSplit = true break } @@ -57,14 +59,20 @@ func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComple if !argsWereSplit { return err } + } +} - // Since custom parsing failed, replace the flag set before retrying - newSet, err := ip.newFlagSet() - if err != nil { - return err - } - *set = *newSet +const providedButNotDefinedErrMsg = "flag provided but not defined: -" + +// flagFromError tries to parse a provided flag from an error message. If the +// parsing fials, it returns the input error and an empty string +func flagFromError(err error) (string, error) { + errStr := err.Error() + trimmed := strings.TrimPrefix(errStr, providedButNotDefinedErrMsg) + if errStr == trimmed { + return "", err } + return trimmed, nil } func splitShortOptions(set *flag.FlagSet, arg string) []string { diff --git a/vendor/github.com/urfave/cli/v2/sliceflag.go b/vendor/github.com/urfave/cli/v2/sliceflag.go new file mode 100644 index 000000000..b2ca59041 --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/sliceflag.go @@ -0,0 +1,290 @@ +package cli + +import ( + "flag" + "reflect" +) + +type ( + // SliceFlag extends implementations like StringSliceFlag and IntSliceFlag with support for using slices directly, + // as Value and/or Destination. + // See also SliceFlagTarget, MultiStringFlag, MultiFloat64Flag, MultiInt64Flag, MultiIntFlag. + SliceFlag[T SliceFlagTarget[E], S ~[]E, E any] struct { + Target T + Value S + Destination *S + } + + // SliceFlagTarget models a target implementation for use with SliceFlag. + // The three methods, SetValue, SetDestination, and GetDestination, are necessary to propagate Value and + // Destination, where Value is propagated inwards (initially), and Destination is propagated outwards (on every + // update). + SliceFlagTarget[E any] interface { + Flag + RequiredFlag + DocGenerationFlag + VisibleFlag + CategorizableFlag + + // SetValue should propagate the given slice to the target, ideally as a new value. + // Note that a nil slice should nil/clear any existing value (modelled as ~[]E). + SetValue(slice []E) + // SetDestination should propagate the given slice to the target, ideally as a new value. + // Note that a nil slice should nil/clear any existing value (modelled as ~*[]E). + SetDestination(slice []E) + // GetDestination should return the current value referenced by any destination, or nil if nil/unset. + GetDestination() []E + } + + // MultiStringFlag extends StringSliceFlag with support for using slices directly, as Value and/or Destination. + // See also SliceFlag. + MultiStringFlag = SliceFlag[*StringSliceFlag, []string, string] + + // MultiFloat64Flag extends Float64SliceFlag with support for using slices directly, as Value and/or Destination. + // See also SliceFlag. + MultiFloat64Flag = SliceFlag[*Float64SliceFlag, []float64, float64] + + // MultiInt64Flag extends Int64SliceFlag with support for using slices directly, as Value and/or Destination. + // See also SliceFlag. + MultiInt64Flag = SliceFlag[*Int64SliceFlag, []int64, int64] + + // MultiIntFlag extends IntSliceFlag with support for using slices directly, as Value and/or Destination. + // See also SliceFlag. + MultiIntFlag = SliceFlag[*IntSliceFlag, []int, int] + + flagValueHook struct { + value Generic + hook func() + } +) + +var ( + // compile time assertions + + _ SliceFlagTarget[string] = (*StringSliceFlag)(nil) + _ SliceFlagTarget[string] = (*SliceFlag[*StringSliceFlag, []string, string])(nil) + _ SliceFlagTarget[string] = (*MultiStringFlag)(nil) + _ SliceFlagTarget[float64] = (*MultiFloat64Flag)(nil) + _ SliceFlagTarget[int64] = (*MultiInt64Flag)(nil) + _ SliceFlagTarget[int] = (*MultiIntFlag)(nil) + + _ Generic = (*flagValueHook)(nil) + _ Serializer = (*flagValueHook)(nil) +) + +func (x *SliceFlag[T, S, E]) Apply(set *flag.FlagSet) error { + x.Target.SetValue(x.convertSlice(x.Value)) + + destination := x.Destination + if destination == nil { + x.Target.SetDestination(nil) + + return x.Target.Apply(set) + } + + x.Target.SetDestination(x.convertSlice(*destination)) + + return applyFlagValueHook(set, x.Target.Apply, func() { + *destination = x.Target.GetDestination() + }) +} + +func (x *SliceFlag[T, S, E]) convertSlice(slice S) []E { + result := make([]E, len(slice)) + copy(result, slice) + return result +} + +func (x *SliceFlag[T, S, E]) SetValue(slice S) { + x.Value = slice +} + +func (x *SliceFlag[T, S, E]) SetDestination(slice S) { + if slice != nil { + x.Destination = &slice + } else { + x.Destination = nil + } +} + +func (x *SliceFlag[T, S, E]) GetDestination() S { + if destination := x.Destination; destination != nil { + return *destination + } + return nil +} + +func (x *SliceFlag[T, S, E]) String() string { return x.Target.String() } +func (x *SliceFlag[T, S, E]) Names() []string { return x.Target.Names() } +func (x *SliceFlag[T, S, E]) IsSet() bool { return x.Target.IsSet() } +func (x *SliceFlag[T, S, E]) IsRequired() bool { return x.Target.IsRequired() } +func (x *SliceFlag[T, S, E]) TakesValue() bool { return x.Target.TakesValue() } +func (x *SliceFlag[T, S, E]) GetUsage() string { return x.Target.GetUsage() } +func (x *SliceFlag[T, S, E]) GetValue() string { return x.Target.GetValue() } +func (x *SliceFlag[T, S, E]) GetDefaultText() string { return x.Target.GetDefaultText() } +func (x *SliceFlag[T, S, E]) GetEnvVars() []string { return x.Target.GetEnvVars() } +func (x *SliceFlag[T, S, E]) IsVisible() bool { return x.Target.IsVisible() } +func (x *SliceFlag[T, S, E]) GetCategory() string { return x.Target.GetCategory() } + +func (x *flagValueHook) Set(value string) error { + if err := x.value.Set(value); err != nil { + return err + } + x.hook() + return nil +} + +func (x *flagValueHook) String() string { + // note: this is necessary due to the way Go's flag package handles defaults + isZeroValue := func(f flag.Value, v string) bool { + /* + https://cs.opensource.google/go/go/+/refs/tags/go1.18.3:src/flag/flag.go;drc=2580d0e08d5e9f979b943758d3c49877fb2324cb;l=453 + + Copyright (c) 2009 The Go Authors. All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + // Build a zero value of the flag's Value type, and see if the + // result of calling its String method equals the value passed in. + // This works unless the Value type is itself an interface type. + typ := reflect.TypeOf(f) + var z reflect.Value + if typ.Kind() == reflect.Pointer { + z = reflect.New(typ.Elem()) + } else { + z = reflect.Zero(typ) + } + return v == z.Interface().(flag.Value).String() + } + if x.value != nil { + // only return non-empty if not the same string as returned by the zero value + if s := x.value.String(); !isZeroValue(x.value, s) { + return s + } + } + return `` +} + +func (x *flagValueHook) Serialize() string { + if value, ok := x.value.(Serializer); ok { + return value.Serialize() + } + return x.String() +} + +// applyFlagValueHook wraps calls apply then wraps flags to call a hook function on update and after initial apply. +func applyFlagValueHook(set *flag.FlagSet, apply func(set *flag.FlagSet) error, hook func()) error { + if apply == nil || set == nil || hook == nil { + panic(`invalid input`) + } + var tmp flag.FlagSet + if err := apply(&tmp); err != nil { + return err + } + tmp.VisitAll(func(f *flag.Flag) { set.Var(&flagValueHook{value: f.Value, hook: hook}, f.Name, f.Usage) }) + hook() + return nil +} + +// newSliceFlagValue is for implementing SliceFlagTarget.SetValue and SliceFlagTarget.SetDestination. +// It's e.g. as part of StringSliceFlag.SetValue, using the factory NewStringSlice. +func newSliceFlagValue[R any, S ~[]E, E any](factory func(defaults ...E) *R, defaults S) *R { + if defaults == nil { + return nil + } + return factory(defaults...) +} + +// unwrapFlagValue strips any/all *flagValueHook wrappers. +func unwrapFlagValue(v flag.Value) flag.Value { + for { + h, ok := v.(*flagValueHook) + if !ok { + return v + } + v = h.value + } +} + +// NOTE: the methods below are in this file to make use of the build constraint + +func (f *Float64SliceFlag) SetValue(slice []float64) { + f.Value = newSliceFlagValue(NewFloat64Slice, slice) +} + +func (f *Float64SliceFlag) SetDestination(slice []float64) { + f.Destination = newSliceFlagValue(NewFloat64Slice, slice) +} + +func (f *Float64SliceFlag) GetDestination() []float64 { + if destination := f.Destination; destination != nil { + return destination.Value() + } + return nil +} + +func (f *Int64SliceFlag) SetValue(slice []int64) { + f.Value = newSliceFlagValue(NewInt64Slice, slice) +} + +func (f *Int64SliceFlag) SetDestination(slice []int64) { + f.Destination = newSliceFlagValue(NewInt64Slice, slice) +} + +func (f *Int64SliceFlag) GetDestination() []int64 { + if destination := f.Destination; destination != nil { + return destination.Value() + } + return nil +} + +func (f *IntSliceFlag) SetValue(slice []int) { + f.Value = newSliceFlagValue(NewIntSlice, slice) +} + +func (f *IntSliceFlag) SetDestination(slice []int) { + f.Destination = newSliceFlagValue(NewIntSlice, slice) +} + +func (f *IntSliceFlag) GetDestination() []int { + if destination := f.Destination; destination != nil { + return destination.Value() + } + return nil +} + +func (f *StringSliceFlag) SetValue(slice []string) { + f.Value = newSliceFlagValue(NewStringSlice, slice) +} + +func (f *StringSliceFlag) SetDestination(slice []string) { + f.Destination = newSliceFlagValue(NewStringSlice, slice) +} + +func (f *StringSliceFlag) GetDestination() []string { + if destination := f.Destination; destination != nil { + return destination.Value() + } + return nil +} diff --git a/vendor/github.com/urfave/cli/v2/suggestions.go b/vendor/github.com/urfave/cli/v2/suggestions.go new file mode 100644 index 000000000..9d2b7a81e --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/suggestions.go @@ -0,0 +1,68 @@ +//go:build !urfave_cli_no_suggest +// +build !urfave_cli_no_suggest + +package cli + +import ( + "fmt" + + "github.com/xrash/smetrics" +) + +func init() { + SuggestFlag = suggestFlag + SuggestCommand = suggestCommand +} + +func jaroWinkler(a, b string) float64 { + // magic values are from https://github.com/xrash/smetrics/blob/039620a656736e6ad994090895784a7af15e0b80/jaro-winkler.go#L8 + const ( + boostThreshold = 0.7 + prefixSize = 4 + ) + return smetrics.JaroWinkler(a, b, boostThreshold, prefixSize) +} + +func suggestFlag(flags []Flag, provided string, hideHelp bool) string { + distance := 0.0 + suggestion := "" + + for _, flag := range flags { + flagNames := flag.Names() + if !hideHelp && HelpFlag != nil { + flagNames = append(flagNames, HelpFlag.Names()...) + } + for _, name := range flagNames { + newDistance := jaroWinkler(name, provided) + if newDistance > distance { + distance = newDistance + suggestion = name + } + } + } + + if len(suggestion) == 1 { + suggestion = "-" + suggestion + } else if len(suggestion) > 1 { + suggestion = "--" + suggestion + } + + return suggestion +} + +// suggestCommand takes a list of commands and a provided string to suggest a +// command name +func suggestCommand(commands []*Command, provided string) (suggestion string) { + distance := 0.0 + for _, command := range commands { + for _, name := range append(command.Names(), helpName, helpAlias) { + newDistance := jaroWinkler(name, provided) + if newDistance > distance { + distance = newDistance + suggestion = name + } + } + } + + return fmt.Sprintf(SuggestDidYouMeanTemplate, suggestion) +} diff --git a/vendor/github.com/urfave/cli/v2/template.go b/vendor/github.com/urfave/cli/v2/template.go index aee3e0494..5748f4c20 100644 --- a/vendor/github.com/urfave/cli/v2/template.go +++ b/vendor/github.com/urfave/cli/v2/template.go @@ -1,82 +1,103 @@ package cli +var helpNameTemplate = `{{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}}` +var usageTemplate = `{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}}{{if .ArgsUsage}}{{.ArgsUsage}}{{else}}{{if .Args}} [arguments...]{{end}}{{end}}{{end}}` +var descriptionTemplate = `{{wrap .Description 3}}` +var authorsTemplate = `{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: + {{range $index, $author := .Authors}}{{if $index}} + {{end}}{{$author}}{{end}}` +var visibleCommandTemplate = `{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}} + {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}` +var visibleCommandCategoryTemplate = `{{range .VisibleCategories}}{{if .Name}} + {{.Name}}:{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{template "visibleCommandTemplate" .}}{{end}}{{end}}` +var visibleFlagCategoryTemplate = `{{range .VisibleFlagCategories}} + {{if .Name}}{{.Name}} + + {{end}}{{$flglen := len .Flags}}{{range $i, $e := .Flags}}{{if eq (subtract $flglen $i) 1}}{{$e}} +{{else}}{{$e}} + {{end}}{{end}}{{end}}` + +var visibleFlagTemplate = `{{range $i, $e := .VisibleFlags}} + {{wrap $e.String 6}}{{end}}` + +var versionTemplate = `{{if .Version}}{{if not .HideVersion}} + +VERSION: + {{.Version}}{{end}}{{end}}` + +var copyrightTemplate = `{{wrap .Copyright 3}}` + // AppHelpTemplate is the text template for the Default help topic. // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var AppHelpTemplate = `NAME: - {{.Name}}{{if .Usage}} - {{.Usage}}{{end}} + {{template "helpNameTemplate" .}} USAGE: - {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} + {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}{{if .Args}}[arguments...]{{end}}{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} VERSION: {{.Version}}{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{.Description}}{{end}}{{if len .Authors}} + {{template "descriptionTemplate" .}}{{end}} +{{- if len .Authors}} -AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: - {{range $index, $author := .Authors}}{{if $index}} - {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} +AUTHOR{{template "authorsTemplate" .}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} +COMMANDS:{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}} + +GLOBAL OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -GLOBAL OPTIONS: - {{range $index, $option := .VisibleFlags}}{{if $index}} - {{end}}{{$option}}{{end}}{{end}}{{if .Copyright}} +GLOBAL OPTIONS:{{template "visibleFlagTemplate" .}}{{end}}{{if .Copyright}} COPYRIGHT: - {{.Copyright}}{{end}} + {{template "copyrightTemplate" .}}{{end}} ` // CommandHelpTemplate is the text template for the command help topic. // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var CommandHelpTemplate = `NAME: - {{.HelpName}} - {{.Usage}} + {{template "helpNameTemplate" .}} USAGE: - {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} + {{template "usageTemplate" .}}{{if .Category}} CATEGORY: {{.Category}}{{end}}{{if .Description}} DESCRIPTION: - {{.Description}}{{end}}{{if .VisibleFlags}} + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleFlagCategories}} + +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -OPTIONS: - {{range .VisibleFlags}}{{.}} - {{end}}{{end}} +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}} ` // SubcommandHelpTemplate is the text template for the subcommand help topic. // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var SubcommandHelpTemplate = `NAME: - {{.HelpName}} - {{.Usage}} + {{template "helpNameTemplate" .}} USAGE: - {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}} + {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}{{if .Args}}[arguments...]{{end}}{{end}}{{end}}{{if .Description}} DESCRIPTION: - {{.Description}}{{end}} + {{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}} -COMMANDS:{{range .VisibleCategories}}{{if .Name}} - {{.Name}}:{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} +COMMANDS:{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}} + +OPTIONS:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}} -OPTIONS: - {{range .VisibleFlags}}{{.}} - {{end}}{{end}} +OPTIONS:{{template "visibleFlagTemplate" .}}{{end}} ` -var MarkdownDocTemplate = `% {{ .App.Name }} 8 +var MarkdownDocTemplate = `{{if gt .SectionNum 0}}% {{ .App.Name }} {{ .SectionNum }} -# NAME +{{end}}# NAME {{ .App.Name }}{{ if .App.Usage }} - {{ .App.Usage }}{{ end }} @@ -86,16 +107,18 @@ var MarkdownDocTemplate = `% {{ .App.Name }} 8 {{ if .SynopsisArgs }} ` + "```" + ` {{ range $v := .SynopsisArgs }}{{ $v }}{{ end }}` + "```" + ` -{{ end }}{{ if .App.UsageText }} +{{ end }}{{ if .App.Description }} # DESCRIPTION -{{ .App.UsageText }} +{{ .App.Description }} {{ end }} **Usage**: -` + "```" + ` +` + "```" + `{{ if .App.UsageText }} +{{ .App.UsageText }} +{{ else }} {{ .App.Name }} [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] -` + "```" + ` +{{ end }}` + "```" + ` {{ if .GlobalArgs }} # GLOBAL OPTIONS {{ range $v := .GlobalArgs }} diff --git a/vendor/github.com/urfave/cli/v2/zz_generated.flags.go b/vendor/github.com/urfave/cli/v2/zz_generated.flags.go new file mode 100644 index 000000000..f2fc8c88b --- /dev/null +++ b/vendor/github.com/urfave/cli/v2/zz_generated.flags.go @@ -0,0 +1,865 @@ +// WARNING: this file is generated. DO NOT EDIT + +package cli + +import "time" + +// Float64SliceFlag is a flag with type *Float64Slice +type Float64SliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *Float64Slice + Destination *Float64Slice + + Aliases []string + EnvVars []string + + defaultValue *Float64Slice + defaultValueSet bool + + separator separatorSpec + + Action func(*Context, []float64) error +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Float64SliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *Float64SliceFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *Float64SliceFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *Float64SliceFlag) IsVisible() bool { + return !f.Hidden +} + +// GenericFlag is a flag with type Generic +type GenericFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value Generic + Destination Generic + + Aliases []string + EnvVars []string + + defaultValue Generic + defaultValueSet bool + + TakesFile bool + + Action func(*Context, interface{}) error +} + +// String returns a readable representation of this value (for usage defaults) +func (f *GenericFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *GenericFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *GenericFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *GenericFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *GenericFlag) IsVisible() bool { + return !f.Hidden +} + +// Int64SliceFlag is a flag with type *Int64Slice +type Int64SliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *Int64Slice + Destination *Int64Slice + + Aliases []string + EnvVars []string + + defaultValue *Int64Slice + defaultValueSet bool + + separator separatorSpec + + Action func(*Context, []int64) error +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Int64SliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *Int64SliceFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *Int64SliceFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *Int64SliceFlag) IsVisible() bool { + return !f.Hidden +} + +// IntSliceFlag is a flag with type *IntSlice +type IntSliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *IntSlice + Destination *IntSlice + + Aliases []string + EnvVars []string + + defaultValue *IntSlice + defaultValueSet bool + + separator separatorSpec + + Action func(*Context, []int) error +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *IntSliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *IntSliceFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *IntSliceFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *IntSliceFlag) IsVisible() bool { + return !f.Hidden +} + +// PathFlag is a flag with type Path +type PathFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value Path + Destination *Path + + Aliases []string + EnvVars []string + + defaultValue Path + defaultValueSet bool + + TakesFile bool + + Action func(*Context, Path) error +} + +// String returns a readable representation of this value (for usage defaults) +func (f *PathFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *PathFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *PathFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *PathFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *PathFlag) IsVisible() bool { + return !f.Hidden +} + +// StringSliceFlag is a flag with type *StringSlice +type StringSliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *StringSlice + Destination *StringSlice + + Aliases []string + EnvVars []string + + defaultValue *StringSlice + defaultValueSet bool + + separator separatorSpec + + TakesFile bool + + Action func(*Context, []string) error + + KeepSpace bool +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *StringSliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *StringSliceFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *StringSliceFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *StringSliceFlag) IsVisible() bool { + return !f.Hidden +} + +// TimestampFlag is a flag with type *Timestamp +type TimestampFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *Timestamp + Destination *Timestamp + + Aliases []string + EnvVars []string + + defaultValue *Timestamp + defaultValueSet bool + + Layout string + + Timezone *time.Location + + Action func(*Context, *time.Time) error +} + +// String returns a readable representation of this value (for usage defaults) +func (f *TimestampFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *TimestampFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *TimestampFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *TimestampFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *TimestampFlag) IsVisible() bool { + return !f.Hidden +} + +// Uint64SliceFlag is a flag with type *Uint64Slice +type Uint64SliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *Uint64Slice + Destination *Uint64Slice + + Aliases []string + EnvVars []string + + defaultValue *Uint64Slice + defaultValueSet bool + + separator separatorSpec + + Action func(*Context, []uint64) error +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Uint64SliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *Uint64SliceFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *Uint64SliceFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *Uint64SliceFlag) IsVisible() bool { + return !f.Hidden +} + +// UintSliceFlag is a flag with type *UintSlice +type UintSliceFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value *UintSlice + Destination *UintSlice + + Aliases []string + EnvVars []string + + defaultValue *UintSlice + defaultValueSet bool + + separator separatorSpec + + Action func(*Context, []uint) error +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *UintSliceFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *UintSliceFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *UintSliceFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *UintSliceFlag) IsVisible() bool { + return !f.Hidden +} + +// BoolFlag is a flag with type bool +type BoolFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value bool + Destination *bool + + Aliases []string + EnvVars []string + + defaultValue bool + defaultValueSet bool + + Count *int + + DisableDefaultText bool + + Action func(*Context, bool) error +} + +// String returns a readable representation of this value (for usage defaults) +func (f *BoolFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *BoolFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *BoolFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *BoolFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *BoolFlag) IsVisible() bool { + return !f.Hidden +} + +// Float64Flag is a flag with type float64 +type Float64Flag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value float64 + Destination *float64 + + Aliases []string + EnvVars []string + + defaultValue float64 + defaultValueSet bool + + Action func(*Context, float64) error +} + +// String returns a readable representation of this value (for usage defaults) +func (f *Float64Flag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Float64Flag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *Float64Flag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *Float64Flag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *Float64Flag) IsVisible() bool { + return !f.Hidden +} + +// IntFlag is a flag with type int +type IntFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value int + Destination *int + + Aliases []string + EnvVars []string + + defaultValue int + defaultValueSet bool + + Base int + + Action func(*Context, int) error +} + +// String returns a readable representation of this value (for usage defaults) +func (f *IntFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *IntFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *IntFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *IntFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *IntFlag) IsVisible() bool { + return !f.Hidden +} + +// Int64Flag is a flag with type int64 +type Int64Flag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value int64 + Destination *int64 + + Aliases []string + EnvVars []string + + defaultValue int64 + defaultValueSet bool + + Base int + + Action func(*Context, int64) error +} + +// String returns a readable representation of this value (for usage defaults) +func (f *Int64Flag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Int64Flag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *Int64Flag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *Int64Flag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *Int64Flag) IsVisible() bool { + return !f.Hidden +} + +// StringFlag is a flag with type string +type StringFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value string + Destination *string + + Aliases []string + EnvVars []string + + defaultValue string + defaultValueSet bool + + TakesFile bool + + Action func(*Context, string) error +} + +// String returns a readable representation of this value (for usage defaults) +func (f *StringFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *StringFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *StringFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *StringFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *StringFlag) IsVisible() bool { + return !f.Hidden +} + +// DurationFlag is a flag with type time.Duration +type DurationFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value time.Duration + Destination *time.Duration + + Aliases []string + EnvVars []string + + defaultValue time.Duration + defaultValueSet bool + + Action func(*Context, time.Duration) error +} + +// String returns a readable representation of this value (for usage defaults) +func (f *DurationFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *DurationFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *DurationFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *DurationFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *DurationFlag) IsVisible() bool { + return !f.Hidden +} + +// UintFlag is a flag with type uint +type UintFlag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value uint + Destination *uint + + Aliases []string + EnvVars []string + + defaultValue uint + defaultValueSet bool + + Base int + + Action func(*Context, uint) error +} + +// String returns a readable representation of this value (for usage defaults) +func (f *UintFlag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *UintFlag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *UintFlag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *UintFlag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *UintFlag) IsVisible() bool { + return !f.Hidden +} + +// Uint64Flag is a flag with type uint64 +type Uint64Flag struct { + Name string + + Category string + DefaultText string + FilePath string + Usage string + + Required bool + Hidden bool + HasBeenSet bool + + Value uint64 + Destination *uint64 + + Aliases []string + EnvVars []string + + defaultValue uint64 + defaultValueSet bool + + Base int + + Action func(*Context, uint64) error +} + +// String returns a readable representation of this value (for usage defaults) +func (f *Uint64Flag) String() string { + return FlagStringer(f) +} + +// IsSet returns whether or not the flag has been set through env or file +func (f *Uint64Flag) IsSet() bool { + return f.HasBeenSet +} + +// Names returns the names of the flag +func (f *Uint64Flag) Names() []string { + return FlagNames(f.Name, f.Aliases) +} + +// IsRequired returns whether or not the flag is required +func (f *Uint64Flag) IsRequired() bool { + return f.Required +} + +// IsVisible returns true if the flag is not hidden, otherwise false +func (f *Uint64Flag) IsVisible() bool { + return !f.Hidden +} + +// vim:ro diff --git a/vendor/github.com/xrash/smetrics/.travis.yml b/vendor/github.com/xrash/smetrics/.travis.yml new file mode 100644 index 000000000..d1cd67ff9 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/.travis.yml @@ -0,0 +1,9 @@ +language: go +go: + - 1.11 + - 1.12 + - 1.13 + - 1.14.x + - master +script: + - cd tests && make diff --git a/vendor/github.com/xrash/smetrics/LICENSE b/vendor/github.com/xrash/smetrics/LICENSE new file mode 100644 index 000000000..80445682f --- /dev/null +++ b/vendor/github.com/xrash/smetrics/LICENSE @@ -0,0 +1,21 @@ +Copyright (C) 2016 Felipe da Cunha Gonçalves +All Rights Reserved. + +MIT LICENSE + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/xrash/smetrics/README.md b/vendor/github.com/xrash/smetrics/README.md new file mode 100644 index 000000000..5e0c1a463 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/README.md @@ -0,0 +1,49 @@ +[![Build Status](https://travis-ci.org/xrash/smetrics.svg?branch=master)](http://travis-ci.org/xrash/smetrics) + +# smetrics + +`smetrics` is "string metrics". + +Package smetrics provides a bunch of algorithms for calculating the distance between strings. + +There are implementations for calculating the popular Levenshtein distance (aka Edit Distance or Wagner-Fischer), as well as the Jaro distance, the Jaro-Winkler distance, and more. + +# How to import + +```go +import "github.com/xrash/smetrics" +``` + +# Documentation + +Go to [https://pkg.go.dev/github.com/xrash/smetrics](https://pkg.go.dev/github.com/xrash/smetrics) for complete documentation. + +# Example + +```go +package main + +import ( + "github.com/xrash/smetrics" +) + +func main() { + smetrics.WagnerFischer("POTATO", "POTATTO", 1, 1, 2) + smetrics.WagnerFischer("MOUSE", "HOUSE", 2, 2, 4) + + smetrics.Ukkonen("POTATO", "POTATTO", 1, 1, 2) + smetrics.Ukkonen("MOUSE", "HOUSE", 2, 2, 4) + + smetrics.Jaro("AL", "AL") + smetrics.Jaro("MARTHA", "MARHTA") + + smetrics.JaroWinkler("AL", "AL", 0.7, 4) + smetrics.JaroWinkler("MARTHA", "MARHTA", 0.7, 4) + + smetrics.Soundex("Euler") + smetrics.Soundex("Ellery") + + smetrics.Hamming("aaa", "aaa") + smetrics.Hamming("aaa", "aab") +} +``` diff --git a/vendor/github.com/xrash/smetrics/doc.go b/vendor/github.com/xrash/smetrics/doc.go new file mode 100644 index 000000000..21bc986c9 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/doc.go @@ -0,0 +1,19 @@ +/* +Package smetrics provides a bunch of algorithms for calculating +the distance between strings. + +There are implementations for calculating the popular Levenshtein +distance (aka Edit Distance or Wagner-Fischer), as well as the Jaro +distance, the Jaro-Winkler distance, and more. + +For the Levenshtein distance, you can use the functions WagnerFischer() +and Ukkonen(). Read the documentation on these functions. + +For the Jaro and Jaro-Winkler algorithms, check the functions +Jaro() and JaroWinkler(). Read the documentation on these functions. + +For the Soundex algorithm, check the function Soundex(). + +For the Hamming distance algorithm, check the function Hamming(). +*/ +package smetrics diff --git a/vendor/github.com/xrash/smetrics/hamming.go b/vendor/github.com/xrash/smetrics/hamming.go new file mode 100644 index 000000000..505d3e5da --- /dev/null +++ b/vendor/github.com/xrash/smetrics/hamming.go @@ -0,0 +1,25 @@ +package smetrics + +import ( + "fmt" +) + +// The Hamming distance is the minimum number of substitutions required to change string A into string B. Both strings must have the same size. If the strings have different sizes, the function returns an error. +func Hamming(a, b string) (int, error) { + al := len(a) + bl := len(b) + + if al != bl { + return -1, fmt.Errorf("strings are not equal (len(a)=%d, len(b)=%d)", al, bl) + } + + var difference = 0 + + for i := range a { + if a[i] != b[i] { + difference = difference + 1 + } + } + + return difference, nil +} diff --git a/vendor/github.com/xrash/smetrics/jaro-winkler.go b/vendor/github.com/xrash/smetrics/jaro-winkler.go new file mode 100644 index 000000000..abdb28883 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/jaro-winkler.go @@ -0,0 +1,28 @@ +package smetrics + +import ( + "math" +) + +// The Jaro-Winkler distance. The result is 1 for equal strings, and 0 for completely different strings. It is commonly used on Record Linkage stuff, thus it tries to be accurate for common typos when writing real names such as person names and street names. +// Jaro-Winkler is a modification of the Jaro algorithm. It works by first running Jaro, then boosting the score of exact matches at the beginning of the strings. Because of that, it introduces two more parameters: the boostThreshold and the prefixSize. These are commonly set to 0.7 and 4, respectively. +func JaroWinkler(a, b string, boostThreshold float64, prefixSize int) float64 { + j := Jaro(a, b) + + if j <= boostThreshold { + return j + } + + prefixSize = int(math.Min(float64(len(a)), math.Min(float64(prefixSize), float64(len(b))))) + + var prefixMatch float64 + for i := 0; i < prefixSize; i++ { + if a[i] == b[i] { + prefixMatch++ + } else { + break + } + } + + return j + 0.1*prefixMatch*(1.0-j) +} diff --git a/vendor/github.com/xrash/smetrics/jaro.go b/vendor/github.com/xrash/smetrics/jaro.go new file mode 100644 index 000000000..75f924e11 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/jaro.go @@ -0,0 +1,86 @@ +package smetrics + +import ( + "math" +) + +// The Jaro distance. The result is 1 for equal strings, and 0 for completely different strings. +func Jaro(a, b string) float64 { + // If both strings are zero-length, they are completely equal, + // therefore return 1. + if len(a) == 0 && len(b) == 0 { + return 1 + } + + // If one string is zero-length, strings are completely different, + // therefore return 0. + if len(a) == 0 || len(b) == 0 { + return 0 + } + + // Define the necessary variables for the algorithm. + la := float64(len(a)) + lb := float64(len(b)) + matchRange := int(math.Max(0, math.Floor(math.Max(la, lb)/2.0)-1)) + matchesA := make([]bool, len(a)) + matchesB := make([]bool, len(b)) + var matches float64 = 0 + + // Step 1: Matches + // Loop through each character of the first string, + // looking for a matching character in the second string. + for i := 0; i < len(a); i++ { + start := int(math.Max(0, float64(i-matchRange))) + end := int(math.Min(lb-1, float64(i+matchRange))) + + for j := start; j <= end; j++ { + if matchesB[j] { + continue + } + + if a[i] == b[j] { + matchesA[i] = true + matchesB[j] = true + matches++ + break + } + } + } + + // If there are no matches, strings are completely different, + // therefore return 0. + if matches == 0 { + return 0 + } + + // Step 2: Transpositions + // Loop through the matches' arrays, looking for + // unaligned matches. Count the number of unaligned matches. + unaligned := 0 + j := 0 + for i := 0; i < len(a); i++ { + if !matchesA[i] { + continue + } + + for !matchesB[j] { + j++ + } + + if a[i] != b[j] { + unaligned++ + } + + j++ + } + + // The number of unaligned matches divided by two, is the number of _transpositions_. + transpositions := math.Floor(float64(unaligned / 2)) + + // Jaro distance is the average between these three numbers: + // 1. matches / length of string A + // 2. matches / length of string B + // 3. (matches - transpositions/matches) + // So, all that divided by three is the final result. + return ((matches / la) + (matches / lb) + ((matches - transpositions) / matches)) / 3.0 +} diff --git a/vendor/github.com/xrash/smetrics/soundex.go b/vendor/github.com/xrash/smetrics/soundex.go new file mode 100644 index 000000000..18c3aef72 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/soundex.go @@ -0,0 +1,63 @@ +package smetrics + +import ( + "strings" +) + +// The Soundex encoding. It is a phonetic algorithm that considers how the words sound in English. Soundex maps a string to a 4-byte code consisting of the first letter of the original string and three numbers. Strings that sound similar should map to the same code. +func Soundex(s string) string { + b := strings.Builder{} + b.Grow(4) + + p := s[0] + if p <= 'z' && p >= 'a' { + p -= 32 // convert to uppercase + } + b.WriteByte(p) + + n := 0 + for i := 1; i < len(s); i++ { + c := s[i] + + if c <= 'z' && c >= 'a' { + c -= 32 // convert to uppercase + } else if c < 'A' || c > 'Z' { + continue + } + + if c == p { + continue + } + + p = c + + switch c { + case 'B', 'P', 'F', 'V': + c = '1' + case 'C', 'S', 'K', 'G', 'J', 'Q', 'X', 'Z': + c = '2' + case 'D', 'T': + c = '3' + case 'L': + c = '4' + case 'M', 'N': + c = '5' + case 'R': + c = '6' + default: + continue + } + + b.WriteByte(c) + n++ + if n == 3 { + break + } + } + + for i := n; i < 3; i++ { + b.WriteByte('0') + } + + return b.String() +} diff --git a/vendor/github.com/xrash/smetrics/ukkonen.go b/vendor/github.com/xrash/smetrics/ukkonen.go new file mode 100644 index 000000000..3c5579cd9 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/ukkonen.go @@ -0,0 +1,94 @@ +package smetrics + +import ( + "math" +) + +// The Ukkonen algorithm for calculating the Levenshtein distance. The algorithm is described in http://www.cs.helsinki.fi/u/ukkonen/InfCont85.PDF, or in docs/InfCont85.PDF. It runs on O(t . min(m, n)) where t is the actual distance between strings a and b. It needs O(min(t, m, n)) space. This function might be preferred over WagnerFischer() for *very* similar strings. But test it out yourself. +// The first two parameters are the two strings to be compared. The last three parameters are the insertion cost, the deletion cost and the substitution cost. These are normally defined as 1, 1 and 2 respectively. +func Ukkonen(a, b string, icost, dcost, scost int) int { + var lowerCost int + + if icost < dcost && icost < scost { + lowerCost = icost + } else if dcost < scost { + lowerCost = dcost + } else { + lowerCost = scost + } + + infinite := math.MaxInt32 / 2 + + var r []int + var k, kprime, p, t int + var ins, del, sub int + + if len(a) > len(b) { + t = (len(a) - len(b) + 1) * lowerCost + } else { + t = (len(b) - len(a) + 1) * lowerCost + } + + for { + if (t / lowerCost) < (len(b) - len(a)) { + continue + } + + // This is the right damn thing since the original Ukkonen + // paper minimizes the expression result only, but the uncommented version + // doesn't need to deal with floats so it's faster. + // p = int(math.Floor(0.5*((float64(t)/float64(lowerCost)) - float64(len(b) - len(a))))) + p = ((t / lowerCost) - (len(b) - len(a))) / 2 + + k = -p + kprime = k + + rowlength := (len(b) - len(a)) + (2 * p) + + r = make([]int, rowlength+2) + + for i := 0; i < rowlength+2; i++ { + r[i] = infinite + } + + for i := 0; i <= len(a); i++ { + for j := 0; j <= rowlength; j++ { + if i == j+k && i == 0 { + r[j] = 0 + } else { + if j-1 < 0 { + ins = infinite + } else { + ins = r[j-1] + icost + } + + del = r[j+1] + dcost + sub = r[j] + scost + + if i-1 < 0 || i-1 >= len(a) || j+k-1 >= len(b) || j+k-1 < 0 { + sub = infinite + } else if a[i-1] == b[j+k-1] { + sub = r[j] + } + + if ins < del && ins < sub { + r[j] = ins + } else if del < sub { + r[j] = del + } else { + r[j] = sub + } + } + } + k++ + } + + if r[(len(b)-len(a))+(2*p)+kprime] <= t { + break + } else { + t *= 2 + } + } + + return r[(len(b)-len(a))+(2*p)+kprime] +} diff --git a/vendor/github.com/xrash/smetrics/wagner-fischer.go b/vendor/github.com/xrash/smetrics/wagner-fischer.go new file mode 100644 index 000000000..9883aea04 --- /dev/null +++ b/vendor/github.com/xrash/smetrics/wagner-fischer.go @@ -0,0 +1,48 @@ +package smetrics + +// The Wagner-Fischer algorithm for calculating the Levenshtein distance. +// The first two parameters are the two strings to be compared. The last three parameters are the insertion cost, the deletion cost and the substitution cost. These are normally defined as 1, 1 and 2 respectively. +func WagnerFischer(a, b string, icost, dcost, scost int) int { + + // Allocate both rows. + row1 := make([]int, len(b)+1) + row2 := make([]int, len(b)+1) + var tmp []int + + // Initialize the first row. + for i := 1; i <= len(b); i++ { + row1[i] = i * icost + } + + // For each row... + for i := 1; i <= len(a); i++ { + row2[0] = i * dcost + + // For each column... + for j := 1; j <= len(b); j++ { + if a[i-1] == b[j-1] { + row2[j] = row1[j-1] + } else { + ins := row2[j-1] + icost + del := row1[j] + dcost + sub := row1[j-1] + scost + + if ins < del && ins < sub { + row2[j] = ins + } else if del < sub { + row2[j] = del + } else { + row2[j] = sub + } + } + } + + // Swap the rows at the end of each row. + tmp = row1 + row1 = row2 + row2 = tmp + } + + // Because we swapped the rows, the final result is in row1 instead of row2. + return row1[len(row1)-1] +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 11583cc9e..9bd2c63e5 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -79,7 +79,7 @@ github.com/containernetworking/plugins/pkg/utils/sysctl # github.com/coreos/go-iptables v0.6.0 ## explicit; go 1.16 github.com/coreos/go-iptables/iptables -# github.com/cpuguy83/go-md2man/v2 v2.0.3 +# github.com/cpuguy83/go-md2man/v2 v2.0.4 ## explicit; go 1.11 github.com/cpuguy83/go-md2man/v2/md2man # github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc @@ -340,7 +340,7 @@ github.com/ovn-org/libovsdb/model github.com/ovn-org/libovsdb/ovsdb github.com/ovn-org/libovsdb/ovsdb/serverdb github.com/ovn-org/libovsdb/updates -# github.com/ovn-org/ovn-kubernetes/go-controller v0.0.0-20240902083137-5d2310e77f87 +# github.com/ovn-org/ovn-kubernetes/go-controller v0.0.0-20240902083137-5d2310e77f87 => github.com/npinaeva/ovn-kubernetes/go-controller v0.0.0-20241022150829-c03e72d94693 ## explicit; go 1.22.0 github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/ovsdb github.com/ovn-org/ovn-kubernetes/go-controller/observability-lib/sampledecoder @@ -511,8 +511,8 @@ github.com/stretchr/objx github.com/stretchr/testify/assert github.com/stretchr/testify/mock github.com/stretchr/testify/require -# github.com/urfave/cli/v2 v2.2.0 -## explicit; go 1.11 +# github.com/urfave/cli/v2 v2.27.2 +## explicit; go 1.18 github.com/urfave/cli/v2 # github.com/vishvananda/netlink v1.3.0 ## explicit; go 1.12 @@ -550,6 +550,9 @@ github.com/xdg-go/scram # github.com/xdg-go/stringprep v1.0.4 ## explicit; go 1.11 github.com/xdg-go/stringprep +# github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 +## explicit; go 1.15.0 +github.com/xrash/smetrics # go.opentelemetry.io/otel v1.29.0 ## explicit; go 1.21 go.opentelemetry.io/otel @@ -1293,3 +1296,4 @@ sigs.k8s.io/structured-merge-diff/v4/value ## explicit; go 1.12 sigs.k8s.io/yaml sigs.k8s.io/yaml/goyaml.v2 +# github.com/ovn-org/ovn-kubernetes/go-controller => github.com/npinaeva/ovn-kubernetes/go-controller v0.0.0-20241022150829-c03e72d94693