From 1a91d832b12b039940673edc36d29374c8d8f445 Mon Sep 17 00:00:00 2001 From: Per Goncalves da Silva Date: Fri, 7 Jun 2024 14:45:55 +0200 Subject: [PATCH 1/9] make flake attempts an optional parameter Signed-off-by: Per Goncalves da Silva --- Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f54fb286fe..62827f582e 100644 --- a/Makefile +++ b/Makefile @@ -247,8 +247,7 @@ E2E_TIMEOUT ?= 90m E2E_TEST_NS ?= operators E2E_INSTALL_NS ?= operator-lifecycle-manager E2E_CATALOG_NS ?= $(E2E_INSTALL_NS) -E2E_FLAKE_ATTEMPTS ?= 1 -GINKGO_OPTS += -v -randomize-suites -race -trace --show-node-events --flake-attempts=$(E2E_FLAKE_ATTEMPTS) $(if $(E2E_SEED),-seed '$(E2E_SEED)') $(if $(TEST),-focus '$(TEST)',) $(if $(SKIP), -skip '$(SKIP)') +GINKGO_OPTS += -v -randomize-suites -race -trace --show-node-events $(if $(E2E_FLAKE_ATTEMPTS),-flake-attempts=$(E2E_FLAKE_ATTEMPTS) ) $(if $(E2E_SEED),-seed '$(E2E_SEED)' ) $(if $(TEST),-focus '$(TEST)', ) $(if $(SKIP), -skip '$(SKIP)') .PHONY: e2e e2e: #HELP Run e2e tests against a cluster running OLM (params: $E2E_TEST_NS (operator), $E2E_INSTALL_NS (operator-lifecycle-manager), $E2E_CATALOG_NS (operator-lifecycle-manager), $E2E_TIMEOUT (90m), $E2E_FLAKE_ATTEMPTS (1), $TEST(undefined)) From af54346c0bcd83db1d7241257ec43604db776387 Mon Sep 17 00:00:00 2001 From: Per Goncalves da Silva Date: Mon, 10 Jun 2024 11:20:56 +0200 Subject: [PATCH 2/9] add opm to tools Signed-off-by: Per Goncalves da Silva --- go.mod | 19 + go.sum | 24 + scripts/e2e_test_fixtures.sh | 120 + tools.go | 3 + vendor/github.com/Azure/go-ansiterm/LICENSE | 21 + vendor/github.com/Azure/go-ansiterm/README.md | 12 + .../github.com/Azure/go-ansiterm/SECURITY.md | 41 + .../github.com/Azure/go-ansiterm/constants.go | 188 ++ .../github.com/Azure/go-ansiterm/context.go | 7 + .../Azure/go-ansiterm/csi_entry_state.go | 49 + .../Azure/go-ansiterm/csi_param_state.go | 38 + .../go-ansiterm/escape_intermediate_state.go | 36 + .../Azure/go-ansiterm/escape_state.go | 47 + .../Azure/go-ansiterm/event_handler.go | 90 + .../Azure/go-ansiterm/ground_state.go | 24 + .../Azure/go-ansiterm/osc_string_state.go | 31 + vendor/github.com/Azure/go-ansiterm/parser.go | 151 ++ .../go-ansiterm/parser_action_helpers.go | 99 + .../Azure/go-ansiterm/parser_actions.go | 119 + vendor/github.com/Azure/go-ansiterm/states.go | 71 + .../github.com/Azure/go-ansiterm/utilities.go | 21 + .../Azure/go-ansiterm/winterm/ansi.go | 196 ++ .../Azure/go-ansiterm/winterm/api.go | 327 +++ .../go-ansiterm/winterm/attr_translation.go | 100 + .../go-ansiterm/winterm/cursor_helpers.go | 101 + .../go-ansiterm/winterm/erase_helpers.go | 84 + .../go-ansiterm/winterm/scroll_helper.go | 118 + .../Azure/go-ansiterm/winterm/utilities.go | 9 + .../go-ansiterm/winterm/win_event_handler.go | 743 ++++++ vendor/github.com/MakeNowJust/heredoc/LICENSE | 21 + .../github.com/MakeNowJust/heredoc/README.md | 52 + .../github.com/MakeNowJust/heredoc/heredoc.go | 105 + vendor/github.com/akrylysov/pogreb/.gitignore | 2 + .../github.com/akrylysov/pogreb/CHANGELOG.md | 59 + vendor/github.com/akrylysov/pogreb/LICENSE | 201 ++ vendor/github.com/akrylysov/pogreb/README.md | 113 + .../github.com/akrylysov/pogreb/appveyor.yml | 15 + vendor/github.com/akrylysov/pogreb/bucket.go | 126 + .../github.com/akrylysov/pogreb/compaction.go | 160 ++ vendor/github.com/akrylysov/pogreb/datalog.go | 261 ++ vendor/github.com/akrylysov/pogreb/db.go | 397 +++ vendor/github.com/akrylysov/pogreb/doc.go | 4 + vendor/github.com/akrylysov/pogreb/errors.go | 14 + vendor/github.com/akrylysov/pogreb/file.go | 107 + vendor/github.com/akrylysov/pogreb/fs/fs.go | 63 + vendor/github.com/akrylysov/pogreb/fs/mem.go | 234 ++ vendor/github.com/akrylysov/pogreb/fs/os.go | 64 + .../github.com/akrylysov/pogreb/fs/os_mmap.go | 163 ++ .../akrylysov/pogreb/fs/os_mmap_unix.go | 34 + .../akrylysov/pogreb/fs/os_mmap_windows.go | 45 + .../pogreb/fs/os_mmap_windows_386.go | 7 + .../pogreb/fs/os_mmap_windows_amd64.go | 3 + .../github.com/akrylysov/pogreb/fs/os_unix.go | 26 + .../akrylysov/pogreb/fs/os_windows.go | 60 + vendor/github.com/akrylysov/pogreb/fs/sub.go | 52 + vendor/github.com/akrylysov/pogreb/gobfile.go | 27 + vendor/github.com/akrylysov/pogreb/header.go | 43 + vendor/github.com/akrylysov/pogreb/index.go | 363 +++ .../pogreb/internal/errors/errors.go | 42 + .../pogreb/internal/hash/murmurhash32.go | 55 + .../akrylysov/pogreb/internal/hash/seed.go | 15 + .../github.com/akrylysov/pogreb/iterator.go | 75 + vendor/github.com/akrylysov/pogreb/lock.go | 15 + vendor/github.com/akrylysov/pogreb/logger.go | 15 + vendor/github.com/akrylysov/pogreb/metrics.go | 11 + vendor/github.com/akrylysov/pogreb/options.go | 52 + .../github.com/akrylysov/pogreb/recovery.go | 161 ++ vendor/github.com/akrylysov/pogreb/segment.go | 156 ++ vendor/github.com/go-git/gcfg/.gitignore | 1 + vendor/github.com/go-git/gcfg/LICENSE | 28 + vendor/github.com/go-git/gcfg/Makefile | 17 + vendor/github.com/go-git/gcfg/README | 4 + vendor/github.com/go-git/gcfg/doc.go | 145 ++ vendor/github.com/go-git/gcfg/errors.go | 41 + vendor/github.com/go-git/gcfg/read.go | 273 ++ .../github.com/go-git/gcfg/scanner/errors.go | 121 + .../github.com/go-git/gcfg/scanner/scanner.go | 334 +++ vendor/github.com/go-git/gcfg/set.go | 334 +++ .../github.com/go-git/gcfg/token/position.go | 435 ++++ .../github.com/go-git/gcfg/token/serialize.go | 56 + vendor/github.com/go-git/gcfg/token/token.go | 83 + vendor/github.com/go-git/gcfg/types/bool.go | 23 + vendor/github.com/go-git/gcfg/types/doc.go | 4 + vendor/github.com/go-git/gcfg/types/enum.go | 44 + vendor/github.com/go-git/gcfg/types/int.go | 86 + vendor/github.com/go-git/gcfg/types/scan.go | 23 + .../github.com/go-git/go-billy/v5/.gitignore | 4 + vendor/github.com/go-git/go-billy/v5/LICENSE | 201 ++ vendor/github.com/go-git/go-billy/v5/Makefile | 11 + .../github.com/go-git/go-billy/v5/README.md | 73 + vendor/github.com/go-git/go-billy/v5/fs.go | 202 ++ vendor/github.com/go-git/go-git/v5/LICENSE | 201 ++ .../go-git/v5/internal/path_util/path_util.go | 29 + .../v5/plumbing/format/config/common.go | 109 + .../v5/plumbing/format/config/decoder.go | 37 + .../go-git/v5/plumbing/format/config/doc.go | 122 + .../v5/plumbing/format/config/encoder.go | 82 + .../v5/plumbing/format/config/format.go | 53 + .../v5/plumbing/format/config/option.go | 127 + .../v5/plumbing/format/config/section.go | 181 ++ .../v5/plumbing/format/gitignore/dir.go | 144 ++ .../v5/plumbing/format/gitignore/doc.go | 70 + .../v5/plumbing/format/gitignore/matcher.go | 30 + .../v5/plumbing/format/gitignore/pattern.go | 155 ++ .../go-git/go-git/v5/utils/ioutil/common.go | 210 ++ .../github.com/gorilla/websocket/.gitignore | 25 + vendor/github.com/gorilla/websocket/AUTHORS | 9 + vendor/github.com/gorilla/websocket/LICENSE | 22 + vendor/github.com/gorilla/websocket/README.md | 39 + vendor/github.com/gorilla/websocket/client.go | 422 ++++ .../gorilla/websocket/compression.go | 148 ++ vendor/github.com/gorilla/websocket/conn.go | 1230 +++++++++ vendor/github.com/gorilla/websocket/doc.go | 227 ++ vendor/github.com/gorilla/websocket/join.go | 42 + vendor/github.com/gorilla/websocket/json.go | 60 + vendor/github.com/gorilla/websocket/mask.go | 55 + .../github.com/gorilla/websocket/mask_safe.go | 16 + .../github.com/gorilla/websocket/prepared.go | 102 + vendor/github.com/gorilla/websocket/proxy.go | 77 + vendor/github.com/gorilla/websocket/server.go | 365 +++ .../gorilla/websocket/tls_handshake.go | 21 + .../gorilla/websocket/tls_handshake_116.go | 21 + vendor/github.com/gorilla/websocket/util.go | 283 +++ .../gorilla/websocket/x_net_proxy.go | 473 ++++ vendor/github.com/jbenet/go-context/LICENSE | 21 + .../github.com/jbenet/go-context/io/ctxio.go | 120 + .../github.com/joelanford/ignore/.gitignore | 1 + .../joelanford/ignore/.golangci.yml | 17 + vendor/github.com/joelanford/ignore/LICENSE | 201 ++ vendor/github.com/joelanford/ignore/ignore.go | 70 + .../github.com/liggitt/tabwriter/.travis.yml | 11 + vendor/github.com/liggitt/tabwriter/LICENSE | 27 + vendor/github.com/liggitt/tabwriter/README.md | 7 + .../github.com/liggitt/tabwriter/tabwriter.go | 637 +++++ .../mitchellh/go-wordwrap/LICENSE.md | 21 + .../mitchellh/go-wordwrap/README.md | 39 + .../mitchellh/go-wordwrap/wordwrap.go | 83 + .../moby/spdystream/CONTRIBUTING.md | 13 + vendor/github.com/moby/spdystream/LICENSE | 202 ++ vendor/github.com/moby/spdystream/MAINTAINERS | 40 + vendor/github.com/moby/spdystream/NOTICE | 5 + vendor/github.com/moby/spdystream/README.md | 77 + .../github.com/moby/spdystream/connection.go | 972 +++++++ vendor/github.com/moby/spdystream/handlers.go | 52 + vendor/github.com/moby/spdystream/priority.go | 114 + .../moby/spdystream/spdy/dictionary.go | 203 ++ .../github.com/moby/spdystream/spdy/read.go | 364 +++ .../github.com/moby/spdystream/spdy/types.go | 291 +++ .../github.com/moby/spdystream/spdy/write.go | 334 +++ vendor/github.com/moby/spdystream/stream.go | 343 +++ vendor/github.com/moby/spdystream/utils.go | 32 + vendor/github.com/moby/term/.gitignore | 8 + vendor/github.com/moby/term/LICENSE | 191 ++ vendor/github.com/moby/term/README.md | 36 + vendor/github.com/moby/term/ascii.go | 66 + vendor/github.com/moby/term/doc.go | 3 + vendor/github.com/moby/term/proxy.go | 88 + vendor/github.com/moby/term/term.go | 85 + vendor/github.com/moby/term/term_unix.go | 98 + vendor/github.com/moby/term/term_windows.go | 176 ++ vendor/github.com/moby/term/termios_bsd.go | 13 + vendor/github.com/moby/term/termios_nonbsd.go | 13 + vendor/github.com/moby/term/termios_unix.go | 35 + .../github.com/moby/term/termios_windows.go | 37 + .../moby/term/windows/ansi_reader.go | 252 ++ .../moby/term/windows/ansi_writer.go | 57 + .../github.com/moby/term/windows/console.go | 43 + vendor/github.com/moby/term/windows/doc.go | 5 + vendor/github.com/mxk/go-flowrate/LICENSE | 29 + .../mxk/go-flowrate/flowrate/flowrate.go | 267 ++ .../github.com/mxk/go-flowrate/flowrate/io.go | 133 + .../mxk/go-flowrate/flowrate/util.go | 67 + .../alpha/action/generate_dockerfile.go | 64 + .../operator-registry/alpha/action/init.go | 52 + .../operator-registry/alpha/action/list.go | 212 ++ .../operator-registry/alpha/action/migrate.go | 47 + .../operator-registry/alpha/action/render.go | 538 ++++ .../alpha/declcfg/declcfg.go | 209 ++ .../alpha/declcfg/declcfg_to_model.go | 257 ++ .../operator-registry/alpha/declcfg/load.go | 317 +++ .../alpha/declcfg/model_to_declcfg.go | 131 + .../operator-registry/alpha/declcfg/write.go | 542 ++++ .../alpha/template/basic/basic.go | 50 + .../alpha/template/composite/builder.go | 363 +++ .../alpha/template/composite/composite.go | 261 ++ .../alpha/template/composite/config.go | 42 + .../alpha/template/composite/types.go | 62 + .../alpha/template/semver/README.md | 286 +++ .../template/semver/major-version-demo.gif | Bin 0 -> 1041736 bytes .../template/semver/minor-version-demo.gif | Bin 0 -> 1003102 bytes .../alpha/template/semver/semver.go | 466 ++++ .../alpha/template/semver/types.go | 82 + .../cmd/opm/alpha/bundle/build.go | 93 + .../cmd/opm/alpha/bundle/cmd.go | 22 + .../cmd/opm/alpha/bundle/extract.go | 71 + .../cmd/opm/alpha/bundle/generate.go | 60 + .../cmd/opm/alpha/bundle/unpack.go | 167 ++ .../cmd/opm/alpha/bundle/validate.go | 114 + .../operator-registry/cmd/opm/alpha/cmd.go | 31 + .../cmd/opm/alpha/list/cmd.go | 124 + .../cmd/opm/alpha/render-graph/cmd.go | 78 + .../cmd/opm/alpha/template/basic.go | 75 + .../cmd/opm/alpha/template/cmd.go | 30 + .../cmd/opm/alpha/template/composite.go | 83 + .../cmd/opm/alpha/template/semver.go | 84 + .../operator-registry/cmd/opm/generate/cmd.go | 111 + .../operator-registry/cmd/opm/index/add.go | 234 ++ .../operator-registry/cmd/opm/index/cmd.go | 42 + .../operator-registry/cmd/opm/index/delete.go | 131 + .../cmd/opm/index/deprecatetruncate.go | 152 ++ .../operator-registry/cmd/opm/index/export.go | 130 + .../operator-registry/cmd/opm/index/prune.go | 132 + .../cmd/opm/index/prunestranded.go | 115 + .../operator-registry/cmd/opm/init/cmd.go | 77 + .../cmd/opm/internal/util/util.go | 68 + .../operator-registry/cmd/opm/main.go | 30 + .../operator-registry/cmd/opm/migrate/cmd.go | 55 + .../operator-registry/cmd/opm/registry/add.go | 149 ++ .../operator-registry/cmd/opm/registry/cmd.go | 38 + .../cmd/opm/registry/deprecatetruncate.go | 76 + .../cmd/opm/registry/mirror.go | 51 + .../cmd/opm/registry/prune.go | 73 + .../cmd/opm/registry/prunestranded.go | 58 + .../operator-registry/cmd/opm/registry/rm.go | 73 + .../cmd/opm/registry/serve.go | 171 ++ .../operator-registry/cmd/opm/render/cmd.go | 96 + .../operator-registry/cmd/opm/root/cmd.go | 74 + .../operator-registry/cmd/opm/serve/serve.go | 295 +++ .../cmd/opm/validate/validate.go | 38 + .../cmd/opm/version/version.go | 56 + .../operator-registry/pkg/cache/bundle_key.go | 47 + .../operator-registry/pkg/cache/cache.go | 431 ++++ .../operator-registry/pkg/cache/json.go | 205 ++ .../operator-registry/pkg/cache/pkgs.go | 308 +++ .../operator-registry/pkg/cache/pogrebv1.go | 244 ++ .../pkg/cache/syscall_unix.go | 8 + .../pkg/cache/syscall_windows.go | 6 + .../operator-registry/pkg/cache/tar.go | 71 + .../operator-registry/pkg/lib/certs/certs.go | 25 + .../pkg/lib/config/validate.go | 32 + .../operator-registry/pkg/lib/dns/nsswitch.go | 27 + .../pkg/lib/graceful/shutdown.go | 33 + .../pkg/lib/indexer/indexer.go | 719 ++++++ .../pkg/lib/indexer/interfaces.go | 118 + .../operator-registry/pkg/lib/log/null.go | 13 + .../pkg/lib/log/writerhook.go | 76 + .../pkg/lib/registry/interfaces.go | 58 + .../pkg/lib/registry/registry.go | 459 ++++ .../operator-registry/pkg/lib/tmp/copy.go | 53 + .../operator-registry/pkg/mirror/mirror.go | 111 + .../operator-registry/pkg/mirror/options.go | 111 + .../russross/blackfriday/v2/.gitignore | 8 + .../russross/blackfriday/v2/.travis.yml | 17 + .../russross/blackfriday/v2/LICENSE.txt | 29 + .../russross/blackfriday/v2/README.md | 335 +++ .../russross/blackfriday/v2/block.go | 1612 ++++++++++++ .../github.com/russross/blackfriday/v2/doc.go | 46 + .../russross/blackfriday/v2/entities.go | 2236 +++++++++++++++++ .../github.com/russross/blackfriday/v2/esc.go | 70 + .../russross/blackfriday/v2/html.go | 952 +++++++ .../russross/blackfriday/v2/inline.go | 1228 +++++++++ .../russross/blackfriday/v2/markdown.go | 950 +++++++ .../russross/blackfriday/v2/node.go | 360 +++ .../russross/blackfriday/v2/smartypants.go | 457 ++++ vendor/github.com/tidwall/btree/LICENSE | 18 + vendor/github.com/tidwall/btree/PATH_HINT.md | 45 + vendor/github.com/tidwall/btree/README.md | 455 ++++ vendor/github.com/tidwall/btree/btree.go | 399 +++ vendor/github.com/tidwall/btree/btreeg.go | 1427 +++++++++++ vendor/github.com/tidwall/btree/map.go | 1212 +++++++++ vendor/github.com/tidwall/btree/set.go | 179 ++ .../grpc/reflection/README.md | 18 + .../grpc/reflection/adapt.go | 187 ++ .../grpc_reflection_v1/reflection.pb.go | 953 +++++++ .../grpc_reflection_v1/reflection_grpc.pb.go | 164 ++ .../grpc_reflection_v1alpha/reflection.pb.go | 1028 ++++++++ .../reflection_grpc.pb.go | 161 ++ .../grpc/reflection/serverreflection.go | 360 +++ vendor/gopkg.in/warnings.v0/LICENSE | 24 + vendor/gopkg.in/warnings.v0/README | 77 + vendor/gopkg.in/warnings.v0/warnings.go | 194 ++ .../pkg/util/httpstream/spdy/connection.go | 204 ++ .../pkg/util/httpstream/spdy/roundtripper.go | 399 +++ .../pkg/util/httpstream/spdy/upgrade.go | 120 + .../apimachinery/pkg/util/proxy/dial.go | 122 + .../k8s.io/apimachinery/pkg/util/proxy/doc.go | 18 + .../apimachinery/pkg/util/proxy/transport.go | 272 ++ .../pkg/util/proxy/upgradeaware.go | 558 ++++ .../third_party/forked/golang/netutil/addr.go | 28 + vendor/k8s.io/cli-runtime/LICENSE | 202 ++ .../cli-runtime/pkg/printers/discard.go | 30 + vendor/k8s.io/cli-runtime/pkg/printers/doc.go | 19 + .../cli-runtime/pkg/printers/interface.go | 54 + .../k8s.io/cli-runtime/pkg/printers/json.go | 79 + .../cli-runtime/pkg/printers/jsonpath.go | 147 ++ .../cli-runtime/pkg/printers/managedfields.go | 59 + .../k8s.io/cli-runtime/pkg/printers/name.go | 130 + .../cli-runtime/pkg/printers/sourcechecker.go | 60 + .../cli-runtime/pkg/printers/tableprinter.go | 589 +++++ .../cli-runtime/pkg/printers/tabwriter.go | 36 + .../cli-runtime/pkg/printers/template.go | 118 + .../cli-runtime/pkg/printers/terminal.go | 75 + .../cli-runtime/pkg/printers/typesetter.go | 95 + .../pkg/printers/warningprinter.go | 55 + .../k8s.io/cli-runtime/pkg/printers/yaml.go | 85 + .../third_party/forked/golang/LICENSE | 27 + .../third_party/forked/golang/PATENTS | 22 + .../forked/golang/template/exec.go | 52 + .../forked/golang/template/funcs.go | 177 ++ .../client-go/tools/remotecommand/OWNERS | 10 + .../client-go/tools/remotecommand/doc.go | 20 + .../tools/remotecommand/errorstream.go | 54 + .../client-go/tools/remotecommand/fallback.go | 57 + .../client-go/tools/remotecommand/reader.go | 41 + .../tools/remotecommand/remotecommand.go | 58 + .../client-go/tools/remotecommand/resize.go | 33 + .../client-go/tools/remotecommand/spdy.go | 171 ++ .../client-go/tools/remotecommand/v1.go | 159 ++ .../client-go/tools/remotecommand/v2.go | 199 ++ .../client-go/tools/remotecommand/v3.go | 111 + .../client-go/tools/remotecommand/v4.go | 119 + .../client-go/tools/remotecommand/v5.go | 35 + .../tools/remotecommand/websocket.go | 515 ++++ .../k8s.io/client-go/transport/spdy/spdy.go | 107 + .../transport/websocket/roundtripper.go | 182 ++ vendor/k8s.io/client-go/util/exec/exec.go | 52 + vendor/k8s.io/client-go/util/jsonpath/doc.go | 20 + .../client-go/util/jsonpath/jsonpath.go | 582 +++++ vendor/k8s.io/client-go/util/jsonpath/node.go | 256 ++ .../k8s.io/client-go/util/jsonpath/parser.go | 527 ++++ vendor/k8s.io/kubectl/LICENSE | 201 ++ .../kubectl/pkg/util/interrupt/interrupt.go | 104 + .../pkg/util/templates/command_groups.go | 59 + .../pkg/util/templates/help_flags_printer.go | 76 + .../kubectl/pkg/util/templates/markdown.go | 116 + .../kubectl/pkg/util/templates/normalizers.go | 97 + .../kubectl/pkg/util/templates/templater.go | 319 +++ .../kubectl/pkg/util/templates/templates.go | 104 + vendor/k8s.io/kubectl/pkg/util/term/resize.go | 132 + .../kubectl/pkg/util/term/resizeevents.go | 62 + .../pkg/util/term/resizeevents_windows.go | 62 + vendor/k8s.io/kubectl/pkg/util/term/term.go | 115 + .../kubectl/pkg/util/term/term_writer.go | 146 ++ vendor/modules.txt | 119 + 344 files changed, 54782 insertions(+) create mode 100755 scripts/e2e_test_fixtures.sh create mode 100644 vendor/github.com/Azure/go-ansiterm/LICENSE create mode 100644 vendor/github.com/Azure/go-ansiterm/README.md create mode 100644 vendor/github.com/Azure/go-ansiterm/SECURITY.md create mode 100644 vendor/github.com/Azure/go-ansiterm/constants.go create mode 100644 vendor/github.com/Azure/go-ansiterm/context.go create mode 100644 vendor/github.com/Azure/go-ansiterm/csi_entry_state.go create mode 100644 vendor/github.com/Azure/go-ansiterm/csi_param_state.go create mode 100644 vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go create mode 100644 vendor/github.com/Azure/go-ansiterm/escape_state.go create mode 100644 vendor/github.com/Azure/go-ansiterm/event_handler.go create mode 100644 vendor/github.com/Azure/go-ansiterm/ground_state.go create mode 100644 vendor/github.com/Azure/go-ansiterm/osc_string_state.go create mode 100644 vendor/github.com/Azure/go-ansiterm/parser.go create mode 100644 vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go create mode 100644 vendor/github.com/Azure/go-ansiterm/parser_actions.go create mode 100644 vendor/github.com/Azure/go-ansiterm/states.go create mode 100644 vendor/github.com/Azure/go-ansiterm/utilities.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/ansi.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/api.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/utilities.go create mode 100644 vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go create mode 100644 vendor/github.com/MakeNowJust/heredoc/LICENSE create mode 100644 vendor/github.com/MakeNowJust/heredoc/README.md create mode 100644 vendor/github.com/MakeNowJust/heredoc/heredoc.go create mode 100644 vendor/github.com/akrylysov/pogreb/.gitignore create mode 100644 vendor/github.com/akrylysov/pogreb/CHANGELOG.md create mode 100644 vendor/github.com/akrylysov/pogreb/LICENSE create mode 100644 vendor/github.com/akrylysov/pogreb/README.md create mode 100644 vendor/github.com/akrylysov/pogreb/appveyor.yml create mode 100644 vendor/github.com/akrylysov/pogreb/bucket.go create mode 100644 vendor/github.com/akrylysov/pogreb/compaction.go create mode 100644 vendor/github.com/akrylysov/pogreb/datalog.go create mode 100644 vendor/github.com/akrylysov/pogreb/db.go create mode 100644 vendor/github.com/akrylysov/pogreb/doc.go create mode 100644 vendor/github.com/akrylysov/pogreb/errors.go create mode 100644 vendor/github.com/akrylysov/pogreb/file.go create mode 100644 vendor/github.com/akrylysov/pogreb/fs/fs.go create mode 100644 vendor/github.com/akrylysov/pogreb/fs/mem.go create mode 100644 vendor/github.com/akrylysov/pogreb/fs/os.go create mode 100644 vendor/github.com/akrylysov/pogreb/fs/os_mmap.go create mode 100644 vendor/github.com/akrylysov/pogreb/fs/os_mmap_unix.go create mode 100644 vendor/github.com/akrylysov/pogreb/fs/os_mmap_windows.go create mode 100644 vendor/github.com/akrylysov/pogreb/fs/os_mmap_windows_386.go create mode 100644 vendor/github.com/akrylysov/pogreb/fs/os_mmap_windows_amd64.go create mode 100644 vendor/github.com/akrylysov/pogreb/fs/os_unix.go create mode 100644 vendor/github.com/akrylysov/pogreb/fs/os_windows.go create mode 100644 vendor/github.com/akrylysov/pogreb/fs/sub.go create mode 100644 vendor/github.com/akrylysov/pogreb/gobfile.go create mode 100644 vendor/github.com/akrylysov/pogreb/header.go create mode 100644 vendor/github.com/akrylysov/pogreb/index.go create mode 100644 vendor/github.com/akrylysov/pogreb/internal/errors/errors.go create mode 100644 vendor/github.com/akrylysov/pogreb/internal/hash/murmurhash32.go create mode 100644 vendor/github.com/akrylysov/pogreb/internal/hash/seed.go create mode 100644 vendor/github.com/akrylysov/pogreb/iterator.go create mode 100644 vendor/github.com/akrylysov/pogreb/lock.go create mode 100644 vendor/github.com/akrylysov/pogreb/logger.go create mode 100644 vendor/github.com/akrylysov/pogreb/metrics.go create mode 100644 vendor/github.com/akrylysov/pogreb/options.go create mode 100644 vendor/github.com/akrylysov/pogreb/recovery.go create mode 100644 vendor/github.com/akrylysov/pogreb/segment.go create mode 100644 vendor/github.com/go-git/gcfg/.gitignore create mode 100644 vendor/github.com/go-git/gcfg/LICENSE create mode 100644 vendor/github.com/go-git/gcfg/Makefile create mode 100644 vendor/github.com/go-git/gcfg/README create mode 100644 vendor/github.com/go-git/gcfg/doc.go create mode 100644 vendor/github.com/go-git/gcfg/errors.go create mode 100644 vendor/github.com/go-git/gcfg/read.go create mode 100644 vendor/github.com/go-git/gcfg/scanner/errors.go create mode 100644 vendor/github.com/go-git/gcfg/scanner/scanner.go create mode 100644 vendor/github.com/go-git/gcfg/set.go create mode 100644 vendor/github.com/go-git/gcfg/token/position.go create mode 100644 vendor/github.com/go-git/gcfg/token/serialize.go create mode 100644 vendor/github.com/go-git/gcfg/token/token.go create mode 100644 vendor/github.com/go-git/gcfg/types/bool.go create mode 100644 vendor/github.com/go-git/gcfg/types/doc.go create mode 100644 vendor/github.com/go-git/gcfg/types/enum.go create mode 100644 vendor/github.com/go-git/gcfg/types/int.go create mode 100644 vendor/github.com/go-git/gcfg/types/scan.go create mode 100644 vendor/github.com/go-git/go-billy/v5/.gitignore create mode 100644 vendor/github.com/go-git/go-billy/v5/LICENSE create mode 100644 vendor/github.com/go-git/go-billy/v5/Makefile create mode 100644 vendor/github.com/go-git/go-billy/v5/README.md create mode 100644 vendor/github.com/go-git/go-billy/v5/fs.go create mode 100644 vendor/github.com/go-git/go-git/v5/LICENSE create mode 100644 vendor/github.com/go-git/go-git/v5/internal/path_util/path_util.go create mode 100644 vendor/github.com/go-git/go-git/v5/plumbing/format/config/common.go create mode 100644 vendor/github.com/go-git/go-git/v5/plumbing/format/config/decoder.go create mode 100644 vendor/github.com/go-git/go-git/v5/plumbing/format/config/doc.go create mode 100644 vendor/github.com/go-git/go-git/v5/plumbing/format/config/encoder.go create mode 100644 vendor/github.com/go-git/go-git/v5/plumbing/format/config/format.go create mode 100644 vendor/github.com/go-git/go-git/v5/plumbing/format/config/option.go create mode 100644 vendor/github.com/go-git/go-git/v5/plumbing/format/config/section.go create mode 100644 vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/dir.go create mode 100644 vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/doc.go create mode 100644 vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/matcher.go create mode 100644 vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/pattern.go create mode 100644 vendor/github.com/go-git/go-git/v5/utils/ioutil/common.go create mode 100644 vendor/github.com/gorilla/websocket/.gitignore create mode 100644 vendor/github.com/gorilla/websocket/AUTHORS create mode 100644 vendor/github.com/gorilla/websocket/LICENSE create mode 100644 vendor/github.com/gorilla/websocket/README.md create mode 100644 vendor/github.com/gorilla/websocket/client.go create mode 100644 vendor/github.com/gorilla/websocket/compression.go create mode 100644 vendor/github.com/gorilla/websocket/conn.go create mode 100644 vendor/github.com/gorilla/websocket/doc.go create mode 100644 vendor/github.com/gorilla/websocket/join.go create mode 100644 vendor/github.com/gorilla/websocket/json.go create mode 100644 vendor/github.com/gorilla/websocket/mask.go create mode 100644 vendor/github.com/gorilla/websocket/mask_safe.go create mode 100644 vendor/github.com/gorilla/websocket/prepared.go create mode 100644 vendor/github.com/gorilla/websocket/proxy.go create mode 100644 vendor/github.com/gorilla/websocket/server.go create mode 100644 vendor/github.com/gorilla/websocket/tls_handshake.go create mode 100644 vendor/github.com/gorilla/websocket/tls_handshake_116.go create mode 100644 vendor/github.com/gorilla/websocket/util.go create mode 100644 vendor/github.com/gorilla/websocket/x_net_proxy.go create mode 100644 vendor/github.com/jbenet/go-context/LICENSE create mode 100644 vendor/github.com/jbenet/go-context/io/ctxio.go create mode 100644 vendor/github.com/joelanford/ignore/.gitignore create mode 100644 vendor/github.com/joelanford/ignore/.golangci.yml create mode 100644 vendor/github.com/joelanford/ignore/LICENSE create mode 100644 vendor/github.com/joelanford/ignore/ignore.go create mode 100644 vendor/github.com/liggitt/tabwriter/.travis.yml create mode 100644 vendor/github.com/liggitt/tabwriter/LICENSE create mode 100644 vendor/github.com/liggitt/tabwriter/README.md create mode 100644 vendor/github.com/liggitt/tabwriter/tabwriter.go create mode 100644 vendor/github.com/mitchellh/go-wordwrap/LICENSE.md create mode 100644 vendor/github.com/mitchellh/go-wordwrap/README.md create mode 100644 vendor/github.com/mitchellh/go-wordwrap/wordwrap.go create mode 100644 vendor/github.com/moby/spdystream/CONTRIBUTING.md create mode 100644 vendor/github.com/moby/spdystream/LICENSE create mode 100644 vendor/github.com/moby/spdystream/MAINTAINERS create mode 100644 vendor/github.com/moby/spdystream/NOTICE create mode 100644 vendor/github.com/moby/spdystream/README.md create mode 100644 vendor/github.com/moby/spdystream/connection.go create mode 100644 vendor/github.com/moby/spdystream/handlers.go create mode 100644 vendor/github.com/moby/spdystream/priority.go create mode 100644 vendor/github.com/moby/spdystream/spdy/dictionary.go create mode 100644 vendor/github.com/moby/spdystream/spdy/read.go create mode 100644 vendor/github.com/moby/spdystream/spdy/types.go create mode 100644 vendor/github.com/moby/spdystream/spdy/write.go create mode 100644 vendor/github.com/moby/spdystream/stream.go create mode 100644 vendor/github.com/moby/spdystream/utils.go create mode 100644 vendor/github.com/moby/term/.gitignore create mode 100644 vendor/github.com/moby/term/LICENSE create mode 100644 vendor/github.com/moby/term/README.md create mode 100644 vendor/github.com/moby/term/ascii.go create mode 100644 vendor/github.com/moby/term/doc.go create mode 100644 vendor/github.com/moby/term/proxy.go create mode 100644 vendor/github.com/moby/term/term.go create mode 100644 vendor/github.com/moby/term/term_unix.go create mode 100644 vendor/github.com/moby/term/term_windows.go create mode 100644 vendor/github.com/moby/term/termios_bsd.go create mode 100644 vendor/github.com/moby/term/termios_nonbsd.go create mode 100644 vendor/github.com/moby/term/termios_unix.go create mode 100644 vendor/github.com/moby/term/termios_windows.go create mode 100644 vendor/github.com/moby/term/windows/ansi_reader.go create mode 100644 vendor/github.com/moby/term/windows/ansi_writer.go create mode 100644 vendor/github.com/moby/term/windows/console.go create mode 100644 vendor/github.com/moby/term/windows/doc.go create mode 100644 vendor/github.com/mxk/go-flowrate/LICENSE create mode 100644 vendor/github.com/mxk/go-flowrate/flowrate/flowrate.go create mode 100644 vendor/github.com/mxk/go-flowrate/flowrate/io.go create mode 100644 vendor/github.com/mxk/go-flowrate/flowrate/util.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/action/generate_dockerfile.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/action/init.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/action/list.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/action/migrate.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/action/render.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/declcfg/declcfg.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/declcfg/declcfg_to_model.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/declcfg/load.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/declcfg/model_to_declcfg.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/declcfg/write.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/template/basic/basic.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/template/composite/builder.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/template/composite/composite.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/template/composite/config.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/template/composite/types.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/template/semver/README.md create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/template/semver/major-version-demo.gif create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/template/semver/minor-version-demo.gif create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/template/semver/semver.go create mode 100644 vendor/github.com/operator-framework/operator-registry/alpha/template/semver/types.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/build.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/cmd.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/extract.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/generate.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/unpack.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/validate.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/cmd.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/list/cmd.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/render-graph/cmd.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/basic.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/cmd.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/composite.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/semver.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/generate/cmd.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/index/add.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/index/cmd.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/index/delete.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/index/deprecatetruncate.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/index/export.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/index/prune.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/index/prunestranded.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/init/cmd.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/internal/util/util.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/main.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/migrate/cmd.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/add.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/cmd.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/deprecatetruncate.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/mirror.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/prune.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/prunestranded.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/rm.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/serve.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/render/cmd.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/root/cmd.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/serve/serve.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/validate/validate.go create mode 100644 vendor/github.com/operator-framework/operator-registry/cmd/opm/version/version.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/cache/bundle_key.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/cache/cache.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/cache/json.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/cache/pkgs.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/cache/pogrebv1.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/cache/syscall_unix.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/cache/syscall_windows.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/cache/tar.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/lib/certs/certs.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/lib/config/validate.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/lib/dns/nsswitch.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/lib/graceful/shutdown.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/lib/indexer/indexer.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/lib/indexer/interfaces.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/lib/log/null.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/lib/log/writerhook.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/lib/registry/interfaces.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/lib/registry/registry.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/lib/tmp/copy.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/mirror/mirror.go create mode 100644 vendor/github.com/operator-framework/operator-registry/pkg/mirror/options.go create mode 100644 vendor/github.com/russross/blackfriday/v2/.gitignore create mode 100644 vendor/github.com/russross/blackfriday/v2/.travis.yml create mode 100644 vendor/github.com/russross/blackfriday/v2/LICENSE.txt create mode 100644 vendor/github.com/russross/blackfriday/v2/README.md create mode 100644 vendor/github.com/russross/blackfriday/v2/block.go create mode 100644 vendor/github.com/russross/blackfriday/v2/doc.go create mode 100644 vendor/github.com/russross/blackfriday/v2/entities.go create mode 100644 vendor/github.com/russross/blackfriday/v2/esc.go create mode 100644 vendor/github.com/russross/blackfriday/v2/html.go create mode 100644 vendor/github.com/russross/blackfriday/v2/inline.go create mode 100644 vendor/github.com/russross/blackfriday/v2/markdown.go create mode 100644 vendor/github.com/russross/blackfriday/v2/node.go create mode 100644 vendor/github.com/russross/blackfriday/v2/smartypants.go create mode 100644 vendor/github.com/tidwall/btree/LICENSE create mode 100644 vendor/github.com/tidwall/btree/PATH_HINT.md create mode 100644 vendor/github.com/tidwall/btree/README.md create mode 100644 vendor/github.com/tidwall/btree/btree.go create mode 100644 vendor/github.com/tidwall/btree/btreeg.go create mode 100644 vendor/github.com/tidwall/btree/map.go create mode 100644 vendor/github.com/tidwall/btree/set.go create mode 100644 vendor/google.golang.org/grpc/reflection/README.md create mode 100644 vendor/google.golang.org/grpc/reflection/adapt.go create mode 100644 vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go create mode 100644 vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go create mode 100644 vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go create mode 100644 vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go create mode 100644 vendor/google.golang.org/grpc/reflection/serverreflection.go create mode 100644 vendor/gopkg.in/warnings.v0/LICENSE create mode 100644 vendor/gopkg.in/warnings.v0/README create mode 100644 vendor/gopkg.in/warnings.v0/warnings.go create mode 100644 vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/connection.go create mode 100644 vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go create mode 100644 vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/upgrade.go create mode 100644 vendor/k8s.io/apimachinery/pkg/util/proxy/dial.go create mode 100644 vendor/k8s.io/apimachinery/pkg/util/proxy/doc.go create mode 100644 vendor/k8s.io/apimachinery/pkg/util/proxy/transport.go create mode 100644 vendor/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go create mode 100644 vendor/k8s.io/apimachinery/third_party/forked/golang/netutil/addr.go create mode 100644 vendor/k8s.io/cli-runtime/LICENSE create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/discard.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/doc.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/interface.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/json.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/jsonpath.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/managedfields.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/name.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/sourcechecker.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/tableprinter.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/tabwriter.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/template.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/terminal.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/typesetter.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/warningprinter.go create mode 100644 vendor/k8s.io/cli-runtime/pkg/printers/yaml.go create mode 100644 vendor/k8s.io/client-go/third_party/forked/golang/LICENSE create mode 100644 vendor/k8s.io/client-go/third_party/forked/golang/PATENTS create mode 100644 vendor/k8s.io/client-go/third_party/forked/golang/template/exec.go create mode 100644 vendor/k8s.io/client-go/third_party/forked/golang/template/funcs.go create mode 100644 vendor/k8s.io/client-go/tools/remotecommand/OWNERS create mode 100644 vendor/k8s.io/client-go/tools/remotecommand/doc.go create mode 100644 vendor/k8s.io/client-go/tools/remotecommand/errorstream.go create mode 100644 vendor/k8s.io/client-go/tools/remotecommand/fallback.go create mode 100644 vendor/k8s.io/client-go/tools/remotecommand/reader.go create mode 100644 vendor/k8s.io/client-go/tools/remotecommand/remotecommand.go create mode 100644 vendor/k8s.io/client-go/tools/remotecommand/resize.go create mode 100644 vendor/k8s.io/client-go/tools/remotecommand/spdy.go create mode 100644 vendor/k8s.io/client-go/tools/remotecommand/v1.go create mode 100644 vendor/k8s.io/client-go/tools/remotecommand/v2.go create mode 100644 vendor/k8s.io/client-go/tools/remotecommand/v3.go create mode 100644 vendor/k8s.io/client-go/tools/remotecommand/v4.go create mode 100644 vendor/k8s.io/client-go/tools/remotecommand/v5.go create mode 100644 vendor/k8s.io/client-go/tools/remotecommand/websocket.go create mode 100644 vendor/k8s.io/client-go/transport/spdy/spdy.go create mode 100644 vendor/k8s.io/client-go/transport/websocket/roundtripper.go create mode 100644 vendor/k8s.io/client-go/util/exec/exec.go create mode 100644 vendor/k8s.io/client-go/util/jsonpath/doc.go create mode 100644 vendor/k8s.io/client-go/util/jsonpath/jsonpath.go create mode 100644 vendor/k8s.io/client-go/util/jsonpath/node.go create mode 100644 vendor/k8s.io/client-go/util/jsonpath/parser.go create mode 100644 vendor/k8s.io/kubectl/LICENSE create mode 100644 vendor/k8s.io/kubectl/pkg/util/interrupt/interrupt.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/templates/command_groups.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/templates/help_flags_printer.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/templates/markdown.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/templates/normalizers.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/templates/templater.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/templates/templates.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/term/resize.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/term/resizeevents.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/term/resizeevents_windows.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/term/term.go create mode 100644 vendor/k8s.io/kubectl/pkg/util/term/term_writer.go diff --git a/go.mod b/go.mod index 6eda23d033..3c6d916ae5 100644 --- a/go.mod +++ b/go.mod @@ -56,10 +56,13 @@ require ( require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/BurntSushi/toml v1.3.2 // indirect + github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/hcsshim v0.12.3 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect + github.com/akrylysov/pogreb v0.10.2 // indirect github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -89,6 +92,9 @@ require ( github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/fatih/color v1.16.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.5.0 // indirect + github.com/go-git/go-git/v5 v5.11.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect @@ -106,6 +112,7 @@ require ( github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.1 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect github.com/h2non/filetype v1.1.3 // indirect @@ -113,27 +120,36 @@ require ( github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/itchyny/timefmt-go v0.1.6 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect + github.com/joelanford/ignore v0.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.17.8 // indirect + github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-sqlite3 v1.14.22 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/moby/locker v1.0.1 // indirect + github.com/moby/spdystream v0.2.0 // indirect github.com/moby/sys/mountinfo v0.7.1 // indirect github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/sys/user v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opencontainers/runtime-spec v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/procfs v0.12.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect + github.com/tidwall/btree v1.7.0 // indirect go.etcd.io/bbolt v1.3.10 // indirect go.etcd.io/etcd/api/v3 v3.5.12 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.12 // indirect @@ -165,10 +181,13 @@ require ( google.golang.org/protobuf v1.34.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/cli-runtime v0.30.0 // indirect k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 // indirect k8s.io/klog/v2 v2.120.1 // indirect k8s.io/kms v0.30.1 // indirect + k8s.io/kubectl v0.30.0 // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect diff --git a/go.sum b/go.sum index 45bf3a6bb0..1cd82ef2ef 100644 --- a/go.sum +++ b/go.sum @@ -1314,11 +1314,15 @@ gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zum git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/hcsshim v0.12.3 h1:LS9NXqXhMoqNCplK1ApmVSfB4UnVLRDWRapB6EIlxE0= @@ -1348,6 +1352,8 @@ github.com/apache/arrow/go/v12 v12.0.1/go.mod h1:weuTY7JvTG/HDPtMQxEUp7pU73vkLWM github.com/apache/arrow/go/v14 v14.0.2/go.mod h1:u3fgh3EdgN/YQ8cVQRguVW3R+seMybFg8QBQ5LU+eBY= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/apache/thrift v0.17.0/go.mod h1:OLxhMRJxomX+1I/KUw03qoV3mMz16BwaKI+d4fPBx7Q= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -1415,6 +1421,8 @@ github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8 github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -1672,6 +1680,7 @@ github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyE github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= @@ -1754,6 +1763,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= @@ -1780,18 +1791,24 @@ github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1 h1:NicmruxkeqHjDv03SfSxqmaLuisdd github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1/go.mod h1:eyp4DdUJAKkr9tvxR3jWhw2mDK7CWABMG5r9uyaKC7I= github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9kmUZPXP+H0= github.com/mitchellh/hashstructure v1.1.0/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -1799,6 +1816,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= @@ -1868,6 +1887,7 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= @@ -2824,6 +2844,8 @@ k8s.io/apimachinery v0.30.1 h1:ZQStsEfo4n65yAdlGTfP/uSHMQSoYzU/oeEbkmF7P2U= k8s.io/apimachinery v0.30.1/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= k8s.io/apiserver v0.30.1 h1:BEWEe8bzS12nMtDKXzCF5Q5ovp6LjjYkSp8qOPk8LZ8= k8s.io/apiserver v0.30.1/go.mod h1:i87ZnQ+/PGAmSbD/iEKM68bm1D5reX8fO4Ito4B01mo= +k8s.io/cli-runtime v0.30.0 h1:0vn6/XhOvn1RJ2KJOC6IRR2CGqrpT6QQF4+8pYpWQ48= +k8s.io/cli-runtime v0.30.0/go.mod h1:vATpDMATVTMA79sZ0YUCzlMelf6rUjoBzlp+RnoM+cg= k8s.io/client-go v0.30.1 h1:uC/Ir6A3R46wdkgCV3vbLyNOYyCJ8oZnjtJGKfytl/Q= k8s.io/client-go v0.30.1/go.mod h1:wrAqLNs2trwiCH/wxxmT/x3hKVH9PuV0GGW0oDoHVqc= k8s.io/code-generator v0.30.1 h1:ZsG++q5Vt0ScmKCeLhynUuWgcwFGg1Hl1AGfatqPJBI= @@ -2842,6 +2864,8 @@ k8s.io/kube-aggregator v0.30.1 h1:ymR2BsxDacTKwzKTuNhGZttuk009c+oZbSeD+IPX5q4= k8s.io/kube-aggregator v0.30.1/go.mod h1:SFbqWsM6ea8dHd3mPLsZFzJHbjBOS5ykIgJh4znZ5iQ= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/kubectl v0.30.0 h1:xbPvzagbJ6RNYVMVuiHArC1grrV5vSmmIcSZuCdzRyk= +k8s.io/kubectl v0.30.0/go.mod h1:zgolRw2MQXLPwmic2l/+iHs239L49fhSeICuMhQQXTI= k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ= k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= diff --git a/scripts/e2e_test_fixtures.sh b/scripts/e2e_test_fixtures.sh new file mode 100755 index 0000000000..911c775cd6 --- /dev/null +++ b/scripts/e2e_test_fixtures.sh @@ -0,0 +1,120 @@ +#!/usr/bin/env bash + +# Default values +OPM_VERSION=$(go list -m github.com/operator-framework/operator-registry | cut -d" " -f2 | sed 's/^v//') +PUSH=false +CONTAINER_RUNTIME=docker +REGISTRY=quay.io/olmtest +TARGET_BRANCH=master +JUST_CHECK=false + +while [ $# -gt 0 ]; do + case "$1" in + # opm version to build the fixtures against, e.g. 1.39.0 + --opm-version=*) + OPM_VERSION="${1#*=}" + ;; + # push images to registry after build + --push) + PUSH="true" + ;; + # check if images need to be updated - won't build or push images + --check) + JUST_CHECK="true" + ;; + # container runtime to use, e.g. podman (default docker) + --container-runtime=*) + CONTAINER_RUNTIME="${1#*=}" + ;; + # registry to push images to, e.g. quay.io/olmtest + --registry=*) + REGISTRY="${1#*=}" + ;; + # target branch to compare against when checking for changes, e.g. master + --target-branch=*) + TARGET_BRANCH="${1#*=}" + ;; + + *) + printf "*************************\n" + printf "* Error: Invalid argument.\n" + # shellcheck disable=SC2059 + printf "* Usage: %s [--opm-version=version] [--push=true|false] [--container-runtime=runtime] [--registry=registry] [--target-branch=branch]\n" "$0" + printf "*************************\n" + exit 1 + esac + shift +done + +function check_changes() { + OPM_CHANGED=false + FIXTURES_CHANGED=false + + if git diff "origin/${TARGET_BRANCH}" -- go.mod | grep -E '^\+[[:space:]]+github.com/operator-framework/operator-registry' > /dev/null; then + OPM_CHANGED=true + fi + + if git diff "origin/${TARGET_BRANCH}" -- test/images scripts/build_test_images.sh > /dev/null; then + FIXTURES_CHANGED=true + fi + + if [ "$OPM_CHANGED" = true ] || [ "$FIXTURES_CHANGED" = true ]; then + echo "true" + else + echo "false" + fi +} + +function push_fixtures() { + ${CONTAINER_RUNTIME} push "${TEST_CATALOG_IMAGE}" +} + +if [ "$JUST_CHECK" = true ]; then + check_changes + exit 0 +fi + +# Fixtures +BUNDLE_V1_IMAGE="${REGISTRY}/busybox-bundle:1.0.0-${OPM_VERSION}" +BUNDLE_V1_DEP_IMAGE="${REGISTRY}/busybox-dependency-bundle:1.0.0-${OPM_VERSION}" +BUNDLE_V2_IMAGE="${REGISTRY}/busybox-bundle:2.0.0-${OPM_VERSION}" +BUNDLE_V2_DEP_IMAGE="${REGISTRY}/busybox-dependency-bundle:2.0.0-${OPM_VERSION}" + +INDEX_V1="${REGISTRY}/busybox-dependencies-index:1.0.0-with-ListBundles-method-${OPM_VERSION}" +INDEX_V2="${REGISTRY}/busybox-dependencies-index:2.0.0-with-ListBundles-method-${OPM_VERSION}" + +TEST_CATALOG_IMAGE="${REGISTRY}/test-catalog:${OPM_VERSION}" + +# Busybox Operator Index Image +${CONTAINER_RUNTIME} build -t "${BUNDLE_V1_IMAGE}" ./test/images/busybox-index/busybox/1.0.0 +${CONTAINER_RUNTIME} build -t "${BUNDLE_V1_DEP_IMAGE}" ./test/images/busybox-index/busybox-dependency/1.0.0 +${CONTAINER_RUNTIME} build -t "${BUNDLE_V2_IMAGE}" ./test/images/busybox-index/busybox/2.0.0 +${CONTAINER_RUNTIME} build -t "${BUNDLE_V2_DEP_IMAGE}" ./test/images/busybox-index/busybox-dependency/2.0.0 + +# Build catalog from templates +mkdir -p ./test/images/busybox-index/indexv1 +mkdir -p ./test/images/busybox-index/indexv2 +sed -e "s|#BUNDLE_V1_IMAGE#|\"${BUNDLE_V1_IMAGE}\"|g" -e "s|#BUNDLE_V1_DEP_IMAGE#|\"${BUNDLE_V1_DEP_IMAGE}\"|g" ./test/images/busybox-index/busybox-index-v1.template.json > ./test/images/busybox-index/indexv1/catalog.json +sed -e "s|#BUNDLE_V1_IMAGE#|\"${BUNDLE_V1_IMAGE}\"|g" -e "s|#BUNDLE_V1_DEP_IMAGE#|\"${BUNDLE_V1_DEP_IMAGE}\"|g" -e "s|#BUNDLE_V2_IMAGE#|\"${BUNDLE_V2_IMAGE}\"|g" -e "s|#BUNDLE_V2_DEP_IMAGE#|\"${BUNDLE_V2_DEP_IMAGE}\"|g" ./test/images/busybox-index/busybox-index-v2.template.json > ./test/images/busybox-index/indexv2/catalog.json + +# Clean up +rm -rf ./test/images/busybox-index/indexv1 +rm -rf ./test/images/busybox-index/indexv2 + +# Test catalog used for e2e tests related to serving an extracted registry +# Let's reuse one of the other indices for this +${CONTAINER_RUNTIME} tag -t "${TEST_CATALOG_IMAGE}" "${INDEX_V2}" + +if [ "$PUSH" = true ]; then + # push bundles + ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" + ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" + ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" + ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" + + # push indexes + ${CONTAINER_RUNTIME} push "${INDEX_V1}" + ${CONTAINER_RUNTIME} push "${INDEX_V2}" + + # push test catalog +fi diff --git a/tools.go b/tools.go index 8d08220181..e188a797d5 100644 --- a/tools.go +++ b/tools.go @@ -7,6 +7,9 @@ // - They share dependencies (e.g. k8s libraries) with the main module and should be kept in sync package tools +// OPM +import _ "github.com/operator-framework/operator-registry/cmd/opm" + // The OLM API CRDs used as input to the code generators import _ "github.com/operator-framework/api/crds" // operators.coreos.com CRD manifests diff --git a/vendor/github.com/Azure/go-ansiterm/LICENSE b/vendor/github.com/Azure/go-ansiterm/LICENSE new file mode 100644 index 0000000000..e3d9a64d1d --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Microsoft Corporation + +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/Azure/go-ansiterm/README.md b/vendor/github.com/Azure/go-ansiterm/README.md new file mode 100644 index 0000000000..261c041e7a --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/README.md @@ -0,0 +1,12 @@ +# go-ansiterm + +This is a cross platform Ansi Terminal Emulation library. It reads a stream of Ansi characters and produces the appropriate function calls. The results of the function calls are platform dependent. + +For example the parser might receive "ESC, [, A" as a stream of three characters. This is the code for Cursor Up (http://www.vt100.net/docs/vt510-rm/CUU). The parser then calls the cursor up function (CUU()) on an event handler. The event handler determines what platform specific work must be done to cause the cursor to move up one position. + +The parser (parser.go) is a partial implementation of this state machine (http://vt100.net/emu/vt500_parser.png). There are also two event handler implementations, one for tests (test_event_handler.go) to validate that the expected events are being produced and called, the other is a Windows implementation (winterm/win_event_handler.go). + +See parser_test.go for examples exercising the state machine and generating appropriate function calls. + +----- +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/vendor/github.com/Azure/go-ansiterm/SECURITY.md b/vendor/github.com/Azure/go-ansiterm/SECURITY.md new file mode 100644 index 0000000000..e138ec5d6a --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + diff --git a/vendor/github.com/Azure/go-ansiterm/constants.go b/vendor/github.com/Azure/go-ansiterm/constants.go new file mode 100644 index 0000000000..96504a33bc --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/constants.go @@ -0,0 +1,188 @@ +package ansiterm + +const LogEnv = "DEBUG_TERMINAL" + +// ANSI constants +// References: +// -- http://www.ecma-international.org/publications/standards/Ecma-048.htm +// -- http://man7.org/linux/man-pages/man4/console_codes.4.html +// -- http://manpages.ubuntu.com/manpages/intrepid/man4/console_codes.4.html +// -- http://en.wikipedia.org/wiki/ANSI_escape_code +// -- http://vt100.net/emu/dec_ansi_parser +// -- http://vt100.net/emu/vt500_parser.svg +// -- http://invisible-island.net/xterm/ctlseqs/ctlseqs.html +// -- http://www.inwap.com/pdp10/ansicode.txt +const ( + // ECMA-48 Set Graphics Rendition + // Note: + // -- Constants leading with an underscore (e.g., _ANSI_xxx) are unsupported or reserved + // -- Fonts could possibly be supported via SetCurrentConsoleFontEx + // -- Windows does not expose the per-window cursor (i.e., caret) blink times + ANSI_SGR_RESET = 0 + ANSI_SGR_BOLD = 1 + ANSI_SGR_DIM = 2 + _ANSI_SGR_ITALIC = 3 + ANSI_SGR_UNDERLINE = 4 + _ANSI_SGR_BLINKSLOW = 5 + _ANSI_SGR_BLINKFAST = 6 + ANSI_SGR_REVERSE = 7 + _ANSI_SGR_INVISIBLE = 8 + _ANSI_SGR_LINETHROUGH = 9 + _ANSI_SGR_FONT_00 = 10 + _ANSI_SGR_FONT_01 = 11 + _ANSI_SGR_FONT_02 = 12 + _ANSI_SGR_FONT_03 = 13 + _ANSI_SGR_FONT_04 = 14 + _ANSI_SGR_FONT_05 = 15 + _ANSI_SGR_FONT_06 = 16 + _ANSI_SGR_FONT_07 = 17 + _ANSI_SGR_FONT_08 = 18 + _ANSI_SGR_FONT_09 = 19 + _ANSI_SGR_FONT_10 = 20 + _ANSI_SGR_DOUBLEUNDERLINE = 21 + ANSI_SGR_BOLD_DIM_OFF = 22 + _ANSI_SGR_ITALIC_OFF = 23 + ANSI_SGR_UNDERLINE_OFF = 24 + _ANSI_SGR_BLINK_OFF = 25 + _ANSI_SGR_RESERVED_00 = 26 + ANSI_SGR_REVERSE_OFF = 27 + _ANSI_SGR_INVISIBLE_OFF = 28 + _ANSI_SGR_LINETHROUGH_OFF = 29 + ANSI_SGR_FOREGROUND_BLACK = 30 + ANSI_SGR_FOREGROUND_RED = 31 + ANSI_SGR_FOREGROUND_GREEN = 32 + ANSI_SGR_FOREGROUND_YELLOW = 33 + ANSI_SGR_FOREGROUND_BLUE = 34 + ANSI_SGR_FOREGROUND_MAGENTA = 35 + ANSI_SGR_FOREGROUND_CYAN = 36 + ANSI_SGR_FOREGROUND_WHITE = 37 + _ANSI_SGR_RESERVED_01 = 38 + ANSI_SGR_FOREGROUND_DEFAULT = 39 + ANSI_SGR_BACKGROUND_BLACK = 40 + ANSI_SGR_BACKGROUND_RED = 41 + ANSI_SGR_BACKGROUND_GREEN = 42 + ANSI_SGR_BACKGROUND_YELLOW = 43 + ANSI_SGR_BACKGROUND_BLUE = 44 + ANSI_SGR_BACKGROUND_MAGENTA = 45 + ANSI_SGR_BACKGROUND_CYAN = 46 + ANSI_SGR_BACKGROUND_WHITE = 47 + _ANSI_SGR_RESERVED_02 = 48 + ANSI_SGR_BACKGROUND_DEFAULT = 49 + // 50 - 65: Unsupported + + ANSI_MAX_CMD_LENGTH = 4096 + + MAX_INPUT_EVENTS = 128 + DEFAULT_WIDTH = 80 + DEFAULT_HEIGHT = 24 + + ANSI_BEL = 0x07 + ANSI_BACKSPACE = 0x08 + ANSI_TAB = 0x09 + ANSI_LINE_FEED = 0x0A + ANSI_VERTICAL_TAB = 0x0B + ANSI_FORM_FEED = 0x0C + ANSI_CARRIAGE_RETURN = 0x0D + ANSI_ESCAPE_PRIMARY = 0x1B + ANSI_ESCAPE_SECONDARY = 0x5B + ANSI_OSC_STRING_ENTRY = 0x5D + ANSI_COMMAND_FIRST = 0x40 + ANSI_COMMAND_LAST = 0x7E + DCS_ENTRY = 0x90 + CSI_ENTRY = 0x9B + OSC_STRING = 0x9D + ANSI_PARAMETER_SEP = ";" + ANSI_CMD_G0 = '(' + ANSI_CMD_G1 = ')' + ANSI_CMD_G2 = '*' + ANSI_CMD_G3 = '+' + ANSI_CMD_DECPNM = '>' + ANSI_CMD_DECPAM = '=' + ANSI_CMD_OSC = ']' + ANSI_CMD_STR_TERM = '\\' + + KEY_CONTROL_PARAM_2 = ";2" + KEY_CONTROL_PARAM_3 = ";3" + KEY_CONTROL_PARAM_4 = ";4" + KEY_CONTROL_PARAM_5 = ";5" + KEY_CONTROL_PARAM_6 = ";6" + KEY_CONTROL_PARAM_7 = ";7" + KEY_CONTROL_PARAM_8 = ";8" + KEY_ESC_CSI = "\x1B[" + KEY_ESC_N = "\x1BN" + KEY_ESC_O = "\x1BO" + + FILL_CHARACTER = ' ' +) + +func getByteRange(start byte, end byte) []byte { + bytes := make([]byte, 0, 32) + for i := start; i <= end; i++ { + bytes = append(bytes, byte(i)) + } + + return bytes +} + +var toGroundBytes = getToGroundBytes() +var executors = getExecuteBytes() + +// SPACE 20+A0 hex Always and everywhere a blank space +// Intermediate 20-2F hex !"#$%&'()*+,-./ +var intermeds = getByteRange(0x20, 0x2F) + +// Parameters 30-3F hex 0123456789:;<=>? +// CSI Parameters 30-39, 3B hex 0123456789; +var csiParams = getByteRange(0x30, 0x3F) + +var csiCollectables = append(getByteRange(0x30, 0x39), getByteRange(0x3B, 0x3F)...) + +// Uppercase 40-5F hex @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ +var upperCase = getByteRange(0x40, 0x5F) + +// Lowercase 60-7E hex `abcdefghijlkmnopqrstuvwxyz{|}~ +var lowerCase = getByteRange(0x60, 0x7E) + +// Alphabetics 40-7E hex (all of upper and lower case) +var alphabetics = append(upperCase, lowerCase...) + +var printables = getByteRange(0x20, 0x7F) + +var escapeIntermediateToGroundBytes = getByteRange(0x30, 0x7E) +var escapeToGroundBytes = getEscapeToGroundBytes() + +// See http://www.vt100.net/emu/vt500_parser.png for description of the complex +// byte ranges below + +func getEscapeToGroundBytes() []byte { + escapeToGroundBytes := getByteRange(0x30, 0x4F) + escapeToGroundBytes = append(escapeToGroundBytes, getByteRange(0x51, 0x57)...) + escapeToGroundBytes = append(escapeToGroundBytes, 0x59) + escapeToGroundBytes = append(escapeToGroundBytes, 0x5A) + escapeToGroundBytes = append(escapeToGroundBytes, 0x5C) + escapeToGroundBytes = append(escapeToGroundBytes, getByteRange(0x60, 0x7E)...) + return escapeToGroundBytes +} + +func getExecuteBytes() []byte { + executeBytes := getByteRange(0x00, 0x17) + executeBytes = append(executeBytes, 0x19) + executeBytes = append(executeBytes, getByteRange(0x1C, 0x1F)...) + return executeBytes +} + +func getToGroundBytes() []byte { + groundBytes := []byte{0x18} + groundBytes = append(groundBytes, 0x1A) + groundBytes = append(groundBytes, getByteRange(0x80, 0x8F)...) + groundBytes = append(groundBytes, getByteRange(0x91, 0x97)...) + groundBytes = append(groundBytes, 0x99) + groundBytes = append(groundBytes, 0x9A) + groundBytes = append(groundBytes, 0x9C) + return groundBytes +} + +// Delete 7F hex Always and everywhere ignored +// C1 Control 80-9F hex 32 additional control characters +// G1 Displayable A1-FE hex 94 additional displayable characters +// Special A0+FF hex Same as SPACE and DELETE diff --git a/vendor/github.com/Azure/go-ansiterm/context.go b/vendor/github.com/Azure/go-ansiterm/context.go new file mode 100644 index 0000000000..8d66e777c0 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/context.go @@ -0,0 +1,7 @@ +package ansiterm + +type ansiContext struct { + currentChar byte + paramBuffer []byte + interBuffer []byte +} diff --git a/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go b/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go new file mode 100644 index 0000000000..bcbe00d0c5 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/csi_entry_state.go @@ -0,0 +1,49 @@ +package ansiterm + +type csiEntryState struct { + baseState +} + +func (csiState csiEntryState) Handle(b byte) (s state, e error) { + csiState.parser.logf("CsiEntry::Handle %#x", b) + + nextState, err := csiState.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case sliceContains(alphabetics, b): + return csiState.parser.ground, nil + case sliceContains(csiCollectables, b): + return csiState.parser.csiParam, nil + case sliceContains(executors, b): + return csiState, csiState.parser.execute() + } + + return csiState, nil +} + +func (csiState csiEntryState) Transition(s state) error { + csiState.parser.logf("CsiEntry::Transition %s --> %s", csiState.Name(), s.Name()) + csiState.baseState.Transition(s) + + switch s { + case csiState.parser.ground: + return csiState.parser.csiDispatch() + case csiState.parser.csiParam: + switch { + case sliceContains(csiParams, csiState.parser.context.currentChar): + csiState.parser.collectParam() + case sliceContains(intermeds, csiState.parser.context.currentChar): + csiState.parser.collectInter() + } + } + + return nil +} + +func (csiState csiEntryState) Enter() error { + csiState.parser.clear() + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/csi_param_state.go b/vendor/github.com/Azure/go-ansiterm/csi_param_state.go new file mode 100644 index 0000000000..7ed5e01c34 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/csi_param_state.go @@ -0,0 +1,38 @@ +package ansiterm + +type csiParamState struct { + baseState +} + +func (csiState csiParamState) Handle(b byte) (s state, e error) { + csiState.parser.logf("CsiParam::Handle %#x", b) + + nextState, err := csiState.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case sliceContains(alphabetics, b): + return csiState.parser.ground, nil + case sliceContains(csiCollectables, b): + csiState.parser.collectParam() + return csiState, nil + case sliceContains(executors, b): + return csiState, csiState.parser.execute() + } + + return csiState, nil +} + +func (csiState csiParamState) Transition(s state) error { + csiState.parser.logf("CsiParam::Transition %s --> %s", csiState.Name(), s.Name()) + csiState.baseState.Transition(s) + + switch s { + case csiState.parser.ground: + return csiState.parser.csiDispatch() + } + + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go b/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go new file mode 100644 index 0000000000..1c719db9e4 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/escape_intermediate_state.go @@ -0,0 +1,36 @@ +package ansiterm + +type escapeIntermediateState struct { + baseState +} + +func (escState escapeIntermediateState) Handle(b byte) (s state, e error) { + escState.parser.logf("escapeIntermediateState::Handle %#x", b) + nextState, err := escState.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case sliceContains(intermeds, b): + return escState, escState.parser.collectInter() + case sliceContains(executors, b): + return escState, escState.parser.execute() + case sliceContains(escapeIntermediateToGroundBytes, b): + return escState.parser.ground, nil + } + + return escState, nil +} + +func (escState escapeIntermediateState) Transition(s state) error { + escState.parser.logf("escapeIntermediateState::Transition %s --> %s", escState.Name(), s.Name()) + escState.baseState.Transition(s) + + switch s { + case escState.parser.ground: + return escState.parser.escDispatch() + } + + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/escape_state.go b/vendor/github.com/Azure/go-ansiterm/escape_state.go new file mode 100644 index 0000000000..6390abd231 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/escape_state.go @@ -0,0 +1,47 @@ +package ansiterm + +type escapeState struct { + baseState +} + +func (escState escapeState) Handle(b byte) (s state, e error) { + escState.parser.logf("escapeState::Handle %#x", b) + nextState, err := escState.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case b == ANSI_ESCAPE_SECONDARY: + return escState.parser.csiEntry, nil + case b == ANSI_OSC_STRING_ENTRY: + return escState.parser.oscString, nil + case sliceContains(executors, b): + return escState, escState.parser.execute() + case sliceContains(escapeToGroundBytes, b): + return escState.parser.ground, nil + case sliceContains(intermeds, b): + return escState.parser.escapeIntermediate, nil + } + + return escState, nil +} + +func (escState escapeState) Transition(s state) error { + escState.parser.logf("Escape::Transition %s --> %s", escState.Name(), s.Name()) + escState.baseState.Transition(s) + + switch s { + case escState.parser.ground: + return escState.parser.escDispatch() + case escState.parser.escapeIntermediate: + return escState.parser.collectInter() + } + + return nil +} + +func (escState escapeState) Enter() error { + escState.parser.clear() + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/event_handler.go b/vendor/github.com/Azure/go-ansiterm/event_handler.go new file mode 100644 index 0000000000..98087b38c2 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/event_handler.go @@ -0,0 +1,90 @@ +package ansiterm + +type AnsiEventHandler interface { + // Print + Print(b byte) error + + // Execute C0 commands + Execute(b byte) error + + // CUrsor Up + CUU(int) error + + // CUrsor Down + CUD(int) error + + // CUrsor Forward + CUF(int) error + + // CUrsor Backward + CUB(int) error + + // Cursor to Next Line + CNL(int) error + + // Cursor to Previous Line + CPL(int) error + + // Cursor Horizontal position Absolute + CHA(int) error + + // Vertical line Position Absolute + VPA(int) error + + // CUrsor Position + CUP(int, int) error + + // Horizontal and Vertical Position (depends on PUM) + HVP(int, int) error + + // Text Cursor Enable Mode + DECTCEM(bool) error + + // Origin Mode + DECOM(bool) error + + // 132 Column Mode + DECCOLM(bool) error + + // Erase in Display + ED(int) error + + // Erase in Line + EL(int) error + + // Insert Line + IL(int) error + + // Delete Line + DL(int) error + + // Insert Character + ICH(int) error + + // Delete Character + DCH(int) error + + // Set Graphics Rendition + SGR([]int) error + + // Pan Down + SU(int) error + + // Pan Up + SD(int) error + + // Device Attributes + DA([]string) error + + // Set Top and Bottom Margins + DECSTBM(int, int) error + + // Index + IND() error + + // Reverse Index + RI() error + + // Flush updates from previous commands + Flush() error +} diff --git a/vendor/github.com/Azure/go-ansiterm/ground_state.go b/vendor/github.com/Azure/go-ansiterm/ground_state.go new file mode 100644 index 0000000000..52451e9469 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/ground_state.go @@ -0,0 +1,24 @@ +package ansiterm + +type groundState struct { + baseState +} + +func (gs groundState) Handle(b byte) (s state, e error) { + gs.parser.context.currentChar = b + + nextState, err := gs.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case sliceContains(printables, b): + return gs, gs.parser.print() + + case sliceContains(executors, b): + return gs, gs.parser.execute() + } + + return gs, nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/osc_string_state.go b/vendor/github.com/Azure/go-ansiterm/osc_string_state.go new file mode 100644 index 0000000000..593b10ab69 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/osc_string_state.go @@ -0,0 +1,31 @@ +package ansiterm + +type oscStringState struct { + baseState +} + +func (oscState oscStringState) Handle(b byte) (s state, e error) { + oscState.parser.logf("OscString::Handle %#x", b) + nextState, err := oscState.baseState.Handle(b) + if nextState != nil || err != nil { + return nextState, err + } + + switch { + case isOscStringTerminator(b): + return oscState.parser.ground, nil + } + + return oscState, nil +} + +// See below for OSC string terminators for linux +// http://man7.org/linux/man-pages/man4/console_codes.4.html +func isOscStringTerminator(b byte) bool { + + if b == ANSI_BEL || b == 0x5C { + return true + } + + return false +} diff --git a/vendor/github.com/Azure/go-ansiterm/parser.go b/vendor/github.com/Azure/go-ansiterm/parser.go new file mode 100644 index 0000000000..03cec7ada6 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/parser.go @@ -0,0 +1,151 @@ +package ansiterm + +import ( + "errors" + "log" + "os" +) + +type AnsiParser struct { + currState state + eventHandler AnsiEventHandler + context *ansiContext + csiEntry state + csiParam state + dcsEntry state + escape state + escapeIntermediate state + error state + ground state + oscString state + stateMap []state + + logf func(string, ...interface{}) +} + +type Option func(*AnsiParser) + +func WithLogf(f func(string, ...interface{})) Option { + return func(ap *AnsiParser) { + ap.logf = f + } +} + +func CreateParser(initialState string, evtHandler AnsiEventHandler, opts ...Option) *AnsiParser { + ap := &AnsiParser{ + eventHandler: evtHandler, + context: &ansiContext{}, + } + for _, o := range opts { + o(ap) + } + + if isDebugEnv := os.Getenv(LogEnv); isDebugEnv == "1" { + logFile, _ := os.Create("ansiParser.log") + logger := log.New(logFile, "", log.LstdFlags) + if ap.logf != nil { + l := ap.logf + ap.logf = func(s string, v ...interface{}) { + l(s, v...) + logger.Printf(s, v...) + } + } else { + ap.logf = logger.Printf + } + } + + if ap.logf == nil { + ap.logf = func(string, ...interface{}) {} + } + + ap.csiEntry = csiEntryState{baseState{name: "CsiEntry", parser: ap}} + ap.csiParam = csiParamState{baseState{name: "CsiParam", parser: ap}} + ap.dcsEntry = dcsEntryState{baseState{name: "DcsEntry", parser: ap}} + ap.escape = escapeState{baseState{name: "Escape", parser: ap}} + ap.escapeIntermediate = escapeIntermediateState{baseState{name: "EscapeIntermediate", parser: ap}} + ap.error = errorState{baseState{name: "Error", parser: ap}} + ap.ground = groundState{baseState{name: "Ground", parser: ap}} + ap.oscString = oscStringState{baseState{name: "OscString", parser: ap}} + + ap.stateMap = []state{ + ap.csiEntry, + ap.csiParam, + ap.dcsEntry, + ap.escape, + ap.escapeIntermediate, + ap.error, + ap.ground, + ap.oscString, + } + + ap.currState = getState(initialState, ap.stateMap) + + ap.logf("CreateParser: parser %p", ap) + return ap +} + +func getState(name string, states []state) state { + for _, el := range states { + if el.Name() == name { + return el + } + } + + return nil +} + +func (ap *AnsiParser) Parse(bytes []byte) (int, error) { + for i, b := range bytes { + if err := ap.handle(b); err != nil { + return i, err + } + } + + return len(bytes), ap.eventHandler.Flush() +} + +func (ap *AnsiParser) handle(b byte) error { + ap.context.currentChar = b + newState, err := ap.currState.Handle(b) + if err != nil { + return err + } + + if newState == nil { + ap.logf("WARNING: newState is nil") + return errors.New("New state of 'nil' is invalid.") + } + + if newState != ap.currState { + if err := ap.changeState(newState); err != nil { + return err + } + } + + return nil +} + +func (ap *AnsiParser) changeState(newState state) error { + ap.logf("ChangeState %s --> %s", ap.currState.Name(), newState.Name()) + + // Exit old state + if err := ap.currState.Exit(); err != nil { + ap.logf("Exit state '%s' failed with : '%v'", ap.currState.Name(), err) + return err + } + + // Perform transition action + if err := ap.currState.Transition(newState); err != nil { + ap.logf("Transition from '%s' to '%s' failed with: '%v'", ap.currState.Name(), newState.Name, err) + return err + } + + // Enter new state + if err := newState.Enter(); err != nil { + ap.logf("Enter state '%s' failed with: '%v'", newState.Name(), err) + return err + } + + ap.currState = newState + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go b/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go new file mode 100644 index 0000000000..de0a1f9cde --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/parser_action_helpers.go @@ -0,0 +1,99 @@ +package ansiterm + +import ( + "strconv" +) + +func parseParams(bytes []byte) ([]string, error) { + paramBuff := make([]byte, 0, 0) + params := []string{} + + for _, v := range bytes { + if v == ';' { + if len(paramBuff) > 0 { + // Completed parameter, append it to the list + s := string(paramBuff) + params = append(params, s) + paramBuff = make([]byte, 0, 0) + } + } else { + paramBuff = append(paramBuff, v) + } + } + + // Last parameter may not be terminated with ';' + if len(paramBuff) > 0 { + s := string(paramBuff) + params = append(params, s) + } + + return params, nil +} + +func parseCmd(context ansiContext) (string, error) { + return string(context.currentChar), nil +} + +func getInt(params []string, dflt int) int { + i := getInts(params, 1, dflt)[0] + return i +} + +func getInts(params []string, minCount int, dflt int) []int { + ints := []int{} + + for _, v := range params { + i, _ := strconv.Atoi(v) + // Zero is mapped to the default value in VT100. + if i == 0 { + i = dflt + } + ints = append(ints, i) + } + + if len(ints) < minCount { + remaining := minCount - len(ints) + for i := 0; i < remaining; i++ { + ints = append(ints, dflt) + } + } + + return ints +} + +func (ap *AnsiParser) modeDispatch(param string, set bool) error { + switch param { + case "?3": + return ap.eventHandler.DECCOLM(set) + case "?6": + return ap.eventHandler.DECOM(set) + case "?25": + return ap.eventHandler.DECTCEM(set) + } + return nil +} + +func (ap *AnsiParser) hDispatch(params []string) error { + if len(params) == 1 { + return ap.modeDispatch(params[0], true) + } + + return nil +} + +func (ap *AnsiParser) lDispatch(params []string) error { + if len(params) == 1 { + return ap.modeDispatch(params[0], false) + } + + return nil +} + +func getEraseParam(params []string) int { + param := getInt(params, 0) + if param < 0 || 3 < param { + param = 0 + } + + return param +} diff --git a/vendor/github.com/Azure/go-ansiterm/parser_actions.go b/vendor/github.com/Azure/go-ansiterm/parser_actions.go new file mode 100644 index 0000000000..0bb5e51e9a --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/parser_actions.go @@ -0,0 +1,119 @@ +package ansiterm + +func (ap *AnsiParser) collectParam() error { + currChar := ap.context.currentChar + ap.logf("collectParam %#x", currChar) + ap.context.paramBuffer = append(ap.context.paramBuffer, currChar) + return nil +} + +func (ap *AnsiParser) collectInter() error { + currChar := ap.context.currentChar + ap.logf("collectInter %#x", currChar) + ap.context.paramBuffer = append(ap.context.interBuffer, currChar) + return nil +} + +func (ap *AnsiParser) escDispatch() error { + cmd, _ := parseCmd(*ap.context) + intermeds := ap.context.interBuffer + ap.logf("escDispatch currentChar: %#x", ap.context.currentChar) + ap.logf("escDispatch: %v(%v)", cmd, intermeds) + + switch cmd { + case "D": // IND + return ap.eventHandler.IND() + case "E": // NEL, equivalent to CRLF + err := ap.eventHandler.Execute(ANSI_CARRIAGE_RETURN) + if err == nil { + err = ap.eventHandler.Execute(ANSI_LINE_FEED) + } + return err + case "M": // RI + return ap.eventHandler.RI() + } + + return nil +} + +func (ap *AnsiParser) csiDispatch() error { + cmd, _ := parseCmd(*ap.context) + params, _ := parseParams(ap.context.paramBuffer) + ap.logf("Parsed params: %v with length: %d", params, len(params)) + + ap.logf("csiDispatch: %v(%v)", cmd, params) + + switch cmd { + case "@": + return ap.eventHandler.ICH(getInt(params, 1)) + case "A": + return ap.eventHandler.CUU(getInt(params, 1)) + case "B": + return ap.eventHandler.CUD(getInt(params, 1)) + case "C": + return ap.eventHandler.CUF(getInt(params, 1)) + case "D": + return ap.eventHandler.CUB(getInt(params, 1)) + case "E": + return ap.eventHandler.CNL(getInt(params, 1)) + case "F": + return ap.eventHandler.CPL(getInt(params, 1)) + case "G": + return ap.eventHandler.CHA(getInt(params, 1)) + case "H": + ints := getInts(params, 2, 1) + x, y := ints[0], ints[1] + return ap.eventHandler.CUP(x, y) + case "J": + param := getEraseParam(params) + return ap.eventHandler.ED(param) + case "K": + param := getEraseParam(params) + return ap.eventHandler.EL(param) + case "L": + return ap.eventHandler.IL(getInt(params, 1)) + case "M": + return ap.eventHandler.DL(getInt(params, 1)) + case "P": + return ap.eventHandler.DCH(getInt(params, 1)) + case "S": + return ap.eventHandler.SU(getInt(params, 1)) + case "T": + return ap.eventHandler.SD(getInt(params, 1)) + case "c": + return ap.eventHandler.DA(params) + case "d": + return ap.eventHandler.VPA(getInt(params, 1)) + case "f": + ints := getInts(params, 2, 1) + x, y := ints[0], ints[1] + return ap.eventHandler.HVP(x, y) + case "h": + return ap.hDispatch(params) + case "l": + return ap.lDispatch(params) + case "m": + return ap.eventHandler.SGR(getInts(params, 1, 0)) + case "r": + ints := getInts(params, 2, 1) + top, bottom := ints[0], ints[1] + return ap.eventHandler.DECSTBM(top, bottom) + default: + ap.logf("ERROR: Unsupported CSI command: '%s', with full context: %v", cmd, ap.context) + return nil + } + +} + +func (ap *AnsiParser) print() error { + return ap.eventHandler.Print(ap.context.currentChar) +} + +func (ap *AnsiParser) clear() error { + ap.context = &ansiContext{} + return nil +} + +func (ap *AnsiParser) execute() error { + return ap.eventHandler.Execute(ap.context.currentChar) +} diff --git a/vendor/github.com/Azure/go-ansiterm/states.go b/vendor/github.com/Azure/go-ansiterm/states.go new file mode 100644 index 0000000000..f2ea1fcd12 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/states.go @@ -0,0 +1,71 @@ +package ansiterm + +type stateID int + +type state interface { + Enter() error + Exit() error + Handle(byte) (state, error) + Name() string + Transition(state) error +} + +type baseState struct { + name string + parser *AnsiParser +} + +func (base baseState) Enter() error { + return nil +} + +func (base baseState) Exit() error { + return nil +} + +func (base baseState) Handle(b byte) (s state, e error) { + + switch { + case b == CSI_ENTRY: + return base.parser.csiEntry, nil + case b == DCS_ENTRY: + return base.parser.dcsEntry, nil + case b == ANSI_ESCAPE_PRIMARY: + return base.parser.escape, nil + case b == OSC_STRING: + return base.parser.oscString, nil + case sliceContains(toGroundBytes, b): + return base.parser.ground, nil + } + + return nil, nil +} + +func (base baseState) Name() string { + return base.name +} + +func (base baseState) Transition(s state) error { + if s == base.parser.ground { + execBytes := []byte{0x18} + execBytes = append(execBytes, 0x1A) + execBytes = append(execBytes, getByteRange(0x80, 0x8F)...) + execBytes = append(execBytes, getByteRange(0x91, 0x97)...) + execBytes = append(execBytes, 0x99) + execBytes = append(execBytes, 0x9A) + + if sliceContains(execBytes, base.parser.context.currentChar) { + return base.parser.execute() + } + } + + return nil +} + +type dcsEntryState struct { + baseState +} + +type errorState struct { + baseState +} diff --git a/vendor/github.com/Azure/go-ansiterm/utilities.go b/vendor/github.com/Azure/go-ansiterm/utilities.go new file mode 100644 index 0000000000..392114493a --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/utilities.go @@ -0,0 +1,21 @@ +package ansiterm + +import ( + "strconv" +) + +func sliceContains(bytes []byte, b byte) bool { + for _, v := range bytes { + if v == b { + return true + } + } + + return false +} + +func convertBytesToInteger(bytes []byte) int { + s := string(bytes) + i, _ := strconv.Atoi(s) + return i +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go b/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go new file mode 100644 index 0000000000..5599082ae9 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/ansi.go @@ -0,0 +1,196 @@ +// +build windows + +package winterm + +import ( + "fmt" + "os" + "strconv" + "strings" + "syscall" + + "github.com/Azure/go-ansiterm" + windows "golang.org/x/sys/windows" +) + +// Windows keyboard constants +// See https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx. +const ( + VK_PRIOR = 0x21 // PAGE UP key + VK_NEXT = 0x22 // PAGE DOWN key + VK_END = 0x23 // END key + VK_HOME = 0x24 // HOME key + VK_LEFT = 0x25 // LEFT ARROW key + VK_UP = 0x26 // UP ARROW key + VK_RIGHT = 0x27 // RIGHT ARROW key + VK_DOWN = 0x28 // DOWN ARROW key + VK_SELECT = 0x29 // SELECT key + VK_PRINT = 0x2A // PRINT key + VK_EXECUTE = 0x2B // EXECUTE key + VK_SNAPSHOT = 0x2C // PRINT SCREEN key + VK_INSERT = 0x2D // INS key + VK_DELETE = 0x2E // DEL key + VK_HELP = 0x2F // HELP key + VK_F1 = 0x70 // F1 key + VK_F2 = 0x71 // F2 key + VK_F3 = 0x72 // F3 key + VK_F4 = 0x73 // F4 key + VK_F5 = 0x74 // F5 key + VK_F6 = 0x75 // F6 key + VK_F7 = 0x76 // F7 key + VK_F8 = 0x77 // F8 key + VK_F9 = 0x78 // F9 key + VK_F10 = 0x79 // F10 key + VK_F11 = 0x7A // F11 key + VK_F12 = 0x7B // F12 key + + RIGHT_ALT_PRESSED = 0x0001 + LEFT_ALT_PRESSED = 0x0002 + RIGHT_CTRL_PRESSED = 0x0004 + LEFT_CTRL_PRESSED = 0x0008 + SHIFT_PRESSED = 0x0010 + NUMLOCK_ON = 0x0020 + SCROLLLOCK_ON = 0x0040 + CAPSLOCK_ON = 0x0080 + ENHANCED_KEY = 0x0100 +) + +type ansiCommand struct { + CommandBytes []byte + Command string + Parameters []string + IsSpecial bool +} + +func newAnsiCommand(command []byte) *ansiCommand { + + if isCharacterSelectionCmdChar(command[1]) { + // Is Character Set Selection commands + return &ansiCommand{ + CommandBytes: command, + Command: string(command), + IsSpecial: true, + } + } + + // last char is command character + lastCharIndex := len(command) - 1 + + ac := &ansiCommand{ + CommandBytes: command, + Command: string(command[lastCharIndex]), + IsSpecial: false, + } + + // more than a single escape + if lastCharIndex != 0 { + start := 1 + // skip if double char escape sequence + if command[0] == ansiterm.ANSI_ESCAPE_PRIMARY && command[1] == ansiterm.ANSI_ESCAPE_SECONDARY { + start++ + } + // convert this to GetNextParam method + ac.Parameters = strings.Split(string(command[start:lastCharIndex]), ansiterm.ANSI_PARAMETER_SEP) + } + + return ac +} + +func (ac *ansiCommand) paramAsSHORT(index int, defaultValue int16) int16 { + if index < 0 || index >= len(ac.Parameters) { + return defaultValue + } + + param, err := strconv.ParseInt(ac.Parameters[index], 10, 16) + if err != nil { + return defaultValue + } + + return int16(param) +} + +func (ac *ansiCommand) String() string { + return fmt.Sprintf("0x%v \"%v\" (\"%v\")", + bytesToHex(ac.CommandBytes), + ac.Command, + strings.Join(ac.Parameters, "\",\"")) +} + +// isAnsiCommandChar returns true if the passed byte falls within the range of ANSI commands. +// See http://manpages.ubuntu.com/manpages/intrepid/man4/console_codes.4.html. +func isAnsiCommandChar(b byte) bool { + switch { + case ansiterm.ANSI_COMMAND_FIRST <= b && b <= ansiterm.ANSI_COMMAND_LAST && b != ansiterm.ANSI_ESCAPE_SECONDARY: + return true + case b == ansiterm.ANSI_CMD_G1 || b == ansiterm.ANSI_CMD_OSC || b == ansiterm.ANSI_CMD_DECPAM || b == ansiterm.ANSI_CMD_DECPNM: + // non-CSI escape sequence terminator + return true + case b == ansiterm.ANSI_CMD_STR_TERM || b == ansiterm.ANSI_BEL: + // String escape sequence terminator + return true + } + return false +} + +func isXtermOscSequence(command []byte, current byte) bool { + return (len(command) >= 2 && command[0] == ansiterm.ANSI_ESCAPE_PRIMARY && command[1] == ansiterm.ANSI_CMD_OSC && current != ansiterm.ANSI_BEL) +} + +func isCharacterSelectionCmdChar(b byte) bool { + return (b == ansiterm.ANSI_CMD_G0 || b == ansiterm.ANSI_CMD_G1 || b == ansiterm.ANSI_CMD_G2 || b == ansiterm.ANSI_CMD_G3) +} + +// bytesToHex converts a slice of bytes to a human-readable string. +func bytesToHex(b []byte) string { + hex := make([]string, len(b)) + for i, ch := range b { + hex[i] = fmt.Sprintf("%X", ch) + } + return strings.Join(hex, "") +} + +// ensureInRange adjusts the passed value, if necessary, to ensure it is within +// the passed min / max range. +func ensureInRange(n int16, min int16, max int16) int16 { + if n < min { + return min + } else if n > max { + return max + } else { + return n + } +} + +func GetStdFile(nFile int) (*os.File, uintptr) { + var file *os.File + + // syscall uses negative numbers + // windows package uses very big uint32 + // Keep these switches split so we don't have to convert ints too much. + switch uint32(nFile) { + case windows.STD_INPUT_HANDLE: + file = os.Stdin + case windows.STD_OUTPUT_HANDLE: + file = os.Stdout + case windows.STD_ERROR_HANDLE: + file = os.Stderr + default: + switch nFile { + case syscall.STD_INPUT_HANDLE: + file = os.Stdin + case syscall.STD_OUTPUT_HANDLE: + file = os.Stdout + case syscall.STD_ERROR_HANDLE: + file = os.Stderr + default: + panic(fmt.Errorf("Invalid standard handle identifier: %v", nFile)) + } + } + + fd, err := syscall.GetStdHandle(nFile) + if err != nil { + panic(fmt.Errorf("Invalid standard handle identifier: %v -- %v", nFile, err)) + } + + return file, uintptr(fd) +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/api.go b/vendor/github.com/Azure/go-ansiterm/winterm/api.go new file mode 100644 index 0000000000..6055e33b91 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/api.go @@ -0,0 +1,327 @@ +// +build windows + +package winterm + +import ( + "fmt" + "syscall" + "unsafe" +) + +//=========================================================================================================== +// IMPORTANT NOTE: +// +// The methods below make extensive use of the "unsafe" package to obtain the required pointers. +// Beginning in Go 1.3, the garbage collector may release local variables (e.g., incoming arguments, stack +// variables) the pointers reference *before* the API completes. +// +// As a result, in those cases, the code must hint that the variables remain in active by invoking the +// dummy method "use" (see below). Newer versions of Go are planned to change the mechanism to no longer +// require unsafe pointers. +// +// If you add or modify methods, ENSURE protection of local variables through the "use" builtin to inform +// the garbage collector the variables remain in use if: +// +// -- The value is not a pointer (e.g., int32, struct) +// -- The value is not referenced by the method after passing the pointer to Windows +// +// See http://golang.org/doc/go1.3. +//=========================================================================================================== + +var ( + kernel32DLL = syscall.NewLazyDLL("kernel32.dll") + + getConsoleCursorInfoProc = kernel32DLL.NewProc("GetConsoleCursorInfo") + setConsoleCursorInfoProc = kernel32DLL.NewProc("SetConsoleCursorInfo") + setConsoleCursorPositionProc = kernel32DLL.NewProc("SetConsoleCursorPosition") + setConsoleModeProc = kernel32DLL.NewProc("SetConsoleMode") + getConsoleScreenBufferInfoProc = kernel32DLL.NewProc("GetConsoleScreenBufferInfo") + setConsoleScreenBufferSizeProc = kernel32DLL.NewProc("SetConsoleScreenBufferSize") + scrollConsoleScreenBufferProc = kernel32DLL.NewProc("ScrollConsoleScreenBufferA") + setConsoleTextAttributeProc = kernel32DLL.NewProc("SetConsoleTextAttribute") + setConsoleWindowInfoProc = kernel32DLL.NewProc("SetConsoleWindowInfo") + writeConsoleOutputProc = kernel32DLL.NewProc("WriteConsoleOutputW") + readConsoleInputProc = kernel32DLL.NewProc("ReadConsoleInputW") + waitForSingleObjectProc = kernel32DLL.NewProc("WaitForSingleObject") +) + +// Windows Console constants +const ( + // Console modes + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx. + ENABLE_PROCESSED_INPUT = 0x0001 + ENABLE_LINE_INPUT = 0x0002 + ENABLE_ECHO_INPUT = 0x0004 + ENABLE_WINDOW_INPUT = 0x0008 + ENABLE_MOUSE_INPUT = 0x0010 + ENABLE_INSERT_MODE = 0x0020 + ENABLE_QUICK_EDIT_MODE = 0x0040 + ENABLE_EXTENDED_FLAGS = 0x0080 + ENABLE_AUTO_POSITION = 0x0100 + ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200 + + ENABLE_PROCESSED_OUTPUT = 0x0001 + ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002 + ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 + DISABLE_NEWLINE_AUTO_RETURN = 0x0008 + ENABLE_LVB_GRID_WORLDWIDE = 0x0010 + + // Character attributes + // Note: + // -- The attributes are combined to produce various colors (e.g., Blue + Green will create Cyan). + // Clearing all foreground or background colors results in black; setting all creates white. + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682088(v=vs.85).aspx#_win32_character_attributes. + FOREGROUND_BLUE uint16 = 0x0001 + FOREGROUND_GREEN uint16 = 0x0002 + FOREGROUND_RED uint16 = 0x0004 + FOREGROUND_INTENSITY uint16 = 0x0008 + FOREGROUND_MASK uint16 = 0x000F + + BACKGROUND_BLUE uint16 = 0x0010 + BACKGROUND_GREEN uint16 = 0x0020 + BACKGROUND_RED uint16 = 0x0040 + BACKGROUND_INTENSITY uint16 = 0x0080 + BACKGROUND_MASK uint16 = 0x00F0 + + COMMON_LVB_MASK uint16 = 0xFF00 + COMMON_LVB_REVERSE_VIDEO uint16 = 0x4000 + COMMON_LVB_UNDERSCORE uint16 = 0x8000 + + // Input event types + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx. + KEY_EVENT = 0x0001 + MOUSE_EVENT = 0x0002 + WINDOW_BUFFER_SIZE_EVENT = 0x0004 + MENU_EVENT = 0x0008 + FOCUS_EVENT = 0x0010 + + // WaitForSingleObject return codes + WAIT_ABANDONED = 0x00000080 + WAIT_FAILED = 0xFFFFFFFF + WAIT_SIGNALED = 0x0000000 + WAIT_TIMEOUT = 0x00000102 + + // WaitForSingleObject wait duration + WAIT_INFINITE = 0xFFFFFFFF + WAIT_ONE_SECOND = 1000 + WAIT_HALF_SECOND = 500 + WAIT_QUARTER_SECOND = 250 +) + +// Windows API Console types +// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms682101(v=vs.85).aspx for Console specific types (e.g., COORD) +// -- See https://msdn.microsoft.com/en-us/library/aa296569(v=vs.60).aspx for comments on alignment +type ( + CHAR_INFO struct { + UnicodeChar uint16 + Attributes uint16 + } + + CONSOLE_CURSOR_INFO struct { + Size uint32 + Visible int32 + } + + CONSOLE_SCREEN_BUFFER_INFO struct { + Size COORD + CursorPosition COORD + Attributes uint16 + Window SMALL_RECT + MaximumWindowSize COORD + } + + COORD struct { + X int16 + Y int16 + } + + SMALL_RECT struct { + Left int16 + Top int16 + Right int16 + Bottom int16 + } + + // INPUT_RECORD is a C/C++ union of which KEY_EVENT_RECORD is one case, it is also the largest + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683499(v=vs.85).aspx. + INPUT_RECORD struct { + EventType uint16 + KeyEvent KEY_EVENT_RECORD + } + + KEY_EVENT_RECORD struct { + KeyDown int32 + RepeatCount uint16 + VirtualKeyCode uint16 + VirtualScanCode uint16 + UnicodeChar uint16 + ControlKeyState uint32 + } + + WINDOW_BUFFER_SIZE struct { + Size COORD + } +) + +// boolToBOOL converts a Go bool into a Windows int32. +func boolToBOOL(f bool) int32 { + if f { + return int32(1) + } else { + return int32(0) + } +} + +// GetConsoleCursorInfo retrieves information about the size and visiblity of the console cursor. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683163(v=vs.85).aspx. +func GetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error { + r1, r2, err := getConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0) + return checkError(r1, r2, err) +} + +// SetConsoleCursorInfo sets the size and visiblity of the console cursor. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686019(v=vs.85).aspx. +func SetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error { + r1, r2, err := setConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0) + return checkError(r1, r2, err) +} + +// SetConsoleCursorPosition location of the console cursor. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686025(v=vs.85).aspx. +func SetConsoleCursorPosition(handle uintptr, coord COORD) error { + r1, r2, err := setConsoleCursorPositionProc.Call(handle, coordToPointer(coord)) + use(coord) + return checkError(r1, r2, err) +} + +// GetConsoleMode gets the console mode for given file descriptor +// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx. +func GetConsoleMode(handle uintptr) (mode uint32, err error) { + err = syscall.GetConsoleMode(syscall.Handle(handle), &mode) + return mode, err +} + +// SetConsoleMode sets the console mode for given file descriptor +// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx. +func SetConsoleMode(handle uintptr, mode uint32) error { + r1, r2, err := setConsoleModeProc.Call(handle, uintptr(mode), 0) + use(mode) + return checkError(r1, r2, err) +} + +// GetConsoleScreenBufferInfo retrieves information about the specified console screen buffer. +// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx. +func GetConsoleScreenBufferInfo(handle uintptr) (*CONSOLE_SCREEN_BUFFER_INFO, error) { + info := CONSOLE_SCREEN_BUFFER_INFO{} + err := checkError(getConsoleScreenBufferInfoProc.Call(handle, uintptr(unsafe.Pointer(&info)), 0)) + if err != nil { + return nil, err + } + return &info, nil +} + +func ScrollConsoleScreenBuffer(handle uintptr, scrollRect SMALL_RECT, clipRect SMALL_RECT, destOrigin COORD, char CHAR_INFO) error { + r1, r2, err := scrollConsoleScreenBufferProc.Call(handle, uintptr(unsafe.Pointer(&scrollRect)), uintptr(unsafe.Pointer(&clipRect)), coordToPointer(destOrigin), uintptr(unsafe.Pointer(&char))) + use(scrollRect) + use(clipRect) + use(destOrigin) + use(char) + return checkError(r1, r2, err) +} + +// SetConsoleScreenBufferSize sets the size of the console screen buffer. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686044(v=vs.85).aspx. +func SetConsoleScreenBufferSize(handle uintptr, coord COORD) error { + r1, r2, err := setConsoleScreenBufferSizeProc.Call(handle, coordToPointer(coord)) + use(coord) + return checkError(r1, r2, err) +} + +// SetConsoleTextAttribute sets the attributes of characters written to the +// console screen buffer by the WriteFile or WriteConsole function. +// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms686047(v=vs.85).aspx. +func SetConsoleTextAttribute(handle uintptr, attribute uint16) error { + r1, r2, err := setConsoleTextAttributeProc.Call(handle, uintptr(attribute), 0) + use(attribute) + return checkError(r1, r2, err) +} + +// SetConsoleWindowInfo sets the size and position of the console screen buffer's window. +// Note that the size and location must be within and no larger than the backing console screen buffer. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686125(v=vs.85).aspx. +func SetConsoleWindowInfo(handle uintptr, isAbsolute bool, rect SMALL_RECT) error { + r1, r2, err := setConsoleWindowInfoProc.Call(handle, uintptr(boolToBOOL(isAbsolute)), uintptr(unsafe.Pointer(&rect))) + use(isAbsolute) + use(rect) + return checkError(r1, r2, err) +} + +// WriteConsoleOutput writes the CHAR_INFOs from the provided buffer to the active console buffer. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687404(v=vs.85).aspx. +func WriteConsoleOutput(handle uintptr, buffer []CHAR_INFO, bufferSize COORD, bufferCoord COORD, writeRegion *SMALL_RECT) error { + r1, r2, err := writeConsoleOutputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), coordToPointer(bufferSize), coordToPointer(bufferCoord), uintptr(unsafe.Pointer(writeRegion))) + use(buffer) + use(bufferSize) + use(bufferCoord) + return checkError(r1, r2, err) +} + +// ReadConsoleInput reads (and removes) data from the console input buffer. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx. +func ReadConsoleInput(handle uintptr, buffer []INPUT_RECORD, count *uint32) error { + r1, r2, err := readConsoleInputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), uintptr(len(buffer)), uintptr(unsafe.Pointer(count))) + use(buffer) + return checkError(r1, r2, err) +} + +// WaitForSingleObject waits for the passed handle to be signaled. +// It returns true if the handle was signaled; false otherwise. +// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms687032(v=vs.85).aspx. +func WaitForSingleObject(handle uintptr, msWait uint32) (bool, error) { + r1, _, err := waitForSingleObjectProc.Call(handle, uintptr(uint32(msWait))) + switch r1 { + case WAIT_ABANDONED, WAIT_TIMEOUT: + return false, nil + case WAIT_SIGNALED: + return true, nil + } + use(msWait) + return false, err +} + +// String helpers +func (info CONSOLE_SCREEN_BUFFER_INFO) String() string { + return fmt.Sprintf("Size(%v) Cursor(%v) Window(%v) Max(%v)", info.Size, info.CursorPosition, info.Window, info.MaximumWindowSize) +} + +func (coord COORD) String() string { + return fmt.Sprintf("%v,%v", coord.X, coord.Y) +} + +func (rect SMALL_RECT) String() string { + return fmt.Sprintf("(%v,%v),(%v,%v)", rect.Left, rect.Top, rect.Right, rect.Bottom) +} + +// checkError evaluates the results of a Windows API call and returns the error if it failed. +func checkError(r1, r2 uintptr, err error) error { + // Windows APIs return non-zero to indicate success + if r1 != 0 { + return nil + } + + // Return the error if provided, otherwise default to EINVAL + if err != nil { + return err + } + return syscall.EINVAL +} + +// coordToPointer converts a COORD into a uintptr (by fooling the type system). +func coordToPointer(c COORD) uintptr { + // Note: This code assumes the two SHORTs are correctly laid out; the "cast" to uint32 is just to get a pointer to pass. + return uintptr(*((*uint32)(unsafe.Pointer(&c)))) +} + +// use is a no-op, but the compiler cannot see that it is. +// Calling use(p) ensures that p is kept live until that point. +func use(p interface{}) {} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go b/vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go new file mode 100644 index 0000000000..cbec8f728f --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/attr_translation.go @@ -0,0 +1,100 @@ +// +build windows + +package winterm + +import "github.com/Azure/go-ansiterm" + +const ( + FOREGROUND_COLOR_MASK = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE + BACKGROUND_COLOR_MASK = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE +) + +// collectAnsiIntoWindowsAttributes modifies the passed Windows text mode flags to reflect the +// request represented by the passed ANSI mode. +func collectAnsiIntoWindowsAttributes(windowsMode uint16, inverted bool, baseMode uint16, ansiMode int16) (uint16, bool) { + switch ansiMode { + + // Mode styles + case ansiterm.ANSI_SGR_BOLD: + windowsMode = windowsMode | FOREGROUND_INTENSITY + + case ansiterm.ANSI_SGR_DIM, ansiterm.ANSI_SGR_BOLD_DIM_OFF: + windowsMode &^= FOREGROUND_INTENSITY + + case ansiterm.ANSI_SGR_UNDERLINE: + windowsMode = windowsMode | COMMON_LVB_UNDERSCORE + + case ansiterm.ANSI_SGR_REVERSE: + inverted = true + + case ansiterm.ANSI_SGR_REVERSE_OFF: + inverted = false + + case ansiterm.ANSI_SGR_UNDERLINE_OFF: + windowsMode &^= COMMON_LVB_UNDERSCORE + + // Foreground colors + case ansiterm.ANSI_SGR_FOREGROUND_DEFAULT: + windowsMode = (windowsMode &^ FOREGROUND_MASK) | (baseMode & FOREGROUND_MASK) + + case ansiterm.ANSI_SGR_FOREGROUND_BLACK: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) + + case ansiterm.ANSI_SGR_FOREGROUND_RED: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED + + case ansiterm.ANSI_SGR_FOREGROUND_GREEN: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_GREEN + + case ansiterm.ANSI_SGR_FOREGROUND_YELLOW: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_GREEN + + case ansiterm.ANSI_SGR_FOREGROUND_BLUE: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_BLUE + + case ansiterm.ANSI_SGR_FOREGROUND_MAGENTA: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_BLUE + + case ansiterm.ANSI_SGR_FOREGROUND_CYAN: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_GREEN | FOREGROUND_BLUE + + case ansiterm.ANSI_SGR_FOREGROUND_WHITE: + windowsMode = (windowsMode &^ FOREGROUND_COLOR_MASK) | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE + + // Background colors + case ansiterm.ANSI_SGR_BACKGROUND_DEFAULT: + // Black with no intensity + windowsMode = (windowsMode &^ BACKGROUND_MASK) | (baseMode & BACKGROUND_MASK) + + case ansiterm.ANSI_SGR_BACKGROUND_BLACK: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) + + case ansiterm.ANSI_SGR_BACKGROUND_RED: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED + + case ansiterm.ANSI_SGR_BACKGROUND_GREEN: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_GREEN + + case ansiterm.ANSI_SGR_BACKGROUND_YELLOW: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_GREEN + + case ansiterm.ANSI_SGR_BACKGROUND_BLUE: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_BLUE + + case ansiterm.ANSI_SGR_BACKGROUND_MAGENTA: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_BLUE + + case ansiterm.ANSI_SGR_BACKGROUND_CYAN: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_GREEN | BACKGROUND_BLUE + + case ansiterm.ANSI_SGR_BACKGROUND_WHITE: + windowsMode = (windowsMode &^ BACKGROUND_COLOR_MASK) | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE + } + + return windowsMode, inverted +} + +// invertAttributes inverts the foreground and background colors of a Windows attributes value +func invertAttributes(windowsMode uint16) uint16 { + return (COMMON_LVB_MASK & windowsMode) | ((FOREGROUND_MASK & windowsMode) << 4) | ((BACKGROUND_MASK & windowsMode) >> 4) +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go b/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go new file mode 100644 index 0000000000..3ee06ea728 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/cursor_helpers.go @@ -0,0 +1,101 @@ +// +build windows + +package winterm + +const ( + horizontal = iota + vertical +) + +func (h *windowsAnsiEventHandler) getCursorWindow(info *CONSOLE_SCREEN_BUFFER_INFO) SMALL_RECT { + if h.originMode { + sr := h.effectiveSr(info.Window) + return SMALL_RECT{ + Top: sr.top, + Bottom: sr.bottom, + Left: 0, + Right: info.Size.X - 1, + } + } else { + return SMALL_RECT{ + Top: info.Window.Top, + Bottom: info.Window.Bottom, + Left: 0, + Right: info.Size.X - 1, + } + } +} + +// setCursorPosition sets the cursor to the specified position, bounded to the screen size +func (h *windowsAnsiEventHandler) setCursorPosition(position COORD, window SMALL_RECT) error { + position.X = ensureInRange(position.X, window.Left, window.Right) + position.Y = ensureInRange(position.Y, window.Top, window.Bottom) + err := SetConsoleCursorPosition(h.fd, position) + if err != nil { + return err + } + h.logf("Cursor position set: (%d, %d)", position.X, position.Y) + return err +} + +func (h *windowsAnsiEventHandler) moveCursorVertical(param int) error { + return h.moveCursor(vertical, param) +} + +func (h *windowsAnsiEventHandler) moveCursorHorizontal(param int) error { + return h.moveCursor(horizontal, param) +} + +func (h *windowsAnsiEventHandler) moveCursor(moveMode int, param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + position := info.CursorPosition + switch moveMode { + case horizontal: + position.X += int16(param) + case vertical: + position.Y += int16(param) + } + + if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil { + return err + } + + return nil +} + +func (h *windowsAnsiEventHandler) moveCursorLine(param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + position := info.CursorPosition + position.X = 0 + position.Y += int16(param) + + if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil { + return err + } + + return nil +} + +func (h *windowsAnsiEventHandler) moveCursorColumn(param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + position := info.CursorPosition + position.X = int16(param) - 1 + + if err = h.setCursorPosition(position, h.getCursorWindow(info)); err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go b/vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go new file mode 100644 index 0000000000..244b5fa25e --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/erase_helpers.go @@ -0,0 +1,84 @@ +// +build windows + +package winterm + +import "github.com/Azure/go-ansiterm" + +func (h *windowsAnsiEventHandler) clearRange(attributes uint16, fromCoord COORD, toCoord COORD) error { + // Ignore an invalid (negative area) request + if toCoord.Y < fromCoord.Y { + return nil + } + + var err error + + var coordStart = COORD{} + var coordEnd = COORD{} + + xCurrent, yCurrent := fromCoord.X, fromCoord.Y + xEnd, yEnd := toCoord.X, toCoord.Y + + // Clear any partial initial line + if xCurrent > 0 { + coordStart.X, coordStart.Y = xCurrent, yCurrent + coordEnd.X, coordEnd.Y = xEnd, yCurrent + + err = h.clearRect(attributes, coordStart, coordEnd) + if err != nil { + return err + } + + xCurrent = 0 + yCurrent += 1 + } + + // Clear intervening rectangular section + if yCurrent < yEnd { + coordStart.X, coordStart.Y = xCurrent, yCurrent + coordEnd.X, coordEnd.Y = xEnd, yEnd-1 + + err = h.clearRect(attributes, coordStart, coordEnd) + if err != nil { + return err + } + + xCurrent = 0 + yCurrent = yEnd + } + + // Clear remaining partial ending line + coordStart.X, coordStart.Y = xCurrent, yCurrent + coordEnd.X, coordEnd.Y = xEnd, yEnd + + err = h.clearRect(attributes, coordStart, coordEnd) + if err != nil { + return err + } + + return nil +} + +func (h *windowsAnsiEventHandler) clearRect(attributes uint16, fromCoord COORD, toCoord COORD) error { + region := SMALL_RECT{Top: fromCoord.Y, Left: fromCoord.X, Bottom: toCoord.Y, Right: toCoord.X} + width := toCoord.X - fromCoord.X + 1 + height := toCoord.Y - fromCoord.Y + 1 + size := uint32(width) * uint32(height) + + if size <= 0 { + return nil + } + + buffer := make([]CHAR_INFO, size) + + char := CHAR_INFO{ansiterm.FILL_CHARACTER, attributes} + for i := 0; i < int(size); i++ { + buffer[i] = char + } + + err := WriteConsoleOutput(h.fd, buffer, COORD{X: width, Y: height}, COORD{X: 0, Y: 0}, ®ion) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go b/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go new file mode 100644 index 0000000000..2d27fa1d02 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/scroll_helper.go @@ -0,0 +1,118 @@ +// +build windows + +package winterm + +// effectiveSr gets the current effective scroll region in buffer coordinates +func (h *windowsAnsiEventHandler) effectiveSr(window SMALL_RECT) scrollRegion { + top := addInRange(window.Top, h.sr.top, window.Top, window.Bottom) + bottom := addInRange(window.Top, h.sr.bottom, window.Top, window.Bottom) + if top >= bottom { + top = window.Top + bottom = window.Bottom + } + return scrollRegion{top: top, bottom: bottom} +} + +func (h *windowsAnsiEventHandler) scrollUp(param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + sr := h.effectiveSr(info.Window) + return h.scroll(param, sr, info) +} + +func (h *windowsAnsiEventHandler) scrollDown(param int) error { + return h.scrollUp(-param) +} + +func (h *windowsAnsiEventHandler) deleteLines(param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + start := info.CursorPosition.Y + sr := h.effectiveSr(info.Window) + // Lines cannot be inserted or deleted outside the scrolling region. + if start >= sr.top && start <= sr.bottom { + sr.top = start + return h.scroll(param, sr, info) + } else { + return nil + } +} + +func (h *windowsAnsiEventHandler) insertLines(param int) error { + return h.deleteLines(-param) +} + +// scroll scrolls the provided scroll region by param lines. The scroll region is in buffer coordinates. +func (h *windowsAnsiEventHandler) scroll(param int, sr scrollRegion, info *CONSOLE_SCREEN_BUFFER_INFO) error { + h.logf("scroll: scrollTop: %d, scrollBottom: %d", sr.top, sr.bottom) + h.logf("scroll: windowTop: %d, windowBottom: %d", info.Window.Top, info.Window.Bottom) + + // Copy from and clip to the scroll region (full buffer width) + scrollRect := SMALL_RECT{ + Top: sr.top, + Bottom: sr.bottom, + Left: 0, + Right: info.Size.X - 1, + } + + // Origin to which area should be copied + destOrigin := COORD{ + X: 0, + Y: sr.top - int16(param), + } + + char := CHAR_INFO{ + UnicodeChar: ' ', + Attributes: h.attributes, + } + + if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil { + return err + } + return nil +} + +func (h *windowsAnsiEventHandler) deleteCharacters(param int) error { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + return h.scrollLine(param, info.CursorPosition, info) +} + +func (h *windowsAnsiEventHandler) insertCharacters(param int) error { + return h.deleteCharacters(-param) +} + +// scrollLine scrolls a line horizontally starting at the provided position by a number of columns. +func (h *windowsAnsiEventHandler) scrollLine(columns int, position COORD, info *CONSOLE_SCREEN_BUFFER_INFO) error { + // Copy from and clip to the scroll region (full buffer width) + scrollRect := SMALL_RECT{ + Top: position.Y, + Bottom: position.Y, + Left: position.X, + Right: info.Size.X - 1, + } + + // Origin to which area should be copied + destOrigin := COORD{ + X: position.X - int16(columns), + Y: position.Y, + } + + char := CHAR_INFO{ + UnicodeChar: ' ', + Attributes: h.attributes, + } + + if err := ScrollConsoleScreenBuffer(h.fd, scrollRect, scrollRect, destOrigin, char); err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/utilities.go b/vendor/github.com/Azure/go-ansiterm/winterm/utilities.go new file mode 100644 index 0000000000..afa7635d77 --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/utilities.go @@ -0,0 +1,9 @@ +// +build windows + +package winterm + +// AddInRange increments a value by the passed quantity while ensuring the values +// always remain within the supplied min / max range. +func addInRange(n int16, increment int16, min int16, max int16) int16 { + return ensureInRange(n+increment, min, max) +} diff --git a/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go b/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go new file mode 100644 index 0000000000..2d40fb75ad --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/winterm/win_event_handler.go @@ -0,0 +1,743 @@ +// +build windows + +package winterm + +import ( + "bytes" + "log" + "os" + "strconv" + + "github.com/Azure/go-ansiterm" +) + +type windowsAnsiEventHandler struct { + fd uintptr + file *os.File + infoReset *CONSOLE_SCREEN_BUFFER_INFO + sr scrollRegion + buffer bytes.Buffer + attributes uint16 + inverted bool + wrapNext bool + drewMarginByte bool + originMode bool + marginByte byte + curInfo *CONSOLE_SCREEN_BUFFER_INFO + curPos COORD + logf func(string, ...interface{}) +} + +type Option func(*windowsAnsiEventHandler) + +func WithLogf(f func(string, ...interface{})) Option { + return func(w *windowsAnsiEventHandler) { + w.logf = f + } +} + +func CreateWinEventHandler(fd uintptr, file *os.File, opts ...Option) ansiterm.AnsiEventHandler { + infoReset, err := GetConsoleScreenBufferInfo(fd) + if err != nil { + return nil + } + + h := &windowsAnsiEventHandler{ + fd: fd, + file: file, + infoReset: infoReset, + attributes: infoReset.Attributes, + } + for _, o := range opts { + o(h) + } + + if isDebugEnv := os.Getenv(ansiterm.LogEnv); isDebugEnv == "1" { + logFile, _ := os.Create("winEventHandler.log") + logger := log.New(logFile, "", log.LstdFlags) + if h.logf != nil { + l := h.logf + h.logf = func(s string, v ...interface{}) { + l(s, v...) + logger.Printf(s, v...) + } + } else { + h.logf = logger.Printf + } + } + + if h.logf == nil { + h.logf = func(string, ...interface{}) {} + } + + return h +} + +type scrollRegion struct { + top int16 + bottom int16 +} + +// simulateLF simulates a LF or CR+LF by scrolling if necessary to handle the +// current cursor position and scroll region settings, in which case it returns +// true. If no special handling is necessary, then it does nothing and returns +// false. +// +// In the false case, the caller should ensure that a carriage return +// and line feed are inserted or that the text is otherwise wrapped. +func (h *windowsAnsiEventHandler) simulateLF(includeCR bool) (bool, error) { + if h.wrapNext { + if err := h.Flush(); err != nil { + return false, err + } + h.clearWrap() + } + pos, info, err := h.getCurrentInfo() + if err != nil { + return false, err + } + sr := h.effectiveSr(info.Window) + if pos.Y == sr.bottom { + // Scrolling is necessary. Let Windows automatically scroll if the scrolling region + // is the full window. + if sr.top == info.Window.Top && sr.bottom == info.Window.Bottom { + if includeCR { + pos.X = 0 + h.updatePos(pos) + } + return false, nil + } + + // A custom scroll region is active. Scroll the window manually to simulate + // the LF. + if err := h.Flush(); err != nil { + return false, err + } + h.logf("Simulating LF inside scroll region") + if err := h.scrollUp(1); err != nil { + return false, err + } + if includeCR { + pos.X = 0 + if err := SetConsoleCursorPosition(h.fd, pos); err != nil { + return false, err + } + } + return true, nil + + } else if pos.Y < info.Window.Bottom { + // Let Windows handle the LF. + pos.Y++ + if includeCR { + pos.X = 0 + } + h.updatePos(pos) + return false, nil + } else { + // The cursor is at the bottom of the screen but outside the scroll + // region. Skip the LF. + h.logf("Simulating LF outside scroll region") + if includeCR { + if err := h.Flush(); err != nil { + return false, err + } + pos.X = 0 + if err := SetConsoleCursorPosition(h.fd, pos); err != nil { + return false, err + } + } + return true, nil + } +} + +// executeLF executes a LF without a CR. +func (h *windowsAnsiEventHandler) executeLF() error { + handled, err := h.simulateLF(false) + if err != nil { + return err + } + if !handled { + // Windows LF will reset the cursor column position. Write the LF + // and restore the cursor position. + pos, _, err := h.getCurrentInfo() + if err != nil { + return err + } + h.buffer.WriteByte(ansiterm.ANSI_LINE_FEED) + if pos.X != 0 { + if err := h.Flush(); err != nil { + return err + } + h.logf("Resetting cursor position for LF without CR") + if err := SetConsoleCursorPosition(h.fd, pos); err != nil { + return err + } + } + } + return nil +} + +func (h *windowsAnsiEventHandler) Print(b byte) error { + if h.wrapNext { + h.buffer.WriteByte(h.marginByte) + h.clearWrap() + if _, err := h.simulateLF(true); err != nil { + return err + } + } + pos, info, err := h.getCurrentInfo() + if err != nil { + return err + } + if pos.X == info.Size.X-1 { + h.wrapNext = true + h.marginByte = b + } else { + pos.X++ + h.updatePos(pos) + h.buffer.WriteByte(b) + } + return nil +} + +func (h *windowsAnsiEventHandler) Execute(b byte) error { + switch b { + case ansiterm.ANSI_TAB: + h.logf("Execute(TAB)") + // Move to the next tab stop, but preserve auto-wrap if already set. + if !h.wrapNext { + pos, info, err := h.getCurrentInfo() + if err != nil { + return err + } + pos.X = (pos.X + 8) - pos.X%8 + if pos.X >= info.Size.X { + pos.X = info.Size.X - 1 + } + if err := h.Flush(); err != nil { + return err + } + if err := SetConsoleCursorPosition(h.fd, pos); err != nil { + return err + } + } + return nil + + case ansiterm.ANSI_BEL: + h.buffer.WriteByte(ansiterm.ANSI_BEL) + return nil + + case ansiterm.ANSI_BACKSPACE: + if h.wrapNext { + if err := h.Flush(); err != nil { + return err + } + h.clearWrap() + } + pos, _, err := h.getCurrentInfo() + if err != nil { + return err + } + if pos.X > 0 { + pos.X-- + h.updatePos(pos) + h.buffer.WriteByte(ansiterm.ANSI_BACKSPACE) + } + return nil + + case ansiterm.ANSI_VERTICAL_TAB, ansiterm.ANSI_FORM_FEED: + // Treat as true LF. + return h.executeLF() + + case ansiterm.ANSI_LINE_FEED: + // Simulate a CR and LF for now since there is no way in go-ansiterm + // to tell if the LF should include CR (and more things break when it's + // missing than when it's incorrectly added). + handled, err := h.simulateLF(true) + if handled || err != nil { + return err + } + return h.buffer.WriteByte(ansiterm.ANSI_LINE_FEED) + + case ansiterm.ANSI_CARRIAGE_RETURN: + if h.wrapNext { + if err := h.Flush(); err != nil { + return err + } + h.clearWrap() + } + pos, _, err := h.getCurrentInfo() + if err != nil { + return err + } + if pos.X != 0 { + pos.X = 0 + h.updatePos(pos) + h.buffer.WriteByte(ansiterm.ANSI_CARRIAGE_RETURN) + } + return nil + + default: + return nil + } +} + +func (h *windowsAnsiEventHandler) CUU(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CUU: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorVertical(-param) +} + +func (h *windowsAnsiEventHandler) CUD(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CUD: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorVertical(param) +} + +func (h *windowsAnsiEventHandler) CUF(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CUF: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorHorizontal(param) +} + +func (h *windowsAnsiEventHandler) CUB(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CUB: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorHorizontal(-param) +} + +func (h *windowsAnsiEventHandler) CNL(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CNL: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorLine(param) +} + +func (h *windowsAnsiEventHandler) CPL(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CPL: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorLine(-param) +} + +func (h *windowsAnsiEventHandler) CHA(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CHA: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.moveCursorColumn(param) +} + +func (h *windowsAnsiEventHandler) VPA(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("VPA: [[%d]]", param) + h.clearWrap() + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + window := h.getCursorWindow(info) + position := info.CursorPosition + position.Y = window.Top + int16(param) - 1 + return h.setCursorPosition(position, window) +} + +func (h *windowsAnsiEventHandler) CUP(row int, col int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("CUP: [[%d %d]]", row, col) + h.clearWrap() + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + window := h.getCursorWindow(info) + position := COORD{window.Left + int16(col) - 1, window.Top + int16(row) - 1} + return h.setCursorPosition(position, window) +} + +func (h *windowsAnsiEventHandler) HVP(row int, col int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("HVP: [[%d %d]]", row, col) + h.clearWrap() + return h.CUP(row, col) +} + +func (h *windowsAnsiEventHandler) DECTCEM(visible bool) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DECTCEM: [%v]", []string{strconv.FormatBool(visible)}) + h.clearWrap() + return nil +} + +func (h *windowsAnsiEventHandler) DECOM(enable bool) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DECOM: [%v]", []string{strconv.FormatBool(enable)}) + h.clearWrap() + h.originMode = enable + return h.CUP(1, 1) +} + +func (h *windowsAnsiEventHandler) DECCOLM(use132 bool) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DECCOLM: [%v]", []string{strconv.FormatBool(use132)}) + h.clearWrap() + if err := h.ED(2); err != nil { + return err + } + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + targetWidth := int16(80) + if use132 { + targetWidth = 132 + } + if info.Size.X < targetWidth { + if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil { + h.logf("set buffer failed: %v", err) + return err + } + } + window := info.Window + window.Left = 0 + window.Right = targetWidth - 1 + if err := SetConsoleWindowInfo(h.fd, true, window); err != nil { + h.logf("set window failed: %v", err) + return err + } + if info.Size.X > targetWidth { + if err := SetConsoleScreenBufferSize(h.fd, COORD{targetWidth, info.Size.Y}); err != nil { + h.logf("set buffer failed: %v", err) + return err + } + } + return SetConsoleCursorPosition(h.fd, COORD{0, 0}) +} + +func (h *windowsAnsiEventHandler) ED(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("ED: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + + // [J -- Erases from the cursor to the end of the screen, including the cursor position. + // [1J -- Erases from the beginning of the screen to the cursor, including the cursor position. + // [2J -- Erases the complete display. The cursor does not move. + // Notes: + // -- Clearing the entire buffer, versus just the Window, works best for Windows Consoles + + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + var start COORD + var end COORD + + switch param { + case 0: + start = info.CursorPosition + end = COORD{info.Size.X - 1, info.Size.Y - 1} + + case 1: + start = COORD{0, 0} + end = info.CursorPosition + + case 2: + start = COORD{0, 0} + end = COORD{info.Size.X - 1, info.Size.Y - 1} + } + + err = h.clearRange(h.attributes, start, end) + if err != nil { + return err + } + + // If the whole buffer was cleared, move the window to the top while preserving + // the window-relative cursor position. + if param == 2 { + pos := info.CursorPosition + window := info.Window + pos.Y -= window.Top + window.Bottom -= window.Top + window.Top = 0 + if err := SetConsoleCursorPosition(h.fd, pos); err != nil { + return err + } + if err := SetConsoleWindowInfo(h.fd, true, window); err != nil { + return err + } + } + + return nil +} + +func (h *windowsAnsiEventHandler) EL(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("EL: [%v]", strconv.Itoa(param)) + h.clearWrap() + + // [K -- Erases from the cursor to the end of the line, including the cursor position. + // [1K -- Erases from the beginning of the line to the cursor, including the cursor position. + // [2K -- Erases the complete line. + + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + var start COORD + var end COORD + + switch param { + case 0: + start = info.CursorPosition + end = COORD{info.Size.X, info.CursorPosition.Y} + + case 1: + start = COORD{0, info.CursorPosition.Y} + end = info.CursorPosition + + case 2: + start = COORD{0, info.CursorPosition.Y} + end = COORD{info.Size.X, info.CursorPosition.Y} + } + + err = h.clearRange(h.attributes, start, end) + if err != nil { + return err + } + + return nil +} + +func (h *windowsAnsiEventHandler) IL(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("IL: [%v]", strconv.Itoa(param)) + h.clearWrap() + return h.insertLines(param) +} + +func (h *windowsAnsiEventHandler) DL(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DL: [%v]", strconv.Itoa(param)) + h.clearWrap() + return h.deleteLines(param) +} + +func (h *windowsAnsiEventHandler) ICH(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("ICH: [%v]", strconv.Itoa(param)) + h.clearWrap() + return h.insertCharacters(param) +} + +func (h *windowsAnsiEventHandler) DCH(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DCH: [%v]", strconv.Itoa(param)) + h.clearWrap() + return h.deleteCharacters(param) +} + +func (h *windowsAnsiEventHandler) SGR(params []int) error { + if err := h.Flush(); err != nil { + return err + } + strings := []string{} + for _, v := range params { + strings = append(strings, strconv.Itoa(v)) + } + + h.logf("SGR: [%v]", strings) + + if len(params) <= 0 { + h.attributes = h.infoReset.Attributes + h.inverted = false + } else { + for _, attr := range params { + + if attr == ansiterm.ANSI_SGR_RESET { + h.attributes = h.infoReset.Attributes + h.inverted = false + continue + } + + h.attributes, h.inverted = collectAnsiIntoWindowsAttributes(h.attributes, h.inverted, h.infoReset.Attributes, int16(attr)) + } + } + + attributes := h.attributes + if h.inverted { + attributes = invertAttributes(attributes) + } + err := SetConsoleTextAttribute(h.fd, attributes) + if err != nil { + return err + } + + return nil +} + +func (h *windowsAnsiEventHandler) SU(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("SU: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.scrollUp(param) +} + +func (h *windowsAnsiEventHandler) SD(param int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("SD: [%v]", []string{strconv.Itoa(param)}) + h.clearWrap() + return h.scrollDown(param) +} + +func (h *windowsAnsiEventHandler) DA(params []string) error { + h.logf("DA: [%v]", params) + // DA cannot be implemented because it must send data on the VT100 input stream, + // which is not available to go-ansiterm. + return nil +} + +func (h *windowsAnsiEventHandler) DECSTBM(top int, bottom int) error { + if err := h.Flush(); err != nil { + return err + } + h.logf("DECSTBM: [%d, %d]", top, bottom) + + // Windows is 0 indexed, Linux is 1 indexed + h.sr.top = int16(top - 1) + h.sr.bottom = int16(bottom - 1) + + // This command also moves the cursor to the origin. + h.clearWrap() + return h.CUP(1, 1) +} + +func (h *windowsAnsiEventHandler) RI() error { + if err := h.Flush(); err != nil { + return err + } + h.logf("RI: []") + h.clearWrap() + + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + sr := h.effectiveSr(info.Window) + if info.CursorPosition.Y == sr.top { + return h.scrollDown(1) + } + + return h.moveCursorVertical(-1) +} + +func (h *windowsAnsiEventHandler) IND() error { + h.logf("IND: []") + return h.executeLF() +} + +func (h *windowsAnsiEventHandler) Flush() error { + h.curInfo = nil + if h.buffer.Len() > 0 { + h.logf("Flush: [%s]", h.buffer.Bytes()) + if _, err := h.buffer.WriteTo(h.file); err != nil { + return err + } + } + + if h.wrapNext && !h.drewMarginByte { + h.logf("Flush: drawing margin byte '%c'", h.marginByte) + + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return err + } + + charInfo := []CHAR_INFO{{UnicodeChar: uint16(h.marginByte), Attributes: info.Attributes}} + size := COORD{1, 1} + position := COORD{0, 0} + region := SMALL_RECT{Left: info.CursorPosition.X, Top: info.CursorPosition.Y, Right: info.CursorPosition.X, Bottom: info.CursorPosition.Y} + if err := WriteConsoleOutput(h.fd, charInfo, size, position, ®ion); err != nil { + return err + } + h.drewMarginByte = true + } + return nil +} + +// cacheConsoleInfo ensures that the current console screen information has been queried +// since the last call to Flush(). It must be called before accessing h.curInfo or h.curPos. +func (h *windowsAnsiEventHandler) getCurrentInfo() (COORD, *CONSOLE_SCREEN_BUFFER_INFO, error) { + if h.curInfo == nil { + info, err := GetConsoleScreenBufferInfo(h.fd) + if err != nil { + return COORD{}, nil, err + } + h.curInfo = info + h.curPos = info.CursorPosition + } + return h.curPos, h.curInfo, nil +} + +func (h *windowsAnsiEventHandler) updatePos(pos COORD) { + if h.curInfo == nil { + panic("failed to call getCurrentInfo before calling updatePos") + } + h.curPos = pos +} + +// clearWrap clears the state where the cursor is in the margin +// waiting for the next character before wrapping the line. This must +// be done before most operations that act on the cursor. +func (h *windowsAnsiEventHandler) clearWrap() { + h.wrapNext = false + h.drewMarginByte = false +} diff --git a/vendor/github.com/MakeNowJust/heredoc/LICENSE b/vendor/github.com/MakeNowJust/heredoc/LICENSE new file mode 100644 index 0000000000..6d0eb9d5d6 --- /dev/null +++ b/vendor/github.com/MakeNowJust/heredoc/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2019 TSUYUSATO Kitsune + +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/MakeNowJust/heredoc/README.md b/vendor/github.com/MakeNowJust/heredoc/README.md new file mode 100644 index 0000000000..e9924d2974 --- /dev/null +++ b/vendor/github.com/MakeNowJust/heredoc/README.md @@ -0,0 +1,52 @@ +# heredoc + +[![Build Status](https://circleci.com/gh/MakeNowJust/heredoc.svg?style=svg)](https://circleci.com/gh/MakeNowJust/heredoc) [![GoDoc](https://godoc.org/github.com/MakeNowJusti/heredoc?status.svg)](https://godoc.org/github.com/MakeNowJust/heredoc) + +## About + +Package heredoc provides the here-document with keeping indent. + +## Install + +```console +$ go get github.com/MakeNowJust/heredoc +``` + +## Import + +```go +// usual +import "github.com/MakeNowJust/heredoc" +``` + +## Example + +```go +package main + +import ( + "fmt" + "github.com/MakeNowJust/heredoc" +) + +func main() { + fmt.Println(heredoc.Doc(` + Lorem ipsum dolor sit amet, consectetur adipisicing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. Ut enim ad minim veniam, ... + `)) + // Output: + // Lorem ipsum dolor sit amet, consectetur adipisicing elit, + // sed do eiusmod tempor incididunt ut labore et dolore magna + // aliqua. Ut enim ad minim veniam, ... + // +} +``` + +## API Document + + - [heredoc - GoDoc](https://godoc.org/github.com/MakeNowJust/heredoc) + +## License + +This software is released under the MIT License, see LICENSE. diff --git a/vendor/github.com/MakeNowJust/heredoc/heredoc.go b/vendor/github.com/MakeNowJust/heredoc/heredoc.go new file mode 100644 index 0000000000..1fc0469555 --- /dev/null +++ b/vendor/github.com/MakeNowJust/heredoc/heredoc.go @@ -0,0 +1,105 @@ +// Copyright (c) 2014-2019 TSUYUSATO Kitsune +// This software is released under the MIT License. +// http://opensource.org/licenses/mit-license.php + +// Package heredoc provides creation of here-documents from raw strings. +// +// Golang supports raw-string syntax. +// +// doc := ` +// Foo +// Bar +// ` +// +// But raw-string cannot recognize indentation. Thus such content is an indented string, equivalent to +// +// "\n\tFoo\n\tBar\n" +// +// I dont't want this! +// +// However this problem is solved by package heredoc. +// +// doc := heredoc.Doc(` +// Foo +// Bar +// `) +// +// Is equivalent to +// +// "Foo\nBar\n" +package heredoc + +import ( + "fmt" + "strings" + "unicode" +) + +const maxInt = int(^uint(0) >> 1) + +// Doc returns un-indented string as here-document. +func Doc(raw string) string { + skipFirstLine := false + if len(raw) > 0 && raw[0] == '\n' { + raw = raw[1:] + } else { + skipFirstLine = true + } + + lines := strings.Split(raw, "\n") + + minIndentSize := getMinIndent(lines, skipFirstLine) + lines = removeIndentation(lines, minIndentSize, skipFirstLine) + + return strings.Join(lines, "\n") +} + +// getMinIndent calculates the minimum indentation in lines, excluding empty lines. +func getMinIndent(lines []string, skipFirstLine bool) int { + minIndentSize := maxInt + + for i, line := range lines { + if i == 0 && skipFirstLine { + continue + } + + indentSize := 0 + for _, r := range []rune(line) { + if unicode.IsSpace(r) { + indentSize += 1 + } else { + break + } + } + + if len(line) == indentSize { + if i == len(lines)-1 && indentSize < minIndentSize { + lines[i] = "" + } + } else if indentSize < minIndentSize { + minIndentSize = indentSize + } + } + return minIndentSize +} + +// removeIndentation removes n characters from the front of each line in lines. +// Skips first line if skipFirstLine is true, skips empty lines. +func removeIndentation(lines []string, n int, skipFirstLine bool) []string { + for i, line := range lines { + if i == 0 && skipFirstLine { + continue + } + + if len(lines[i]) >= n { + lines[i] = line[n:] + } + } + return lines +} + +// Docf returns unindented and formatted string as here-document. +// Formatting is done as for fmt.Printf(). +func Docf(raw string, args ...interface{}) string { + return fmt.Sprintf(Doc(raw), args...) +} diff --git a/vendor/github.com/akrylysov/pogreb/.gitignore b/vendor/github.com/akrylysov/pogreb/.gitignore new file mode 100644 index 0000000000..9cc570c38b --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/.gitignore @@ -0,0 +1,2 @@ +/test.db +/fs/test diff --git a/vendor/github.com/akrylysov/pogreb/CHANGELOG.md b/vendor/github.com/akrylysov/pogreb/CHANGELOG.md new file mode 100644 index 0000000000..3ef9db66eb --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/CHANGELOG.md @@ -0,0 +1,59 @@ +# Changelog + +## [0.10.2] - 2023-12-10 +### Fixed +- Fix an edge case causing recovery to fail. + +## [0.10.1] - 2021-05-01 +### Changed +- Improve error reporting. +### Fixed +- Fix compilation for 32-bit OS. + +## [0.10.0] - 2021-02-09 +### Added +- Memory-mapped file access can now be disabled by setting `Options.FileSystem` to `fs.OS`. +### Changed +- The default file system implementation is changed to `fs.OSMMap`. + +## [0.9.2] - 2021-01-01 +### Changed +- Write-ahead log doesn't rely on wall-clock time anymore. It prevents potential race conditions during compaction and recovery. +### Fixed +- Fix recovery writing extra delete records. + +## [0.9.1] - 2020-04-03 +### Changed +- Improve Go 1.14 compatibility (remove "unsafe" usage). + +## [0.9.0] - 2020-03-08 +### Changed +- Replace the unstructured data file for storing key-value pairs with a write-ahead log. +### Added +- In the event of a crash or a power loss the database is automatically recovered. +- Optional background compaction allows reclaiming disk space occupied by overwritten or deleted keys. +### Fixed +- Fix disk space overhead when storing small keys and values. + +## [0.8.3] - 2019-11-03 +### Fixed +- Fix slice bounds out of range error mapping files on Windows. + +## [0.8.2] - 2019-09-04 +### Fixed +- Race condition could lead to data corruption. + +## [0.8.1] - 2019-06-30 +### Fixed +- Fix panic when accessing closed database. +- Return error opening invalid database. + +## [0.8] - 2019-03-30 +### Changed +- ~2x write performance improvement on non-Windows. + +## [0.7] - 2019-03-23 +### Added +- Windows support (@mattn). +### Changed +- Improve freelist performance. diff --git a/vendor/github.com/akrylysov/pogreb/LICENSE b/vendor/github.com/akrylysov/pogreb/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/akrylysov/pogreb/README.md b/vendor/github.com/akrylysov/pogreb/README.md new file mode 100644 index 0000000000..f4fbe58756 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/README.md @@ -0,0 +1,113 @@ +

+ +# Pogreb +[![Docs](https://godoc.org/github.com/akrylysov/pogreb?status.svg)](https://pkg.go.dev/github.com/akrylysov/pogreb) +[![Build Status](https://github.com/akrylysov/pogreb/actions/workflows/test.yaml/badge.svg?branch=master)](https://github.com/akrylysov/pogreb/actions) +[![Go Report Card](https://goreportcard.com/badge/github.com/akrylysov/pogreb)](https://goreportcard.com/report/github.com/akrylysov/pogreb) +[![Codecov](https://codecov.io/gh/akrylysov/pogreb/branch/master/graph/badge.svg)](https://codecov.io/gh/akrylysov/pogreb) + +Pogreb is an embedded key-value store for read-heavy workloads written in Go. + +## Key characteristics + +- 100% Go. +- Optimized for fast random lookups and infrequent bulk inserts. +- Can store larger-than-memory data sets. +- Low memory usage. +- All DB methods are safe for concurrent use by multiple goroutines. + +## Installation + +```sh +$ go get -u github.com/akrylysov/pogreb +``` + +## Usage + +### Opening a database + +To open or create a new database, use the `pogreb.Open()` function: + +```go +package main + +import ( + "log" + + "github.com/akrylysov/pogreb" +) + +func main() { + db, err := pogreb.Open("pogreb.test", nil) + if err != nil { + log.Fatal(err) + return + } + defer db.Close() +} +``` + +### Writing to a database + +Use the `DB.Put()` function to insert a new key-value pair: + +```go +err := db.Put([]byte("testKey"), []byte("testValue")) +if err != nil { + log.Fatal(err) +} +``` + +### Reading from a database + +To retrieve the inserted value, use the `DB.Get()` function: + +```go +val, err := db.Get([]byte("testKey")) +if err != nil { + log.Fatal(err) +} +log.Printf("%s", val) +``` + +### Deleting from a database + +Use the `DB.Delete()` function to delete a key-value pair: + +```go +err := db.Delete([]byte("testKey")) +if err != nil { + log.Fatal(err) +} +``` + +### Iterating over items + +To iterate over items, use `ItemIterator` returned by `DB.Items()`: + +```go +it := db.Items() +for { + key, val, err := it.Next() + if err == pogreb.ErrIterationDone { + break + } + if err != nil { + log.Fatal(err) + } + log.Printf("%s %s", key, val) +} +``` + +## Performance + +The benchmarking code can be found in the [pogreb-bench](https://github.com/akrylysov/pogreb-bench) repository. + +Results of read performance benchmark of pogreb, goleveldb, bolt and badgerdb +on DigitalOcean 8 CPUs / 16 GB RAM / 160 GB SSD + Ubuntu 16.04.3 (higher is better): + +

+ +## Internals + +[Design document](/docs/design.md). diff --git a/vendor/github.com/akrylysov/pogreb/appveyor.yml b/vendor/github.com/akrylysov/pogreb/appveyor.yml new file mode 100644 index 0000000000..0c9e1be20b --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/appveyor.yml @@ -0,0 +1,15 @@ +version: "{build}" + +clone_folder: c:\gopath\src\github.com\akrylysov/pogreb + +environment: + GOPATH: c:\gopath + +install: + - echo %PATH% + - echo %GOPATH% + - go version + - go env + +build_script: + - go test -v ./... diff --git a/vendor/github.com/akrylysov/pogreb/bucket.go b/vendor/github.com/akrylysov/pogreb/bucket.go new file mode 100644 index 0000000000..cb237a5d80 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/bucket.go @@ -0,0 +1,126 @@ +package pogreb + +import ( + "encoding/binary" +) + +const ( + bucketSize = 512 + slotsPerBucket = 31 // Maximum number of slots possible to fit in a 512-byte bucket. +) + +// slot corresponds to a single item in the hash table. +type slot struct { + hash uint32 + segmentID uint16 + keySize uint16 + valueSize uint32 + offset uint32 // Offset of the record in a segment. +} + +func (sl slot) kvSize() uint32 { + return uint32(sl.keySize) + sl.valueSize +} + +// bucket is an array of slots. +type bucket struct { + slots [slotsPerBucket]slot + next int64 // Offset of overflow bucket. +} + +// bucketHandle is a bucket, plus its offset and the file it's written to. +type bucketHandle struct { + bucket + file *file + offset int64 +} + +func (b bucket) MarshalBinary() ([]byte, error) { + buf := make([]byte, bucketSize) + data := buf + for i := 0; i < slotsPerBucket; i++ { + sl := b.slots[i] + binary.LittleEndian.PutUint32(buf[:4], sl.hash) + binary.LittleEndian.PutUint16(buf[4:6], sl.segmentID) + binary.LittleEndian.PutUint16(buf[6:8], sl.keySize) + binary.LittleEndian.PutUint32(buf[8:12], sl.valueSize) + binary.LittleEndian.PutUint32(buf[12:16], sl.offset) + buf = buf[16:] + } + binary.LittleEndian.PutUint64(buf[:8], uint64(b.next)) + return data, nil +} + +func (b *bucket) UnmarshalBinary(data []byte) error { + for i := 0; i < slotsPerBucket; i++ { + _ = data[16] // bounds check hint to compiler; see golang.org/issue/14808 + b.slots[i].hash = binary.LittleEndian.Uint32(data[:4]) + b.slots[i].segmentID = binary.LittleEndian.Uint16(data[4:6]) + b.slots[i].keySize = binary.LittleEndian.Uint16(data[6:8]) + b.slots[i].valueSize = binary.LittleEndian.Uint32(data[8:12]) + b.slots[i].offset = binary.LittleEndian.Uint32(data[12:16]) + data = data[16:] + } + b.next = int64(binary.LittleEndian.Uint64(data[:8])) + return nil +} + +func (b *bucket) del(slotIdx int) { + i := slotIdx + // Shift slots. + for ; i < slotsPerBucket-1; i++ { + b.slots[i] = b.slots[i+1] + } + b.slots[i] = slot{} +} + +func (b *bucketHandle) read() error { + buf, err := b.file.Slice(b.offset, b.offset+int64(bucketSize)) + if err != nil { + return err + } + return b.UnmarshalBinary(buf) +} + +func (b *bucketHandle) write() error { + buf, err := b.MarshalBinary() + if err != nil { + return err + } + _, err = b.file.WriteAt(buf, b.offset) + return err +} + +// slotWriter inserts and writes slots into a bucket. +type slotWriter struct { + bucket *bucketHandle + slotIdx int + prevBuckets []*bucketHandle +} + +func (sw *slotWriter) insert(sl slot, idx *index) error { + if sw.slotIdx == slotsPerBucket { + // Bucket is full, create a new overflow bucket. + nextBucket, err := idx.createOverflowBucket() + if err != nil { + return err + } + sw.bucket.next = nextBucket.offset + sw.prevBuckets = append(sw.prevBuckets, sw.bucket) + sw.bucket = nextBucket + sw.slotIdx = 0 + } + sw.bucket.slots[sw.slotIdx] = sl + sw.slotIdx++ + return nil +} + +func (sw *slotWriter) write() error { + // Write previous buckets first. + for i := len(sw.prevBuckets) - 1; i >= 0; i-- { + if err := sw.prevBuckets[i].write(); err != nil { + return err + } + } + return sw.bucket.write() +} diff --git a/vendor/github.com/akrylysov/pogreb/compaction.go b/vendor/github.com/akrylysov/pogreb/compaction.go new file mode 100644 index 0000000000..5823ef33d5 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/compaction.go @@ -0,0 +1,160 @@ +package pogreb + +import ( + "sync/atomic" + + "github.com/akrylysov/pogreb/internal/errors" +) + +// promoteRecord writes the record to the current segment if the index still points to the record. +// Otherwise it discards the record. +func (db *DB) promoteRecord(rec record) (bool, error) { + hash := db.hash(rec.key) + it := db.index.newBucketIterator(db.index.bucketIndex(hash)) + for { + b, err := it.next() + if err == ErrIterationDone { + // Exhausted all buckets and the slot wasn't found. + // The key was deleted or overwritten. The record is safe to discard. + return true, nil + } + if err != nil { + return false, err + } + for i := 0; i < slotsPerBucket; i++ { + sl := b.slots[i] + + // No more slots in the bucket. + if sl.offset == 0 { + break + } + + // Slot points to a different record. + if hash != sl.hash || rec.offset != sl.offset || rec.segmentID != sl.segmentID { + continue + } + + // The record is in the index, write it to the current segment. + segmentID, offset, err := db.datalog.writeRecord(rec.data, rec.rtype) // TODO: batch writes + if err != nil { + return false, err + } + + // Update index. + b.slots[i].segmentID = segmentID + b.slots[i].offset = offset + return false, b.write() + } + } +} + +// CompactionResult holds the compaction result. +type CompactionResult struct { + CompactedSegments int + ReclaimedRecords int + ReclaimedBytes int +} + +func (db *DB) compact(sourceSeg *segment) (CompactionResult, error) { + cr := CompactionResult{} + + db.mu.Lock() + sourceSeg.meta.Full = true // Prevent writes to the compacted file. + db.mu.Unlock() + + it, err := newSegmentIterator(sourceSeg) + if err != nil { + return cr, err + } + // Copy records from sourceSeg to the current segment. + for { + err := func() error { + db.mu.Lock() + defer db.mu.Unlock() + rec, err := it.next() + if err != nil { + return err + } + if rec.rtype == recordTypeDelete { + cr.ReclaimedRecords++ + cr.ReclaimedBytes += len(rec.data) + return nil + } + reclaimed, err := db.promoteRecord(rec) + if reclaimed { + cr.ReclaimedRecords++ + cr.ReclaimedBytes += len(rec.data) + } + return err + }() + if err == ErrIterationDone { + break + } + if err != nil { + return cr, err + } + } + + db.mu.Lock() + defer db.mu.Unlock() + err = db.datalog.removeSegment(sourceSeg) + return cr, err +} + +// pickForCompaction returns segments eligible for compaction. +func (db *DB) pickForCompaction() []*segment { + segments := db.datalog.segmentsBySequenceID() + var picked []*segment + for i := len(segments) - 1; i >= 0; i-- { + seg := segments[i] + + if uint32(seg.size) < db.opts.compactionMinSegmentSize { + continue + } + + fragmentation := float32(seg.meta.DeletedBytes) / float32(seg.size) + if fragmentation < db.opts.compactionMinFragmentation { + continue + } + + if seg.meta.DeleteRecords > 0 { + // Delete records can be discarded only when older segments contain no put records + // for the corresponding keys. + // All segments older than the segment eligible for compaction have to be compacted. + return append(segments[:i+1], picked...) + } + + picked = append([]*segment{seg}, picked...) + } + return picked +} + +// Compact compacts the DB. Deleted and overwritten items are discarded. +// Returns an error if compaction is already in progress. +func (db *DB) Compact() (CompactionResult, error) { + cr := CompactionResult{} + + // Run only a single compaction at a time. + if !atomic.CompareAndSwapInt32(&db.compactionRunning, 0, 1) { + return cr, errBusy + } + defer func() { + atomic.StoreInt32(&db.compactionRunning, 0) + }() + + db.mu.RLock() + segments := db.pickForCompaction() + db.mu.RUnlock() + + for _, seg := range segments { + segcr, err := db.compact(seg) + if err != nil { + return cr, errors.Wrapf(err, "compacting segment %s", seg.name) + } + cr.CompactedSegments++ + cr.ReclaimedRecords += segcr.ReclaimedRecords + cr.ReclaimedBytes += segcr.ReclaimedBytes + } + + return cr, nil +} diff --git a/vendor/github.com/akrylysov/pogreb/datalog.go b/vendor/github.com/akrylysov/pogreb/datalog.go new file mode 100644 index 0000000000..5fd53aeace --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/datalog.go @@ -0,0 +1,261 @@ +package pogreb + +import ( + "fmt" + "math" + "os" + "path/filepath" + "sort" + "strconv" + "strings" + + "github.com/akrylysov/pogreb/internal/errors" +) + +const ( + maxSegments = math.MaxInt16 +) + +// datalog is a write-ahead log. +type datalog struct { + opts *Options + curSeg *segment + segments [maxSegments]*segment + maxSequenceID uint64 +} + +func openDatalog(opts *Options) (*datalog, error) { + files, err := opts.FileSystem.ReadDir(".") + if err != nil { + return nil, err + } + + dl := &datalog{ + opts: opts, + } + + // Open existing segments. + for _, file := range files { + name := file.Name() + ext := filepath.Ext(name) + if ext != segmentExt { + continue + } + id, seqID, err := parseSegmentName(name) + if err != nil { + return nil, err + } + seg, err := dl.openSegment(name, id, seqID) + if err != nil { + return nil, errors.Wrapf(err, "opening segment %s", name) + } + if seg.sequenceID > dl.maxSequenceID { + dl.maxSequenceID = seg.sequenceID + } + dl.segments[seg.id] = seg + } + + if err := dl.swapSegment(); err != nil { + return nil, err + } + + return dl, nil +} + +func parseSegmentName(name string) (uint16, uint64, error) { + parts := strings.SplitN(strings.TrimSuffix(name, segmentExt), "-", 2) + id, err := strconv.ParseUint(parts[0], 10, 16) + if err != nil { + return 0, 0, err + } + var seqID uint64 + if len(parts) == 2 { + seqID, err = strconv.ParseUint(parts[1], 10, 64) + if err != nil { + return 0, 0, err + } + } + return uint16(id), seqID, nil +} + +func (dl *datalog) openSegment(name string, id uint16, seqID uint64) (*segment, error) { + f, err := openFile(dl.opts.FileSystem, name, openFileFlags{}) + if err != nil { + return nil, err + } + + meta := &segmentMeta{} + if !f.empty() { + metaName := name + metaExt + if err := readGobFile(dl.opts.FileSystem, metaName, &meta); err != nil { + logger.Printf("error reading segment meta %d: %v", id, err) + // TODO: rebuild meta? + } + } + + seg := &segment{ + file: f, + id: id, + sequenceID: seqID, + name: name, + meta: meta, + } + + return seg, nil +} + +func (dl *datalog) nextWritableSegmentID() (uint16, uint64, error) { + for id, seg := range dl.segments { + // Pick empty segment. + if seg == nil { + dl.maxSequenceID++ + return uint16(id), dl.maxSequenceID, nil + } + } + return 0, 0, fmt.Errorf("number of segments exceeds %d", maxSegments) +} + +func (dl *datalog) swapSegment() error { + // Pick unfilled segment. + for _, seg := range dl.segments { + if seg != nil && !seg.meta.Full { + dl.curSeg = seg + return nil + } + } + + // Create new segment. + id, seqID, err := dl.nextWritableSegmentID() + if err != nil { + return err + } + + name := segmentName(id, seqID) + seg, err := dl.openSegment(name, id, seqID) + if err != nil { + return err + } + + dl.segments[id] = seg + dl.curSeg = seg + + return nil +} + +func (dl *datalog) removeSegment(seg *segment) error { + dl.segments[seg.id] = nil + + if err := seg.Close(); err != nil { + return err + } + + // Remove segment meta from FS. + metaName := seg.name + segmentExt + if err := dl.opts.FileSystem.Remove(metaName); err != nil && !os.IsNotExist(err) { + return err + } + + // Remove segment from FS. + if err := dl.opts.FileSystem.Remove(seg.name); err != nil { + return err + } + + return nil +} + +func (dl *datalog) readKeyValue(sl slot) ([]byte, []byte, error) { + off := int64(sl.offset) + 6 // Skip key size and value size. + seg := dl.segments[sl.segmentID] + keyValue, err := seg.Slice(off, off+int64(sl.kvSize())) + if err != nil { + return nil, nil, err + } + return keyValue[:sl.keySize], keyValue[sl.keySize:], nil +} + +func (dl *datalog) readKey(sl slot) ([]byte, error) { + off := int64(sl.offset) + 6 + seg := dl.segments[sl.segmentID] + return seg.Slice(off, off+int64(sl.keySize)) +} + +// trackDel updates segment's metadata for deleted or overwritten items. +func (dl *datalog) trackDel(sl slot) { + meta := dl.segments[sl.segmentID].meta + meta.DeletedKeys++ + meta.DeletedBytes += encodedRecordSize(sl.kvSize()) +} + +func (dl *datalog) del(key []byte) error { + rec := encodeDeleteRecord(key) + _, _, err := dl.writeRecord(rec, recordTypeDelete) + if err != nil { + return err + } + // Compaction removes delete records, increment DeletedBytes. + dl.curSeg.meta.DeletedBytes += uint32(len(rec)) + return nil +} + +func (dl *datalog) writeRecord(data []byte, rt recordType) (uint16, uint32, error) { + if dl.curSeg.meta.Full || dl.curSeg.size+int64(len(data)) > int64(dl.opts.maxSegmentSize) { + // Current segment is full, create a new one. + dl.curSeg.meta.Full = true + if err := dl.swapSegment(); err != nil { + return 0, 0, err + } + } + off, err := dl.curSeg.append(data) + if err != nil { + return 0, 0, err + } + switch rt { + case recordTypePut: + dl.curSeg.meta.PutRecords++ + case recordTypeDelete: + dl.curSeg.meta.DeleteRecords++ + } + return dl.curSeg.id, uint32(off), nil +} + +func (dl *datalog) put(key []byte, value []byte) (uint16, uint32, error) { + return dl.writeRecord(encodePutRecord(key, value), recordTypePut) +} + +func (dl *datalog) sync() error { + return dl.curSeg.Sync() +} + +func (dl *datalog) close() error { + for _, seg := range dl.segments { + if seg == nil { + continue + } + if err := seg.Close(); err != nil { + return err + } + metaName := seg.name + metaExt + if err := writeGobFile(dl.opts.FileSystem, metaName, seg.meta); err != nil { + return err + } + } + return nil +} + +// segmentsBySequenceID returns segments ordered from oldest to newest. +func (dl *datalog) segmentsBySequenceID() []*segment { + var segments []*segment + + for _, seg := range dl.segments { + if seg == nil { + continue + } + segments = append(segments, seg) + } + + sort.SliceStable(segments, func(i, j int) bool { + return segments[i].sequenceID < segments[j].sequenceID + }) + + return segments +} diff --git a/vendor/github.com/akrylysov/pogreb/db.go b/vendor/github.com/akrylysov/pogreb/db.go new file mode 100644 index 0000000000..e2c908e514 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/db.go @@ -0,0 +1,397 @@ +package pogreb + +import ( + "bytes" + "context" + "math" + "os" + "sync" + "time" + + "github.com/akrylysov/pogreb/fs" + "github.com/akrylysov/pogreb/internal/errors" + "github.com/akrylysov/pogreb/internal/hash" +) + +const ( + // MaxKeyLength is the maximum size of a key in bytes. + MaxKeyLength = math.MaxUint16 + + // MaxValueLength is the maximum size of a value in bytes. + MaxValueLength = 512 << 20 // 512 MiB + + // MaxKeys is the maximum numbers of keys in the DB. + MaxKeys = math.MaxUint32 + + metaExt = ".pmt" + dbMetaName = "db" + metaExt +) + +// DB represents the key-value storage. +// All DB methods are safe for concurrent use by multiple goroutines. +type DB struct { + mu sync.RWMutex // Allows multiple database readers or a single writer. + opts *Options + index *index + datalog *datalog + lock fs.LockFile // Prevents opening multiple instances of the same database. + hashSeed uint32 + metrics *Metrics + syncWrites bool + cancelBgWorker context.CancelFunc + closeWg sync.WaitGroup + compactionRunning int32 // Prevents running compactions concurrently. +} + +type dbMeta struct { + HashSeed uint32 +} + +// Open opens or creates a new DB. +// The DB must be closed after use, by calling Close method. +func Open(path string, opts *Options) (*DB, error) { + opts = opts.copyWithDefaults(path) + + if err := os.MkdirAll(path, 0755); err != nil { + return nil, err + } + + // Try to acquire a file lock. + lock, acquiredExistingLock, err := createLockFile(opts) + if err != nil { + if err == os.ErrExist { + err = errLocked + } + return nil, errors.Wrap(err, "creating lock file") + } + + if acquiredExistingLock { + // Lock file already existed, but the process managed to acquire it. + // It means the database wasn't closed properly. + // Start recovery process. + if err := backupNonsegmentFiles(opts.FileSystem); err != nil { + return nil, err + } + } + + index, err := openIndex(opts) + if err != nil { + return nil, errors.Wrap(err, "opening index") + } + + datalog, err := openDatalog(opts) + if err != nil { + return nil, errors.Wrap(err, "opening datalog") + } + + db := &DB{ + opts: opts, + index: index, + datalog: datalog, + lock: lock, + metrics: &Metrics{}, + syncWrites: opts.BackgroundSyncInterval == -1, + } + if index.count() == 0 { + // The index is empty, make a new hash seed. + seed, err := hash.RandSeed() + if err != nil { + return nil, err + } + db.hashSeed = seed + } else { + if err := db.readMeta(); err != nil { + return nil, errors.Wrap(err, "reading db meta") + } + } + + if acquiredExistingLock { + if err := db.recover(); err != nil { + return nil, errors.Wrap(err, "recovering") + } + } + + if db.opts.BackgroundSyncInterval > 0 || db.opts.BackgroundCompactionInterval > 0 { + db.startBackgroundWorker() + } + + return db, nil +} + +func cloneBytes(src []byte) []byte { + dst := make([]byte, len(src)) + copy(dst, src) + return dst +} + +func (db *DB) writeMeta() error { + m := dbMeta{ + HashSeed: db.hashSeed, + } + return writeGobFile(db.opts.FileSystem, dbMetaName, m) +} + +func (db *DB) readMeta() error { + m := dbMeta{} + if err := readGobFile(db.opts.FileSystem, dbMetaName, &m); err != nil { + return err + } + db.hashSeed = m.HashSeed + return nil +} + +func (db *DB) hash(data []byte) uint32 { + return hash.Sum32WithSeed(data, db.hashSeed) +} + +// newNullableTicker is a wrapper around time.NewTicker that allows creating a nil ticker. +// A nil ticker never ticks. +func newNullableTicker(d time.Duration) (<-chan time.Time, func()) { + if d > 0 { + t := time.NewTicker(d) + return t.C, t.Stop + } + return nil, func() {} +} + +func (db *DB) startBackgroundWorker() { + ctx, cancel := context.WithCancel(context.Background()) + db.cancelBgWorker = cancel + db.closeWg.Add(1) + + go func() { + defer db.closeWg.Done() + + syncC, syncStop := newNullableTicker(db.opts.BackgroundSyncInterval) + defer syncStop() + + compactC, compactStop := newNullableTicker(db.opts.BackgroundCompactionInterval) + defer compactStop() + + for { + select { + case <-ctx.Done(): + return + case <-syncC: + if err := db.Sync(); err != nil { + logger.Printf("error synchronizing database: %v", err) + } + case <-compactC: + if cr, err := db.Compact(); err != nil { + logger.Printf("error compacting database: %v", err) + } else if cr.CompactedSegments > 0 { + logger.Printf("compacted database: %+v", cr) + } + } + } + }() +} + +// Get returns the value for the given key stored in the DB or nil if the key doesn't exist. +func (db *DB) Get(key []byte) ([]byte, error) { + h := db.hash(key) + db.metrics.Gets.Add(1) + db.mu.RLock() + defer db.mu.RUnlock() + var retValue []byte + err := db.index.get(h, func(sl slot) (bool, error) { + if uint16(len(key)) != sl.keySize { + return false, nil + } + slKey, value, err := db.datalog.readKeyValue(sl) + if err != nil { + return true, err + } + if bytes.Equal(key, slKey) { + retValue = cloneBytes(value) + return true, nil + } + db.metrics.HashCollisions.Add(1) + return false, nil + }) + if err != nil { + return nil, err + } + return retValue, nil +} + +// Has returns true if the DB contains the given key. +func (db *DB) Has(key []byte) (bool, error) { + h := db.hash(key) + db.metrics.Gets.Add(1) + found := false + db.mu.RLock() + defer db.mu.RUnlock() + err := db.index.get(h, func(sl slot) (bool, error) { + if uint16(len(key)) != sl.keySize { + return false, nil + } + slKey, err := db.datalog.readKey(sl) + if err != nil { + return true, err + } + if bytes.Equal(key, slKey) { + found = true + return true, nil + } + return false, nil + }) + if err != nil { + return false, err + } + return found, nil +} + +func (db *DB) put(sl slot, key []byte) error { + return db.index.put(sl, func(cursl slot) (bool, error) { + if uint16(len(key)) != cursl.keySize { + return false, nil + } + slKey, err := db.datalog.readKey(cursl) + if err != nil { + return true, err + } + if bytes.Equal(key, slKey) { + db.datalog.trackDel(cursl) // Overwriting existing key. + return true, nil + } + return false, nil + }) +} + +// Put sets the value for the given key. It updates the value for the existing key. +func (db *DB) Put(key []byte, value []byte) error { + if len(key) > MaxKeyLength { + return errKeyTooLarge + } + if len(value) > MaxValueLength { + return errValueTooLarge + } + h := db.hash(key) + db.metrics.Puts.Add(1) + db.mu.Lock() + defer db.mu.Unlock() + + segID, offset, err := db.datalog.put(key, value) + if err != nil { + return err + } + + sl := slot{ + hash: h, + segmentID: segID, + keySize: uint16(len(key)), + valueSize: uint32(len(value)), + offset: offset, + } + + if err := db.put(sl, key); err != nil { + return err + } + + if db.syncWrites { + return db.sync() + } + return nil +} + +func (db *DB) del(h uint32, key []byte, writeWAL bool) error { + err := db.index.delete(h, func(sl slot) (b bool, e error) { + if uint16(len(key)) != sl.keySize { + return false, nil + } + slKey, err := db.datalog.readKey(sl) + if err != nil { + return true, err + } + if bytes.Equal(key, slKey) { + db.datalog.trackDel(sl) + var err error + if writeWAL { + err = db.datalog.del(key) + } + return true, err + } + return false, nil + }) + return err +} + +// Delete deletes the given key from the DB. +func (db *DB) Delete(key []byte) error { + h := db.hash(key) + db.metrics.Dels.Add(1) + db.mu.Lock() + defer db.mu.Unlock() + if err := db.del(h, key, true); err != nil { + return err + } + if db.syncWrites { + return db.sync() + } + return nil +} + +// Close closes the DB. +func (db *DB) Close() error { + if db.cancelBgWorker != nil { + db.cancelBgWorker() + } + db.closeWg.Wait() + db.mu.Lock() + defer db.mu.Unlock() + if err := db.writeMeta(); err != nil { + return err + } + if err := db.datalog.close(); err != nil { + return err + } + if err := db.index.close(); err != nil { + return err + } + if err := db.lock.Unlock(); err != nil { + return err + } + return nil +} + +func (db *DB) sync() error { + return db.datalog.sync() +} + +// Items returns a new ItemIterator. +func (db *DB) Items() *ItemIterator { + return &ItemIterator{db: db} +} + +// Sync commits the contents of the database to the backing FileSystem. +func (db *DB) Sync() error { + db.mu.Lock() + defer db.mu.Unlock() + return db.sync() +} + +// Count returns the number of keys in the DB. +func (db *DB) Count() uint32 { + db.mu.RLock() + defer db.mu.RUnlock() + return db.index.count() +} + +// Metrics returns the DB metrics. +func (db *DB) Metrics() *Metrics { + return db.metrics +} + +// FileSize returns the total size of the disk storage used by the DB. +func (db *DB) FileSize() (int64, error) { + var size int64 + files, err := db.opts.FileSystem.ReadDir(".") + if err != nil { + return 0, err + } + for _, file := range files { + size += file.Size() + } + return size, nil +} diff --git a/vendor/github.com/akrylysov/pogreb/doc.go b/vendor/github.com/akrylysov/pogreb/doc.go new file mode 100644 index 0000000000..6a5d7442bf --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/doc.go @@ -0,0 +1,4 @@ +/* +Package pogreb implements an embedded key-value store for read-heavy workloads. +*/ +package pogreb diff --git a/vendor/github.com/akrylysov/pogreb/errors.go b/vendor/github.com/akrylysov/pogreb/errors.go new file mode 100644 index 0000000000..936ccbdce2 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/errors.go @@ -0,0 +1,14 @@ +package pogreb + +import ( + "github.com/akrylysov/pogreb/internal/errors" +) + +var ( + errKeyTooLarge = errors.New("key is too large") + errValueTooLarge = errors.New("value is too large") + errFull = errors.New("database is full") + errCorrupted = errors.New("database is corrupted") + errLocked = errors.New("database is locked") + errBusy = errors.New("database is busy") +) diff --git a/vendor/github.com/akrylysov/pogreb/file.go b/vendor/github.com/akrylysov/pogreb/file.go new file mode 100644 index 0000000000..324bcdb1eb --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/file.go @@ -0,0 +1,107 @@ +package pogreb + +import ( + "io" + "os" + + "github.com/akrylysov/pogreb/fs" +) + +// file is a database file. +// When stored in a file system, the file starts with a header. +type file struct { + fs.File + size int64 +} + +type openFileFlags struct { + truncate bool + readOnly bool +} + +func openFile(fsyst fs.FileSystem, name string, flags openFileFlags) (*file, error) { + var flag int + if flags.readOnly { + flag = os.O_RDONLY + } else { + flag = os.O_CREATE | os.O_RDWR + if flags.truncate { + flag |= os.O_TRUNC + } + } + fi, err := fsyst.OpenFile(name, flag, os.FileMode(0640)) + f := &file{} + if err != nil { + return f, err + } + clean := fi.Close + defer func() { + if clean != nil { + _ = clean() + } + }() + f.File = fi + stat, err := fi.Stat() + if err != nil { + return f, err + } + f.size = stat.Size() + if f.size == 0 { + // It's a new file - write header. + if err := f.writeHeader(); err != nil { + return nil, err + } + } else { + if err := f.readHeader(); err != nil { + return nil, err + } + } + if _, err := f.Seek(int64(headerSize), io.SeekStart); err != nil { + return nil, err + } + clean = nil + return f, nil +} + +func (f *file) writeHeader() error { + h := newHeader() + data, err := h.MarshalBinary() + if err != nil { + return err + } + if _, err = f.append(data); err != nil { + return err + } + return nil +} + +func (f *file) readHeader() error { + h := &header{} + buf := make([]byte, headerSize) + if _, err := io.ReadFull(f, buf); err != nil { + return err + } + return h.UnmarshalBinary(buf) +} + +func (f *file) empty() bool { + return f.size == int64(headerSize) +} + +func (f *file) extend(size uint32) (int64, error) { + off := f.size + if err := f.Truncate(off + int64(size)); err != nil { + return 0, err + } + f.size += int64(size) + return off, nil +} + +func (f *file) append(data []byte) (int64, error) { + off := f.size + if _, err := f.WriteAt(data, off); err != nil { + return 0, err + } + f.size += int64(len(data)) + return off, nil +} diff --git a/vendor/github.com/akrylysov/pogreb/fs/fs.go b/vendor/github.com/akrylysov/pogreb/fs/fs.go new file mode 100644 index 0000000000..ebde0e96f8 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/fs/fs.go @@ -0,0 +1,63 @@ +/* +Package fs provides a file system interface. +*/ +package fs + +import ( + "errors" + "io" + "os" +) + +var ( + errAppendModeNotSupported = errors.New("append mode is not supported") +) + +// File is the interface compatible with os.File. +type File interface { + io.Closer + io.Reader + io.ReaderAt + io.Seeker + io.Writer + io.WriterAt + + // Stat returns os.FileInfo describing the file. + Stat() (os.FileInfo, error) + + // Sync commits the current contents of the file. + Sync() error + + // Truncate changes the size of the file. + Truncate(size int64) error + + // Slice reads and returns the contents of file from offset start to offset end. + Slice(start int64, end int64) ([]byte, error) +} + +// LockFile represents a lock file. +type LockFile interface { + // Unlock and removes the lock file. + Unlock() error +} + +// FileSystem represents a file system. +type FileSystem interface { + // OpenFile opens the file with specified flag. + OpenFile(name string, flag int, perm os.FileMode) (File, error) + + // Stat returns os.FileInfo describing the file. + Stat(name string) (os.FileInfo, error) + + // Remove removes the file. + Remove(name string) error + + // Rename renames oldpath to newpath. + Rename(oldpath, newpath string) error + + // ReadDir reads the directory and returns a list of directory entries. + ReadDir(name string) ([]os.FileInfo, error) + + // CreateLockFile creates a lock file. + CreateLockFile(name string, perm os.FileMode) (LockFile, bool, error) +} diff --git a/vendor/github.com/akrylysov/pogreb/fs/mem.go b/vendor/github.com/akrylysov/pogreb/fs/mem.go new file mode 100644 index 0000000000..d1c3fd84e3 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/fs/mem.go @@ -0,0 +1,234 @@ +package fs + +import ( + "io" + "os" + "path/filepath" + "time" +) + +type memFS struct { + files map[string]*memFile +} + +// Mem is a file system backed by memory. +var Mem FileSystem = &memFS{files: map[string]*memFile{}} + +func (fs *memFS) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + if flag&os.O_APPEND != 0 { + // memFS doesn't support opening files in append-only mode. + // The database doesn't currently use O_APPEND. + return nil, errAppendModeNotSupported + } + f := fs.files[name] + if f == nil || (flag&os.O_TRUNC) != 0 { + f = &memFile{ + name: name, + perm: perm, // Perm is saved to return it in Mode, but don't do anything else with it yet. + } + fs.files[name] = f + } else if !f.closed { + return nil, os.ErrExist + } else { + f.offset = 0 + f.closed = false + } + return f, nil +} + +func (fs *memFS) CreateLockFile(name string, perm os.FileMode) (LockFile, bool, error) { + _, exists := fs.files[name] + _, err := fs.OpenFile(name, 0, perm) + if err != nil { + return nil, false, err + } + return fs.files[name], exists, nil +} + +func (fs *memFS) Stat(name string) (os.FileInfo, error) { + if f, ok := fs.files[name]; ok { + return f, nil + } + return nil, os.ErrNotExist +} + +func (fs *memFS) Remove(name string) error { + if _, ok := fs.files[name]; ok { + delete(fs.files, name) + return nil + } + return os.ErrNotExist +} + +func (fs *memFS) Rename(oldpath, newpath string) error { + if f, ok := fs.files[oldpath]; ok { + delete(fs.files, oldpath) + fs.files[newpath] = f + f.name = newpath + return nil + } + return os.ErrNotExist +} + +func (fs *memFS) ReadDir(dir string) ([]os.FileInfo, error) { + dir = filepath.Clean(dir) + var fis []os.FileInfo + for name, f := range fs.files { + if filepath.Dir(name) == dir { + fis = append(fis, f) + } + } + return fis, nil +} + +type memFile struct { + name string + perm os.FileMode + buf []byte + size int64 + offset int64 + closed bool +} + +func (f *memFile) Close() error { + if f.closed { + return os.ErrClosed + } + f.closed = true + return nil +} + +func (f *memFile) Unlock() error { + if err := f.Close(); err != nil { + return err + } + return Mem.Remove(f.name) +} + +func (f *memFile) ReadAt(p []byte, off int64) (int, error) { + if f.closed { + return 0, os.ErrClosed + } + if off >= f.size { + return 0, io.EOF + } + n := int64(len(p)) + if n > f.size-off { + copy(p, f.buf[off:]) + return int(f.size - off), nil + } + copy(p, f.buf[off:off+n]) + return int(n), nil +} + +func (f *memFile) Read(p []byte) (int, error) { + n, err := f.ReadAt(p, f.offset) + if err != nil { + return n, err + } + f.offset += int64(n) + return n, err +} + +func (f *memFile) WriteAt(p []byte, off int64) (int, error) { + if f.closed { + return 0, os.ErrClosed + } + n := int64(len(p)) + if off+n > f.size { + f.truncate(off + n) + } + copy(f.buf[off:off+n], p) + return int(n), nil +} + +func (f *memFile) Write(p []byte) (int, error) { + n, err := f.WriteAt(p, f.offset) + if err != nil { + return n, err + } + f.offset += int64(n) + return n, err +} + +func (f *memFile) Seek(offset int64, whence int) (int64, error) { + if f.closed { + return 0, os.ErrClosed + } + switch whence { + case io.SeekEnd: + f.offset = f.size + offset + case io.SeekStart: + f.offset = offset + case io.SeekCurrent: + f.offset += offset + } + return f.offset, nil +} + +func (f *memFile) Stat() (os.FileInfo, error) { + if f.closed { + return f, os.ErrClosed + } + return f, nil +} + +func (f *memFile) Sync() error { + if f.closed { + return os.ErrClosed + } + return nil +} + +func (f *memFile) truncate(size int64) { + if size > f.size { + diff := int(size - f.size) + f.buf = append(f.buf, make([]byte, diff)...) + } else { + f.buf = f.buf[:size] + } + f.size = size +} + +func (f *memFile) Truncate(size int64) error { + if f.closed { + return os.ErrClosed + } + f.truncate(size) + return nil +} + +func (f *memFile) Name() string { + _, name := filepath.Split(f.name) + return name +} + +func (f *memFile) Size() int64 { + return f.size +} + +func (f *memFile) Mode() os.FileMode { + return f.perm +} + +func (f *memFile) ModTime() time.Time { + return time.Now() +} + +func (f *memFile) IsDir() bool { + return false +} + +func (f *memFile) Sys() interface{} { + return nil +} + +func (f *memFile) Slice(start int64, end int64) ([]byte, error) { + if f.closed { + return nil, os.ErrClosed + } + if end > f.size { + return nil, io.EOF + } + return f.buf[start:end], nil +} diff --git a/vendor/github.com/akrylysov/pogreb/fs/os.go b/vendor/github.com/akrylysov/pogreb/fs/os.go new file mode 100644 index 0000000000..605ac4e8dd --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/fs/os.go @@ -0,0 +1,64 @@ +package fs + +import ( + "io/ioutil" + "os" +) + +type osFS struct{} + +// OS is a file system backed by the os package. +var OS FileSystem = &osFS{} + +func (fs *osFS) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + f, err := os.OpenFile(name, flag, perm) + if err != nil { + return nil, err + } + return &osFile{File: f}, nil +} + +func (fs *osFS) CreateLockFile(name string, perm os.FileMode) (LockFile, bool, error) { + return createLockFile(name, perm) +} + +func (fs *osFS) Stat(name string) (os.FileInfo, error) { + return os.Stat(name) +} + +func (fs *osFS) Remove(name string) error { + return os.Remove(name) +} + +func (fs *osFS) Rename(oldpath, newpath string) error { + return os.Rename(oldpath, newpath) +} + +func (fs *osFS) ReadDir(name string) ([]os.FileInfo, error) { + return ioutil.ReadDir(name) +} + +type osFile struct { + *os.File +} + +func (f *osFile) Slice(start int64, end int64) ([]byte, error) { + buf := make([]byte, end-start) + _, err := f.ReadAt(buf, start) + if err != nil { + return nil, err + } + return buf, nil +} + +type osLockFile struct { + *os.File + path string +} + +func (f *osLockFile) Unlock() error { + if err := os.Remove(f.path); err != nil { + return err + } + return f.Close() +} diff --git a/vendor/github.com/akrylysov/pogreb/fs/os_mmap.go b/vendor/github.com/akrylysov/pogreb/fs/os_mmap.go new file mode 100644 index 0000000000..3fbe40b598 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/fs/os_mmap.go @@ -0,0 +1,163 @@ +package fs + +import ( + "io" + "os" +) + +const ( + initialMmapSize = 1024 << 20 // 1 GiB +) + +type osMMapFS struct { + osFS +} + +// OSMMap is a file system backed by the os package and memory-mapped files. +var OSMMap FileSystem = &osMMapFS{} + +func (fs *osMMapFS) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + if flag&os.O_APPEND != 0 { + // osMMapFS doesn't support opening files in append-only mode. + // The database doesn't currently use O_APPEND. + return nil, errAppendModeNotSupported + } + f, err := os.OpenFile(name, flag, perm) + if err != nil { + return nil, err + } + + stat, err := f.Stat() + if err != nil { + return nil, err + } + + mf := &osMMapFile{ + File: f, + size: stat.Size(), + } + if err := mf.mremap(); err != nil { + return nil, err + } + return mf, nil +} + +type osMMapFile struct { + *os.File + data []byte + offset int64 + size int64 + mmapSize int64 +} + +func (f *osMMapFile) WriteAt(p []byte, off int64) (int, error) { + n, err := f.File.WriteAt(p, off) + if err != nil { + return 0, err + } + writeOff := off + int64(n) + if writeOff > f.size { + f.size = writeOff + } + return n, f.mremap() +} + +func (f *osMMapFile) Write(p []byte) (int, error) { + n, err := f.File.Write(p) + if err != nil { + return 0, err + } + f.offset += int64(n) + if f.offset > f.size { + f.size = f.offset + } + return n, f.mremap() +} + +func (f *osMMapFile) Seek(offset int64, whence int) (int64, error) { + off, err := f.File.Seek(offset, whence) + f.offset = off + return off, err +} + +func (f *osMMapFile) Read(p []byte) (int, error) { + n, err := f.File.Read(p) + f.offset += int64(n) + return n, err +} + +func (f *osMMapFile) Slice(start int64, end int64) ([]byte, error) { + if end > f.size { + return nil, io.EOF + } + if f.data == nil { + return nil, os.ErrClosed + } + return f.data[start:end], nil +} + +func (f *osMMapFile) munmap() error { + if f.data == nil { + return nil + } + if err := munmap(f.data); err != nil { + return err + } + f.data = nil + f.mmapSize = 0 + return nil +} + +func (f *osMMapFile) mmap(fileSize int64, mappingSize int64) error { + if f.data != nil { + if err := munmap(f.data); err != nil { + return err + } + } + + data, err := mmap(f.File, fileSize, mappingSize) + if err != nil { + return err + } + + _ = madviceRandom(data) + + f.data = data + return nil +} + +func (f *osMMapFile) mremap() error { + mmapSize := f.mmapSize + + if mmapSize >= f.size { + return nil + } + + if mmapSize == 0 { + mmapSize = initialMmapSize + if mmapSize < f.size { + mmapSize = f.size + } + } else { + if err := f.munmap(); err != nil { + return err + } + mmapSize *= 2 + } + + if err := f.mmap(f.size, mmapSize); err != nil { + return err + } + + // On Windows mmap may memory-map less than the requested size. + f.mmapSize = int64(len(f.data)) + + return nil +} + +func (f *osMMapFile) Close() error { + if err := f.munmap(); err != nil { + return err + } + return f.File.Close() +} diff --git a/vendor/github.com/akrylysov/pogreb/fs/os_mmap_unix.go b/vendor/github.com/akrylysov/pogreb/fs/os_mmap_unix.go new file mode 100644 index 0000000000..2a5d4c2738 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/fs/os_mmap_unix.go @@ -0,0 +1,34 @@ +// +build !windows + +package fs + +import ( + "os" + "syscall" + "unsafe" +) + +func mmap(f *os.File, fileSize int64, mappingSize int64) ([]byte, error) { + p, err := syscall.Mmap(int(f.Fd()), 0, int(mappingSize), syscall.PROT_READ, syscall.MAP_SHARED) + return p, err +} + +func munmap(data []byte) error { + return syscall.Munmap(data) +} + +func madviceRandom(data []byte) error { + _, _, errno := syscall.Syscall(syscall.SYS_MADVISE, uintptr(unsafe.Pointer(&data[0])), uintptr(len(data)), uintptr(syscall.MADV_RANDOM)) + if errno != 0 { + return errno + } + return nil +} + +func (f *osMMapFile) Truncate(size int64) error { + if err := f.File.Truncate(size); err != nil { + return err + } + f.size = size + return f.mremap() +} diff --git a/vendor/github.com/akrylysov/pogreb/fs/os_mmap_windows.go b/vendor/github.com/akrylysov/pogreb/fs/os_mmap_windows.go new file mode 100644 index 0000000000..1f2d8f053a --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/fs/os_mmap_windows.go @@ -0,0 +1,45 @@ +// +build windows + +package fs + +import ( + "os" + "syscall" + "unsafe" +) + +func mmap(f *os.File, fileSize int64, mappingSize int64) ([]byte, error) { + size := fileSize + low, high := uint32(size), uint32(size>>32) + fmap, err := syscall.CreateFileMapping(syscall.Handle(f.Fd()), nil, syscall.PAGE_READONLY, high, low, nil) + if err != nil { + return nil, err + } + defer syscall.CloseHandle(fmap) + ptr, err := syscall.MapViewOfFile(fmap, syscall.FILE_MAP_READ, 0, 0, uintptr(size)) + if err != nil { + return nil, err + } + data := (*[maxMmapSize]byte)(unsafe.Pointer(ptr))[:size] + return data, nil +} + +func munmap(data []byte) error { + return syscall.UnmapViewOfFile(uintptr(unsafe.Pointer(&data[0]))) +} + +func madviceRandom(data []byte) error { + return nil +} + +func (f *osMMapFile) Truncate(size int64) error { + // Truncating a memory-mapped file fails on Windows. Unmap it first. + if err := f.munmap(); err != nil { + return err + } + if err := f.File.Truncate(size); err != nil { + return err + } + f.size = size + return f.mremap() +} diff --git a/vendor/github.com/akrylysov/pogreb/fs/os_mmap_windows_386.go b/vendor/github.com/akrylysov/pogreb/fs/os_mmap_windows_386.go new file mode 100644 index 0000000000..57a1264a91 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/fs/os_mmap_windows_386.go @@ -0,0 +1,7 @@ +package fs + +import ( + "math" +) + +const maxMmapSize = math.MaxInt32 diff --git a/vendor/github.com/akrylysov/pogreb/fs/os_mmap_windows_amd64.go b/vendor/github.com/akrylysov/pogreb/fs/os_mmap_windows_amd64.go new file mode 100644 index 0000000000..bac97d87cd --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/fs/os_mmap_windows_amd64.go @@ -0,0 +1,3 @@ +package fs + +const maxMmapSize = 1 << 48 diff --git a/vendor/github.com/akrylysov/pogreb/fs/os_unix.go b/vendor/github.com/akrylysov/pogreb/fs/os_unix.go new file mode 100644 index 0000000000..0b11c15aa8 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/fs/os_unix.go @@ -0,0 +1,26 @@ +// +build !windows + +package fs + +import ( + "os" + "syscall" +) + +func createLockFile(name string, perm os.FileMode) (LockFile, bool, error) { + acquiredExisting := false + if _, err := os.Stat(name); err == nil { + acquiredExisting = true + } + f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE, perm) + if err != nil { + return nil, false, err + } + if err := syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); err != nil { + if err == syscall.EWOULDBLOCK { + err = os.ErrExist + } + return nil, false, err + } + return &osLockFile{f, name}, acquiredExisting, nil +} diff --git a/vendor/github.com/akrylysov/pogreb/fs/os_windows.go b/vendor/github.com/akrylysov/pogreb/fs/os_windows.go new file mode 100644 index 0000000000..cdd61c809e --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/fs/os_windows.go @@ -0,0 +1,60 @@ +// +build windows + +package fs + +import ( + "os" + "syscall" + "unsafe" +) + +var ( + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + procLockFileEx = modkernel32.NewProc("LockFileEx") +) + +const ( + errorLockViolation = 0x21 +) + +func lockfile(f *os.File) error { + var ol syscall.Overlapped + + r1, _, err := syscall.Syscall6( + procLockFileEx.Addr(), + 6, + uintptr(f.Fd()), // handle + uintptr(0x0003), + uintptr(0), // reserved + uintptr(1), // locklow + uintptr(0), // lockhigh + uintptr(unsafe.Pointer(&ol)), + ) + if r1 == 0 && (err == syscall.ERROR_FILE_EXISTS || err == errorLockViolation) { + return os.ErrExist + } + return nil +} + +func createLockFile(name string, perm os.FileMode) (LockFile, bool, error) { + acquiredExisting := false + if _, err := os.Stat(name); err == nil { + acquiredExisting = true + } + fd, err := syscall.CreateFile(&(syscall.StringToUTF16(name)[0]), + syscall.GENERIC_READ|syscall.GENERIC_WRITE, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, + nil, + syscall.CREATE_ALWAYS, + syscall.FILE_ATTRIBUTE_NORMAL, + 0) + if err != nil { + return nil, false, os.ErrExist + } + f := os.NewFile(uintptr(fd), name) + if err := lockfile(f); err != nil { + f.Close() + return nil, false, err + } + return &osLockFile{f, name}, acquiredExisting, nil +} diff --git a/vendor/github.com/akrylysov/pogreb/fs/sub.go b/vendor/github.com/akrylysov/pogreb/fs/sub.go new file mode 100644 index 0000000000..9a69d1ede7 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/fs/sub.go @@ -0,0 +1,52 @@ +package fs + +import ( + "os" + "path/filepath" +) + +// Sub returns a new file system rooted at dir. +func Sub(fsys FileSystem, dir string) FileSystem { + return &subFS{ + fsys: fsys, + root: dir, + } +} + +type subFS struct { + fsys FileSystem + root string +} + +func (fs *subFS) OpenFile(name string, flag int, perm os.FileMode) (File, error) { + subName := filepath.Join(fs.root, name) + return fs.fsys.OpenFile(subName, flag, perm) +} + +func (fs *subFS) Stat(name string) (os.FileInfo, error) { + subName := filepath.Join(fs.root, name) + return fs.fsys.Stat(subName) +} + +func (fs *subFS) Remove(name string) error { + subName := filepath.Join(fs.root, name) + return fs.fsys.Remove(subName) +} + +func (fs *subFS) Rename(oldpath, newpath string) error { + subOldpath := filepath.Join(fs.root, oldpath) + subNewpath := filepath.Join(fs.root, newpath) + return fs.fsys.Rename(subOldpath, subNewpath) +} + +func (fs *subFS) ReadDir(name string) ([]os.FileInfo, error) { + subName := filepath.Join(fs.root, name) + return fs.fsys.ReadDir(subName) +} + +func (fs *subFS) CreateLockFile(name string, perm os.FileMode) (LockFile, bool, error) { + subName := filepath.Join(fs.root, name) + return fs.fsys.CreateLockFile(subName, perm) +} + +var _ FileSystem = &subFS{} diff --git a/vendor/github.com/akrylysov/pogreb/gobfile.go b/vendor/github.com/akrylysov/pogreb/gobfile.go new file mode 100644 index 0000000000..054bfa5e9a --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/gobfile.go @@ -0,0 +1,27 @@ +package pogreb + +import ( + "encoding/gob" + + "github.com/akrylysov/pogreb/fs" +) + +func readGobFile(fsys fs.FileSystem, name string, v interface{}) error { + f, err := openFile(fsys, name, openFileFlags{readOnly: true}) + if err != nil { + return err + } + defer f.Close() + dec := gob.NewDecoder(f) + return dec.Decode(v) +} + +func writeGobFile(fsys fs.FileSystem, name string, v interface{}) error { + f, err := openFile(fsys, name, openFileFlags{truncate: true}) + if err != nil { + return err + } + defer f.Close() + enc := gob.NewEncoder(f) + return enc.Encode(v) +} diff --git a/vendor/github.com/akrylysov/pogreb/header.go b/vendor/github.com/akrylysov/pogreb/header.go new file mode 100644 index 0000000000..7ff5a6795a --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/header.go @@ -0,0 +1,43 @@ +package pogreb + +import ( + "bytes" + "encoding/binary" +) + +const ( + formatVersion = 2 // File format version. + headerSize = 512 +) + +var ( + signature = [8]byte{'p', 'o', 'g', 'r', 'e', 'b', '\x0e', '\xfd'} +) + +type header struct { + signature [8]byte + formatVersion uint32 +} + +func newHeader() *header { + return &header{ + signature: signature, + formatVersion: formatVersion, + } +} + +func (h header) MarshalBinary() ([]byte, error) { + buf := make([]byte, headerSize) + copy(buf[:8], h.signature[:]) + binary.LittleEndian.PutUint32(buf[8:12], h.formatVersion) + return buf, nil +} + +func (h *header) UnmarshalBinary(data []byte) error { + if !bytes.Equal(data[:8], signature[:]) { + return errCorrupted + } + copy(h.signature[:], data[:8]) + h.formatVersion = binary.LittleEndian.Uint32(data[8:12]) + return nil +} diff --git a/vendor/github.com/akrylysov/pogreb/index.go b/vendor/github.com/akrylysov/pogreb/index.go new file mode 100644 index 0000000000..de189642a9 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/index.go @@ -0,0 +1,363 @@ +package pogreb + +import ( + "github.com/akrylysov/pogreb/internal/errors" +) + +const ( + indexExt = ".pix" + indexMainName = "main" + indexExt + indexOverflowName = "overflow" + indexExt + indexMetaName = "index" + metaExt + loadFactor = 0.7 +) + +// index is an on-disk linear hashing hash table. +// It uses two files to store the hash table on disk - "main" and "overflow" index files. +// Each index file holds an array of buckets. +type index struct { + opts *Options + main *file // Main index file. + overflow *file // Overflow index file. + freeBucketOffs []int64 // Offsets of freed buckets. + level uint8 // Maximum number of buckets on a logarithmic scale. + numKeys uint32 // Number of keys. + numBuckets uint32 // Number of buckets. + splitBucketIdx uint32 // Index of the bucket to split on next split. +} + +type indexMeta struct { + Level uint8 + NumKeys uint32 + NumBuckets uint32 + SplitBucketIndex uint32 + FreeOverflowBuckets []int64 +} + +// matchKeyFunc returns whether the slot matches the key sought. +type matchKeyFunc func(slot) (bool, error) + +func openIndex(opts *Options) (*index, error) { + main, err := openFile(opts.FileSystem, indexMainName, openFileFlags{}) + if err != nil { + return nil, errors.Wrap(err, "opening main index") + } + overflow, err := openFile(opts.FileSystem, indexOverflowName, openFileFlags{}) + if err != nil { + _ = main.Close() + return nil, errors.Wrap(err, "opening overflow index") + } + idx := &index{ + opts: opts, + main: main, + overflow: overflow, + numBuckets: 1, + } + if main.empty() { + // Add an empty bucket. + if _, err = idx.main.extend(bucketSize); err != nil { + _ = main.Close() + _ = overflow.Close() + return nil, err + } + } else if err := idx.readMeta(); err != nil { + _ = main.Close() + _ = overflow.Close() + return nil, errors.Wrap(err, "opening index meta") + } + return idx, nil +} + +func (idx *index) writeMeta() error { + m := indexMeta{ + Level: idx.level, + NumKeys: idx.numKeys, + NumBuckets: idx.numBuckets, + SplitBucketIndex: idx.splitBucketIdx, + FreeOverflowBuckets: idx.freeBucketOffs, + } + return writeGobFile(idx.opts.FileSystem, indexMetaName, m) +} + +func (idx *index) readMeta() error { + m := indexMeta{} + if err := readGobFile(idx.opts.FileSystem, indexMetaName, &m); err != nil { + return err + } + idx.level = m.Level + idx.numKeys = m.NumKeys + idx.numBuckets = m.NumBuckets + idx.splitBucketIdx = m.SplitBucketIndex + idx.freeBucketOffs = m.FreeOverflowBuckets + return nil +} + +func (idx *index) bucketIndex(hash uint32) uint32 { + bidx := hash & ((1 << idx.level) - 1) + if bidx < idx.splitBucketIdx { + return hash & ((1 << (idx.level + 1)) - 1) + } + return bidx +} + +type bucketIterator struct { + off int64 // Offset of the next bucket. + f *file // Current index file. + overflow *file // Overflow index file. +} + +// bucketOffset returns on-disk bucket offset by the bucket index. +func bucketOffset(idx uint32) int64 { + return int64(headerSize) + (int64(bucketSize) * int64(idx)) +} + +func (idx *index) newBucketIterator(startBucketIdx uint32) *bucketIterator { + return &bucketIterator{ + off: bucketOffset(startBucketIdx), + f: idx.main, + overflow: idx.overflow, + } +} + +func (it *bucketIterator) next() (bucketHandle, error) { + if it.off == 0 { + return bucketHandle{}, ErrIterationDone + } + b := bucketHandle{file: it.f, offset: it.off} + if err := b.read(); err != nil { + return bucketHandle{}, err + } + it.f = it.overflow + it.off = b.next + return b, nil +} + +func (idx *index) get(hash uint32, matchKey matchKeyFunc) error { + it := idx.newBucketIterator(idx.bucketIndex(hash)) + for { + b, err := it.next() + if err == ErrIterationDone { + return nil + } + if err != nil { + return err + } + for i := 0; i < slotsPerBucket; i++ { + sl := b.slots[i] + // No more slots in the bucket. + if sl.offset == 0 { + break + } + if hash != sl.hash { + continue + } + if match, err := matchKey(sl); match || err != nil { + return err + } + } + } +} + +func (idx *index) findInsertionBucket(newSlot slot, matchKey matchKeyFunc) (*slotWriter, bool, error) { + sw := &slotWriter{} + it := idx.newBucketIterator(idx.bucketIndex(newSlot.hash)) + for { + b, err := it.next() + if err == ErrIterationDone { + return nil, false, errors.New("failed to insert a new slot") + } + if err != nil { + return nil, false, err + } + sw.bucket = &b + var i int + for i = 0; i < slotsPerBucket; i++ { + sl := b.slots[i] + if sl.offset == 0 { + // Found an empty slot. + sw.slotIdx = i + return sw, false, nil + } + if newSlot.hash != sl.hash { + continue + } + match, err := matchKey(sl) + if err != nil { + return nil, false, err + } + if match { + // Key already in the index. + // The slot writer will overwrite the existing slot. + sw.slotIdx = i + return sw, true, nil + } + } + if b.next == 0 { + // No more buckets in the chain. + sw.slotIdx = i + return sw, false, nil + } + } +} + +func (idx *index) put(newSlot slot, matchKey matchKeyFunc) error { + if idx.numKeys == MaxKeys { + return errFull + } + sw, overwritingExisting, err := idx.findInsertionBucket(newSlot, matchKey) + if err != nil { + return err + } + if err := sw.insert(newSlot, idx); err != nil { + return err + } + if err := sw.write(); err != nil { + return err + } + if overwritingExisting { + return nil + } + idx.numKeys++ + if float64(idx.numKeys)/float64(idx.numBuckets*slotsPerBucket) > loadFactor { + if err := idx.split(); err != nil { + return err + } + } + return nil +} + +func (idx *index) delete(hash uint32, matchKey matchKeyFunc) error { + it := idx.newBucketIterator(idx.bucketIndex(hash)) + for { + b, err := it.next() + if err == ErrIterationDone { + return nil + } + if err != nil { + return err + } + for i := 0; i < slotsPerBucket; i++ { + sl := b.slots[i] + if sl.offset == 0 { + break + } + if hash != sl.hash { + continue + } + match, err := matchKey(sl) + if err != nil { + return err + } + if !match { + continue + } + b.del(i) + if err := b.write(); err != nil { + return err + } + idx.numKeys-- + return nil + } + } +} + +func (idx *index) createOverflowBucket() (*bucketHandle, error) { + var off int64 + if len(idx.freeBucketOffs) > 0 { + off = idx.freeBucketOffs[0] + idx.freeBucketOffs = idx.freeBucketOffs[1:] + } else { + var err error + off, err = idx.overflow.extend(bucketSize) + if err != nil { + return nil, err + } + } + return &bucketHandle{file: idx.overflow, offset: off}, nil +} + +func (idx *index) freeOverflowBucket(offsets ...int64) { + idx.freeBucketOffs = append(idx.freeBucketOffs, offsets...) +} + +func (idx *index) split() error { + updatedBucketIdx := idx.splitBucketIdx + updatedBucketOff := bucketOffset(updatedBucketIdx) + updatedBucket := slotWriter{ + bucket: &bucketHandle{file: idx.main, offset: updatedBucketOff}, + } + + newBucketOff, err := idx.main.extend(bucketSize) + if err != nil { + return err + } + + sw := slotWriter{ + bucket: &bucketHandle{file: idx.main, offset: newBucketOff}, + } + + idx.splitBucketIdx++ + if idx.splitBucketIdx == 1<= 4 { + k1 := uint32(data[0]) | uint32(data[1])<<8 | uint32(data[2])<<16 | uint32(data[3])<<24 + data = data[4:] + + k1 *= c1 + k1 = bits.RotateLeft32(k1, 15) + k1 *= c2 + + h1 ^= k1 + h1 = bits.RotateLeft32(h1, 13) + h1 = h1*5 + 0xe6546b64 + } + + var k1 uint32 + switch len(data) { + case 3: + k1 ^= uint32(data[2]) << 16 + fallthrough + case 2: + k1 ^= uint32(data[1]) << 8 + fallthrough + case 1: + k1 ^= uint32(data[0]) + k1 *= c1 + k1 = bits.RotateLeft32(k1, 15) + k1 *= c2 + h1 ^= k1 + } + + h1 ^= uint32(dlen) + + h1 ^= h1 >> 16 + h1 *= 0x85ebca6b + h1 ^= h1 >> 13 + h1 *= 0xc2b2ae35 + h1 ^= h1 >> 16 + + return h1 +} diff --git a/vendor/github.com/akrylysov/pogreb/internal/hash/seed.go b/vendor/github.com/akrylysov/pogreb/internal/hash/seed.go new file mode 100644 index 0000000000..1fbc5bdfbb --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/internal/hash/seed.go @@ -0,0 +1,15 @@ +package hash + +import ( + "crypto/rand" + "encoding/binary" +) + +// RandSeed generates a random hash seed. +func RandSeed() (uint32, error) { + b := make([]byte, 4) + if _, err := rand.Read(b); err != nil { + return 0, err + } + return binary.LittleEndian.Uint32(b), nil +} diff --git a/vendor/github.com/akrylysov/pogreb/iterator.go b/vendor/github.com/akrylysov/pogreb/iterator.go new file mode 100644 index 0000000000..19f4ccc689 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/iterator.go @@ -0,0 +1,75 @@ +package pogreb + +import ( + "errors" + "sync" +) + +// ErrIterationDone is returned by ItemIterator.Next calls when there are no more items to return. +var ErrIterationDone = errors.New("no more items in iterator") + +type item struct { + key []byte + value []byte +} + +// ItemIterator is an iterator over DB key-value pairs. It iterates the items in an unspecified order. +type ItemIterator struct { + db *DB + nextBucketIdx uint32 + queue []item + mu sync.Mutex +} + +// fetchItems adds items to the iterator queue from a bucket located at nextBucketIdx. +func (it *ItemIterator) fetchItems(nextBucketIdx uint32) error { + bit := it.db.index.newBucketIterator(nextBucketIdx) + for { + b, err := bit.next() + if err == ErrIterationDone { + return nil + } + if err != nil { + return err + } + for i := 0; i < slotsPerBucket; i++ { + sl := b.slots[i] + if sl.offset == 0 { + // No more items in the bucket. + break + } + key, value, err := it.db.datalog.readKeyValue(sl) + if err != nil { + return err + } + key = cloneBytes(key) + value = cloneBytes(value) + it.queue = append(it.queue, item{key: key, value: value}) + } + } +} + +// Next returns the next key-value pair if available, otherwise it returns ErrIterationDone error. +func (it *ItemIterator) Next() ([]byte, []byte, error) { + it.mu.Lock() + defer it.mu.Unlock() + + it.db.mu.RLock() + defer it.db.mu.RUnlock() + + // The iterator queue is empty and we have more buckets to check. + for len(it.queue) == 0 && it.nextBucketIdx < it.db.index.numBuckets { + if err := it.fetchItems(it.nextBucketIdx); err != nil { + return nil, nil, err + } + it.nextBucketIdx++ + } + + if len(it.queue) > 0 { + item := it.queue[0] + it.queue = it.queue[1:] + return item.key, item.value, nil + } + + return nil, nil, ErrIterationDone +} diff --git a/vendor/github.com/akrylysov/pogreb/lock.go b/vendor/github.com/akrylysov/pogreb/lock.go new file mode 100644 index 0000000000..f68b141681 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/lock.go @@ -0,0 +1,15 @@ +package pogreb + +import ( + "os" + + "github.com/akrylysov/pogreb/fs" +) + +const ( + lockName = "lock" +) + +func createLockFile(opts *Options) (fs.LockFile, bool, error) { + return opts.FileSystem.CreateLockFile(lockName, os.FileMode(0644)) +} diff --git a/vendor/github.com/akrylysov/pogreb/logger.go b/vendor/github.com/akrylysov/pogreb/logger.go new file mode 100644 index 0000000000..84bc7c2ac4 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/logger.go @@ -0,0 +1,15 @@ +package pogreb + +import ( + "log" + "os" +) + +var logger = log.New(os.Stderr, "pogreb: ", 0) + +// SetLogger sets the global logger. +func SetLogger(l *log.Logger) { + if l != nil { + logger = l + } +} diff --git a/vendor/github.com/akrylysov/pogreb/metrics.go b/vendor/github.com/akrylysov/pogreb/metrics.go new file mode 100644 index 0000000000..5ea34ea239 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/metrics.go @@ -0,0 +1,11 @@ +package pogreb + +import "expvar" + +// Metrics holds the DB metrics. +type Metrics struct { + Puts expvar.Int + Dels expvar.Int + Gets expvar.Int + HashCollisions expvar.Int +} diff --git a/vendor/github.com/akrylysov/pogreb/options.go b/vendor/github.com/akrylysov/pogreb/options.go new file mode 100644 index 0000000000..3cb8048c9a --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/options.go @@ -0,0 +1,52 @@ +package pogreb + +import ( + "math" + "time" + + "github.com/akrylysov/pogreb/fs" +) + +// Options holds the optional DB parameters. +type Options struct { + // BackgroundSyncInterval sets the amount of time between background Sync() calls. + // + // Setting the value to 0 disables the automatic background synchronization. + // Setting the value to -1 makes the DB call Sync() after every write operation. + BackgroundSyncInterval time.Duration + + // BackgroundCompactionInterval sets the amount of time between background Compact() calls. + // + // Setting the value to 0 disables the automatic background compaction. + BackgroundCompactionInterval time.Duration + + // FileSystem sets the file system implementation. + // + // Default: fs.OSMMap. + FileSystem fs.FileSystem + + maxSegmentSize uint32 + compactionMinSegmentSize uint32 + compactionMinFragmentation float32 +} + +func (src *Options) copyWithDefaults(path string) *Options { + opts := Options{} + if src != nil { + opts = *src + } + if opts.FileSystem == nil { + opts.FileSystem = fs.OSMMap + } + opts.FileSystem = fs.Sub(opts.FileSystem, path) + if opts.maxSegmentSize == 0 { + opts.maxSegmentSize = math.MaxUint32 + } + if opts.compactionMinSegmentSize == 0 { + opts.compactionMinSegmentSize = 32 << 20 + } + if opts.compactionMinFragmentation == 0 { + opts.compactionMinFragmentation = 0.5 + } + return &opts +} diff --git a/vendor/github.com/akrylysov/pogreb/recovery.go b/vendor/github.com/akrylysov/pogreb/recovery.go new file mode 100644 index 0000000000..3381348b5a --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/recovery.go @@ -0,0 +1,161 @@ +package pogreb + +import ( + "io" + "path/filepath" + + "github.com/akrylysov/pogreb/fs" +) + +const ( + recoveryBackupExt = ".bac" +) + +func backupNonsegmentFiles(fsys fs.FileSystem) error { + logger.Println("moving non-segment files...") + + files, err := fsys.ReadDir(".") + if err != nil { + return err + } + + for _, file := range files { + name := file.Name() + ext := filepath.Ext(name) + if ext == segmentExt || name == lockName { + continue + } + dst := name + recoveryBackupExt + if err := fsys.Rename(name, dst); err != nil { + return err + } + logger.Printf("moved %s to %s", name, dst) + } + + return nil +} + +func removeRecoveryBackupFiles(fsys fs.FileSystem) error { + logger.Println("removing recovery backup files...") + + files, err := fsys.ReadDir(".") + if err != nil { + return err + } + + for _, file := range files { + name := file.Name() + ext := filepath.Ext(name) + if ext != recoveryBackupExt { + continue + } + if err := fsys.Remove(name); err != nil { + return err + } + logger.Printf("removed %s", name) + } + + return nil +} + +// recoveryIterator iterates over records of all datalog segments in insertion order. +// Corrupted segments are truncated to the last valid record. +type recoveryIterator struct { + segments []*segment + segit *segmentIterator +} + +func newRecoveryIterator(segments []*segment) *recoveryIterator { + return &recoveryIterator{ + segments: segments, + } +} + +func (it *recoveryIterator) next() (record, error) { + for { + if it.segit == nil { + if len(it.segments) == 0 { + return record{}, ErrIterationDone + } + var err error + it.segit, err = newSegmentIterator(it.segments[0]) + if err != nil { + return record{}, err + } + it.segments = it.segments[1:] + } + rec, err := it.segit.next() + if err == io.EOF || err == io.ErrUnexpectedEOF || err == errCorrupted { + // Truncate file to the last valid offset. + if err := it.segit.f.Truncate(int64(it.segit.offset)); err != nil { + return record{}, err + } + fi, fierr := it.segit.f.Stat() + if fierr != nil { + return record{}, fierr + } + logger.Printf("truncated segment %s to offset %d", fi.Name(), it.segit.offset) + err = ErrIterationDone + } + if err == ErrIterationDone { + it.segit = nil + continue + } + if err != nil { + return record{}, err + } + return rec, nil + } +} + +func (db *DB) recover() error { + logger.Println("started recovery") + logger.Println("rebuilding index...") + + segments := db.datalog.segmentsBySequenceID() + it := newRecoveryIterator(segments) + for { + rec, err := it.next() + if err == ErrIterationDone { + break + } + if err != nil { + return err + } + + h := db.hash(rec.key) + meta := db.datalog.segments[rec.segmentID].meta + if rec.rtype == recordTypePut { + sl := slot{ + hash: h, + segmentID: rec.segmentID, + keySize: uint16(len(rec.key)), + valueSize: uint32(len(rec.value)), + offset: rec.offset, + } + if err := db.put(sl, rec.key); err != nil { + return err + } + meta.PutRecords++ + } else { + if err := db.del(h, rec.key, false); err != nil { + return err + } + meta.DeleteRecords++ + meta.DeletedBytes += uint32(len(rec.data)) + } + } + + // Mark all segments except the newest as full. + for i := 0; i < len(segments)-1; i++ { + segments[i].meta.Full = true + } + + if err := removeRecoveryBackupFiles(db.opts.FileSystem); err != nil { + logger.Printf("error removing recovery backups files: %v", err) + } + + logger.Println("successfully recovered database") + + return nil +} diff --git a/vendor/github.com/akrylysov/pogreb/segment.go b/vendor/github.com/akrylysov/pogreb/segment.go new file mode 100644 index 0000000000..34225f2661 --- /dev/null +++ b/vendor/github.com/akrylysov/pogreb/segment.go @@ -0,0 +1,156 @@ +package pogreb + +import ( + "bufio" + "encoding/binary" + "fmt" + "hash/crc32" + "io" +) + +type recordType int + +const ( + recordTypePut recordType = iota + recordTypeDelete + + segmentExt = ".psg" +) + +// segment is a write-ahead log segment. +// It consists of a sequence of binary-encoded variable length records. +type segment struct { + *file + id uint16 // Physical segment identifier. + sequenceID uint64 // Logical monotonically increasing segment identifier. + name string + meta *segmentMeta +} + +func segmentName(id uint16, sequenceID uint64) string { + return fmt.Sprintf("%05d-%d%s", id, sequenceID, segmentExt) +} + +type segmentMeta struct { + Full bool + PutRecords uint32 + DeleteRecords uint32 + DeletedKeys uint32 + DeletedBytes uint32 +} + +func segmentMetaName(id uint16, sequenceID uint64) string { + return segmentName(id, sequenceID) + metaExt +} + +// Binary representation of a segment record: +// +---------------+------------------+------------------+-...-+--...--+----------+ +// | Key Size (2B) | Record Type (1b) | Value Size (31b) | Key | Value | CRC (4B) | +// +---------------+------------------+------------------+-...-+--...--+----------+ +type record struct { + rtype recordType + segmentID uint16 + offset uint32 + data []byte + key []byte + value []byte +} + +func encodedRecordSize(kvSize uint32) uint32 { + // key size, value size, key, value, crc32 + return 2 + 4 + kvSize + 4 +} + +func encodeRecord(key []byte, value []byte, rt recordType) []byte { + size := encodedRecordSize(uint32(len(key) + len(value))) + data := make([]byte, size) + binary.LittleEndian.PutUint16(data[:2], uint16(len(key))) + + valLen := uint32(len(value)) + if rt == recordTypeDelete { // Set delete bit. + valLen |= 1 << 31 + } + binary.LittleEndian.PutUint32(data[2:], valLen) + + copy(data[6:], key) + copy(data[6+len(key):], value) + checksum := crc32.ChecksumIEEE(data[:6+len(key)+len(value)]) + binary.LittleEndian.PutUint32(data[size-4:size], checksum) + return data +} + +func encodePutRecord(key []byte, value []byte) []byte { + return encodeRecord(key, value, recordTypePut) +} + +func encodeDeleteRecord(key []byte) []byte { + return encodeRecord(key, nil, recordTypeDelete) +} + +// segmentIterator iterates over segment records. +type segmentIterator struct { + f *segment + offset uint32 + r *bufio.Reader + buf []byte // kv size and crc32 reusable buffer. +} + +func newSegmentIterator(f *segment) (*segmentIterator, error) { + if _, err := f.Seek(int64(headerSize), io.SeekStart); err != nil { + return nil, err + } + return &segmentIterator{ + f: f, + offset: headerSize, + r: bufio.NewReader(f), + buf: make([]byte, 6), + }, nil +} + +func (it *segmentIterator) next() (record, error) { + // Read key and value size. + kvSizeBuf := it.buf + if _, err := io.ReadFull(it.r, kvSizeBuf); err != nil { + if err == io.EOF { + return record{}, ErrIterationDone + } + return record{}, err + } + + // Decode key size. + keySize := uint32(binary.LittleEndian.Uint16(kvSizeBuf[:2])) + + // Decode value size and record type. + rt := recordTypePut + valueSize := binary.LittleEndian.Uint32(kvSizeBuf[2:]) + if valueSize&(1<<31) != 0 { + rt = recordTypeDelete + valueSize &^= 1 << 31 + } + + // Read key, value and checksum. + recordSize := encodedRecordSize(keySize + valueSize) + data := make([]byte, recordSize) + copy(data, kvSizeBuf) + if _, err := io.ReadFull(it.r, data[6:]); err != nil { + return record{}, err + } + + // Verify checksum. + checksum := binary.LittleEndian.Uint32(data[len(data)-4:]) + if checksum != crc32.ChecksumIEEE(data[:len(data)-4]) { + return record{}, errCorrupted + } + + offset := it.offset + it.offset += recordSize + rec := record{ + rtype: rt, + segmentID: it.f.id, + offset: offset, + data: data, + key: data[6 : 6+keySize], + value: data[6+keySize : 6+keySize+valueSize], + } + return rec, nil +} diff --git a/vendor/github.com/go-git/gcfg/.gitignore b/vendor/github.com/go-git/gcfg/.gitignore new file mode 100644 index 0000000000..2d830686d4 --- /dev/null +++ b/vendor/github.com/go-git/gcfg/.gitignore @@ -0,0 +1 @@ +coverage.out diff --git a/vendor/github.com/go-git/gcfg/LICENSE b/vendor/github.com/go-git/gcfg/LICENSE new file mode 100644 index 0000000000..87a5cede33 --- /dev/null +++ b/vendor/github.com/go-git/gcfg/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2012 Péter Surányi. Portions Copyright (c) 2009 The Go +Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/go-git/gcfg/Makefile b/vendor/github.com/go-git/gcfg/Makefile new file mode 100644 index 0000000000..73604da6b6 --- /dev/null +++ b/vendor/github.com/go-git/gcfg/Makefile @@ -0,0 +1,17 @@ +# General +WORKDIR = $(PWD) + +# Go parameters +GOCMD = go +GOTEST = $(GOCMD) test + +# Coverage +COVERAGE_REPORT = coverage.out +COVERAGE_MODE = count + +test: + $(GOTEST) ./... + +test-coverage: + echo "" > $(COVERAGE_REPORT); \ + $(GOTEST) -coverprofile=$(COVERAGE_REPORT) -coverpkg=./... -covermode=$(COVERAGE_MODE) ./... diff --git a/vendor/github.com/go-git/gcfg/README b/vendor/github.com/go-git/gcfg/README new file mode 100644 index 0000000000..1ff233a529 --- /dev/null +++ b/vendor/github.com/go-git/gcfg/README @@ -0,0 +1,4 @@ +Gcfg reads INI-style configuration files into Go structs; +supports user-defined types and subsections. + +Package docs: https://godoc.org/gopkg.in/gcfg.v1 diff --git a/vendor/github.com/go-git/gcfg/doc.go b/vendor/github.com/go-git/gcfg/doc.go new file mode 100644 index 0000000000..7bdefbf020 --- /dev/null +++ b/vendor/github.com/go-git/gcfg/doc.go @@ -0,0 +1,145 @@ +// Package gcfg reads "INI-style" text-based configuration files with +// "name=value" pairs grouped into sections (gcfg files). +// +// This package is still a work in progress; see the sections below for planned +// changes. +// +// Syntax +// +// The syntax is based on that used by git config: +// http://git-scm.com/docs/git-config#_syntax . +// There are some (planned) differences compared to the git config format: +// - improve data portability: +// - must be encoded in UTF-8 (for now) and must not contain the 0 byte +// - include and "path" type is not supported +// (path type may be implementable as a user-defined type) +// - internationalization +// - section and variable names can contain unicode letters, unicode digits +// (as defined in http://golang.org/ref/spec#Characters ) and hyphens +// (U+002D), starting with a unicode letter +// - disallow potentially ambiguous or misleading definitions: +// - `[sec.sub]` format is not allowed (deprecated in gitconfig) +// - `[sec ""]` is not allowed +// - use `[sec]` for section name "sec" and empty subsection name +// - (planned) within a single file, definitions must be contiguous for each: +// - section: '[secA]' -> '[secB]' -> '[secA]' is an error +// - subsection: '[sec "A"]' -> '[sec "B"]' -> '[sec "A"]' is an error +// - multivalued variable: 'multi=a' -> 'other=x' -> 'multi=b' is an error +// +// Data structure +// +// The functions in this package read values into a user-defined struct. +// Each section corresponds to a struct field in the config struct, and each +// variable in a section corresponds to a data field in the section struct. +// The mapping of each section or variable name to fields is done either based +// on the "gcfg" struct tag or by matching the name of the section or variable, +// ignoring case. In the latter case, hyphens '-' in section and variable names +// correspond to underscores '_' in field names. +// Fields must be exported; to use a section or variable name starting with a +// letter that is neither upper- or lower-case, prefix the field name with 'X'. +// (See https://code.google.com/p/go/issues/detail?id=5763#c4 .) +// +// For sections with subsections, the corresponding field in config must be a +// map, rather than a struct, with string keys and pointer-to-struct values. +// Values for subsection variables are stored in the map with the subsection +// name used as the map key. +// (Note that unlike section and variable names, subsection names are case +// sensitive.) +// When using a map, and there is a section with the same section name but +// without a subsection name, its values are stored with the empty string used +// as the key. +// It is possible to provide default values for subsections in the section +// "default-" (or by setting values in the corresponding struct +// field "Default_"). +// +// The functions in this package panic if config is not a pointer to a struct, +// or when a field is not of a suitable type (either a struct or a map with +// string keys and pointer-to-struct values). +// +// Parsing of values +// +// The section structs in the config struct may contain single-valued or +// multi-valued variables. Variables of unnamed slice type (that is, a type +// starting with `[]`) are treated as multi-value; all others (including named +// slice types) are treated as single-valued variables. +// +// Single-valued variables are handled based on the type as follows. +// Unnamed pointer types (that is, types starting with `*`) are dereferenced, +// and if necessary, a new instance is allocated. +// +// For types implementing the encoding.TextUnmarshaler interface, the +// UnmarshalText method is used to set the value. Implementing this method is +// the recommended way for parsing user-defined types. +// +// For fields of string kind, the value string is assigned to the field, after +// unquoting and unescaping as needed. +// For fields of bool kind, the field is set to true if the value is "true", +// "yes", "on" or "1", and set to false if the value is "false", "no", "off" or +// "0", ignoring case. In addition, single-valued bool fields can be specified +// with a "blank" value (variable name without equals sign and value); in such +// case the value is set to true. +// +// Predefined integer types [u]int(|8|16|32|64) and big.Int are parsed as +// decimal or hexadecimal (if having '0x' prefix). (This is to prevent +// unintuitively handling zero-padded numbers as octal.) Other types having +// [u]int* as the underlying type, such as os.FileMode and uintptr allow +// decimal, hexadecimal, or octal values. +// Parsing mode for integer types can be overridden using the struct tag option +// ",int=mode" where mode is a combination of the 'd', 'h', and 'o' characters +// (each standing for decimal, hexadecimal, and octal, respectively.) +// +// All other types are parsed using fmt.Sscanf with the "%v" verb. +// +// For multi-valued variables, each individual value is parsed as above and +// appended to the slice. If the first value is specified as a "blank" value +// (variable name without equals sign and value), a new slice is allocated; +// that is any values previously set in the slice will be ignored. +// +// The types subpackage for provides helpers for parsing "enum-like" and integer +// types. +// +// Error handling +// +// There are 3 types of errors: +// +// - programmer errors / panics: +// - invalid configuration structure +// - data errors: +// - fatal errors: +// - invalid configuration syntax +// - warnings: +// - data that doesn't belong to any part of the config structure +// +// Programmer errors trigger panics. These are should be fixed by the programmer +// before releasing code that uses gcfg. +// +// Data errors cause gcfg to return a non-nil error value. This includes the +// case when there are extra unknown key-value definitions in the configuration +// data (extra data). +// However, in some occasions it is desirable to be able to proceed in +// situations when the only data error is that of extra data. +// These errors are handled at a different (warning) priority and can be +// filtered out programmatically. To ignore extra data warnings, wrap the +// gcfg.Read*Into invocation into a call to gcfg.FatalOnly. +// +// TODO +// +// The following is a list of changes under consideration: +// - documentation +// - self-contained syntax documentation +// - more practical examples +// - move TODOs to issue tracker (eventually) +// - syntax +// - reconsider valid escape sequences +// (gitconfig doesn't support \r in value, \t in subsection name, etc.) +// - reading / parsing gcfg files +// - define internal representation structure +// - support multiple inputs (readers, strings, files) +// - support declaring encoding (?) +// - support varying fields sets for subsections (?) +// - writing gcfg files +// - error handling +// - make error context accessible programmatically? +// - limit input size? +// +package gcfg // import "github.com/go-git/gcfg" diff --git a/vendor/github.com/go-git/gcfg/errors.go b/vendor/github.com/go-git/gcfg/errors.go new file mode 100644 index 0000000000..853c76021d --- /dev/null +++ b/vendor/github.com/go-git/gcfg/errors.go @@ -0,0 +1,41 @@ +package gcfg + +import ( + "gopkg.in/warnings.v0" +) + +// FatalOnly filters the results of a Read*Into invocation and returns only +// fatal errors. That is, errors (warnings) indicating data for unknown +// sections / variables is ignored. Example invocation: +// +// err := gcfg.FatalOnly(gcfg.ReadFileInto(&cfg, configFile)) +// if err != nil { +// ... +// +func FatalOnly(err error) error { + return warnings.FatalOnly(err) +} + +func isFatal(err error) bool { + _, ok := err.(extraData) + return !ok +} + +type extraData struct { + section string + subsection *string + variable *string +} + +func (e extraData) Error() string { + s := "can't store data at section \"" + e.section + "\"" + if e.subsection != nil { + s += ", subsection \"" + *e.subsection + "\"" + } + if e.variable != nil { + s += ", variable \"" + *e.variable + "\"" + } + return s +} + +var _ error = extraData{} diff --git a/vendor/github.com/go-git/gcfg/read.go b/vendor/github.com/go-git/gcfg/read.go new file mode 100644 index 0000000000..ea5d2edd06 --- /dev/null +++ b/vendor/github.com/go-git/gcfg/read.go @@ -0,0 +1,273 @@ +package gcfg + +import ( + "fmt" + "io" + "os" + "strings" + + "gopkg.in/warnings.v0" + + "github.com/go-git/gcfg/scanner" + "github.com/go-git/gcfg/token" +) + +var unescape = map[rune]rune{'\\': '\\', '"': '"', 'n': '\n', 't': '\t', 'b': '\b', '\n': '\n'} + +// no error: invalid literals should be caught by scanner +func unquote(s string) string { + u, q, esc := make([]rune, 0, len(s)), false, false + for _, c := range s { + if esc { + uc, ok := unescape[c] + switch { + case ok: + u = append(u, uc) + fallthrough + case !q && c == '\n': + esc = false + continue + } + panic("invalid escape sequence") + } + switch c { + case '"': + q = !q + case '\\': + esc = true + default: + u = append(u, c) + } + } + if q { + panic("missing end quote") + } + if esc { + panic("invalid escape sequence") + } + return string(u) +} + +func read(c *warnings.Collector, callback func(string, string, string, string, bool) error, + fset *token.FileSet, file *token.File, src []byte) error { + // + var s scanner.Scanner + var errs scanner.ErrorList + s.Init(file, src, func(p token.Position, m string) { errs.Add(p, m) }, 0) + sect, sectsub := "", "" + pos, tok, lit := s.Scan() + errfn := func(msg string) error { + return fmt.Errorf("%s: %s", fset.Position(pos), msg) + } + for { + if errs.Len() > 0 { + if err := c.Collect(errs.Err()); err != nil { + return err + } + } + switch tok { + case token.EOF: + return nil + case token.EOL, token.COMMENT: + pos, tok, lit = s.Scan() + case token.LBRACK: + pos, tok, lit = s.Scan() + if errs.Len() > 0 { + if err := c.Collect(errs.Err()); err != nil { + return err + } + } + if tok != token.IDENT { + if err := c.Collect(errfn("expected section name")); err != nil { + return err + } + } + sect, sectsub = lit, "" + pos, tok, lit = s.Scan() + if errs.Len() > 0 { + if err := c.Collect(errs.Err()); err != nil { + return err + } + } + if tok == token.STRING { + sectsub = unquote(lit) + if sectsub == "" { + if err := c.Collect(errfn("empty subsection name")); err != nil { + return err + } + } + pos, tok, lit = s.Scan() + if errs.Len() > 0 { + if err := c.Collect(errs.Err()); err != nil { + return err + } + } + } + if tok != token.RBRACK { + if sectsub == "" { + if err := c.Collect(errfn("expected subsection name or right bracket")); err != nil { + return err + } + } + if err := c.Collect(errfn("expected right bracket")); err != nil { + return err + } + } + pos, tok, lit = s.Scan() + if tok != token.EOL && tok != token.EOF && tok != token.COMMENT { + if err := c.Collect(errfn("expected EOL, EOF, or comment")); err != nil { + return err + } + } + // If a section/subsection header was found, ensure a + // container object is created, even if there are no + // variables further down. + err := c.Collect(callback(sect, sectsub, "", "", true)) + if err != nil { + return err + } + case token.IDENT: + if sect == "" { + if err := c.Collect(errfn("expected section header")); err != nil { + return err + } + } + n := lit + pos, tok, lit = s.Scan() + if errs.Len() > 0 { + return errs.Err() + } + blank, v := tok == token.EOF || tok == token.EOL || tok == token.COMMENT, "" + if !blank { + if tok != token.ASSIGN { + if err := c.Collect(errfn("expected '='")); err != nil { + return err + } + } + pos, tok, lit = s.Scan() + if errs.Len() > 0 { + if err := c.Collect(errs.Err()); err != nil { + return err + } + } + if tok != token.STRING { + if err := c.Collect(errfn("expected value")); err != nil { + return err + } + } + v = unquote(lit) + pos, tok, lit = s.Scan() + if errs.Len() > 0 { + if err := c.Collect(errs.Err()); err != nil { + return err + } + } + if tok != token.EOL && tok != token.EOF && tok != token.COMMENT { + if err := c.Collect(errfn("expected EOL, EOF, or comment")); err != nil { + return err + } + } + } + err := c.Collect(callback(sect, sectsub, n, v, blank)) + if err != nil { + return err + } + default: + if sect == "" { + if err := c.Collect(errfn("expected section header")); err != nil { + return err + } + } + if err := c.Collect(errfn("expected section header or variable declaration")); err != nil { + return err + } + } + } + panic("never reached") +} + +func readInto(config interface{}, fset *token.FileSet, file *token.File, + src []byte) error { + // + c := warnings.NewCollector(isFatal) + firstPassCallback := func(s string, ss string, k string, v string, bv bool) error { + return set(c, config, s, ss, k, v, bv, false) + } + err := read(c, firstPassCallback, fset, file, src) + if err != nil { + return err + } + secondPassCallback := func(s string, ss string, k string, v string, bv bool) error { + return set(c, config, s, ss, k, v, bv, true) + } + err = read(c, secondPassCallback, fset, file, src) + if err != nil { + return err + } + return c.Done() +} + +// ReadWithCallback reads gcfg formatted data from reader and calls +// callback with each section and option found. +// +// Callback is called with section, subsection, option key, option value +// and blank value flag as arguments. +// +// When a section is found, callback is called with nil subsection, option key +// and option value. +// +// When a subsection is found, callback is called with nil option key and +// option value. +// +// If blank value flag is true, it means that the value was not set for an option +// (as opposed to set to empty string). +// +// If callback returns an error, ReadWithCallback terminates with an error too. +func ReadWithCallback(reader io.Reader, callback func(string, string, string, string, bool) error) error { + src, err := io.ReadAll(reader) + if err != nil { + return err + } + + fset := token.NewFileSet() + file := fset.AddFile("", fset.Base(), len(src)) + c := warnings.NewCollector(isFatal) + + return read(c, callback, fset, file, src) +} + +// ReadInto reads gcfg formatted data from reader and sets the values into the +// corresponding fields in config. +func ReadInto(config interface{}, reader io.Reader) error { + src, err := io.ReadAll(reader) + if err != nil { + return err + } + fset := token.NewFileSet() + file := fset.AddFile("", fset.Base(), len(src)) + return readInto(config, fset, file, src) +} + +// ReadStringInto reads gcfg formatted data from str and sets the values into +// the corresponding fields in config. +func ReadStringInto(config interface{}, str string) error { + r := strings.NewReader(str) + return ReadInto(config, r) +} + +// ReadFileInto reads gcfg formatted data from the file filename and sets the +// values into the corresponding fields in config. +func ReadFileInto(config interface{}, filename string) error { + f, err := os.Open(filename) + if err != nil { + return err + } + defer f.Close() + src, err := io.ReadAll(f) + if err != nil { + return err + } + fset := token.NewFileSet() + file := fset.AddFile(filename, fset.Base(), len(src)) + return readInto(config, fset, file, src) +} diff --git a/vendor/github.com/go-git/gcfg/scanner/errors.go b/vendor/github.com/go-git/gcfg/scanner/errors.go new file mode 100644 index 0000000000..a6e00f5c64 --- /dev/null +++ b/vendor/github.com/go-git/gcfg/scanner/errors.go @@ -0,0 +1,121 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package scanner + +import ( + "fmt" + "io" + "sort" +) + +import ( + "github.com/go-git/gcfg/token" +) + +// In an ErrorList, an error is represented by an *Error. +// The position Pos, if valid, points to the beginning of +// the offending token, and the error condition is described +// by Msg. +// +type Error struct { + Pos token.Position + Msg string +} + +// Error implements the error interface. +func (e Error) Error() string { + if e.Pos.Filename != "" || e.Pos.IsValid() { + // don't print "" + // TODO(gri) reconsider the semantics of Position.IsValid + return e.Pos.String() + ": " + e.Msg + } + return e.Msg +} + +// ErrorList is a list of *Errors. +// The zero value for an ErrorList is an empty ErrorList ready to use. +// +type ErrorList []*Error + +// Add adds an Error with given position and error message to an ErrorList. +func (p *ErrorList) Add(pos token.Position, msg string) { + *p = append(*p, &Error{pos, msg}) +} + +// Reset resets an ErrorList to no errors. +func (p *ErrorList) Reset() { *p = (*p)[0:0] } + +// ErrorList implements the sort Interface. +func (p ErrorList) Len() int { return len(p) } +func (p ErrorList) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func (p ErrorList) Less(i, j int) bool { + e := &p[i].Pos + f := &p[j].Pos + if e.Filename < f.Filename { + return true + } + if e.Filename == f.Filename { + return e.Offset < f.Offset + } + return false +} + +// Sort sorts an ErrorList. *Error entries are sorted by position, +// other errors are sorted by error message, and before any *Error +// entry. +// +func (p ErrorList) Sort() { + sort.Sort(p) +} + +// RemoveMultiples sorts an ErrorList and removes all but the first error per line. +func (p *ErrorList) RemoveMultiples() { + sort.Sort(p) + var last token.Position // initial last.Line is != any legal error line + i := 0 + for _, e := range *p { + if e.Pos.Filename != last.Filename || e.Pos.Line != last.Line { + last = e.Pos + (*p)[i] = e + i++ + } + } + (*p) = (*p)[0:i] +} + +// An ErrorList implements the error interface. +func (p ErrorList) Error() string { + switch len(p) { + case 0: + return "no errors" + case 1: + return p[0].Error() + } + return fmt.Sprintf("%s (and %d more errors)", p[0], len(p)-1) +} + +// Err returns an error equivalent to this error list. +// If the list is empty, Err returns nil. +func (p ErrorList) Err() error { + if len(p) == 0 { + return nil + } + return p +} + +// PrintError is a utility function that prints a list of errors to w, +// one error per line, if the err parameter is an ErrorList. Otherwise +// it prints the err string. +// +func PrintError(w io.Writer, err error) { + if list, ok := err.(ErrorList); ok { + for _, e := range list { + fmt.Fprintf(w, "%s\n", e) + } + } else if err != nil { + fmt.Fprintf(w, "%s\n", err) + } +} diff --git a/vendor/github.com/go-git/gcfg/scanner/scanner.go b/vendor/github.com/go-git/gcfg/scanner/scanner.go new file mode 100644 index 0000000000..b3da03d0eb --- /dev/null +++ b/vendor/github.com/go-git/gcfg/scanner/scanner.go @@ -0,0 +1,334 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package scanner implements a scanner for gcfg configuration text. +// It takes a []byte as source which can then be tokenized +// through repeated calls to the Scan method. +// +// Note that the API for the scanner package may change to accommodate new +// features or implementation changes in gcfg. +package scanner + +import ( + "fmt" + "path/filepath" + "unicode" + "unicode/utf8" + + "github.com/go-git/gcfg/token" +) + +// An ErrorHandler may be provided to Scanner.Init. If a syntax error is +// encountered and a handler was installed, the handler is called with a +// position and an error message. The position points to the beginning of +// the offending token. +type ErrorHandler func(pos token.Position, msg string) + +// A Scanner holds the scanner's internal state while processing +// a given text. It can be allocated as part of another data +// structure but must be initialized via Init before use. +type Scanner struct { + // immutable state + file *token.File // source file handle + dir string // directory portion of file.Name() + src []byte // source + err ErrorHandler // error reporting; or nil + mode Mode // scanning mode + + // scanning state + ch rune // current character + offset int // character offset + rdOffset int // reading offset (position after current character) + lineOffset int // current line offset + nextVal bool // next token is expected to be a value + + // public state - ok to modify + ErrorCount int // number of errors encountered +} + +// Read the next Unicode char into s.ch. +// s.ch < 0 means end-of-file. +func (s *Scanner) next() { + if s.rdOffset < len(s.src) { + s.offset = s.rdOffset + if s.ch == '\n' { + s.lineOffset = s.offset + s.file.AddLine(s.offset) + } + r, w := rune(s.src[s.rdOffset]), 1 + switch { + case r == 0: + s.error(s.offset, "illegal character NUL") + case r >= 0x80: + // not ASCII + r, w = utf8.DecodeRune(s.src[s.rdOffset:]) + if r == utf8.RuneError && w == 1 { + s.error(s.offset, "illegal UTF-8 encoding") + } + } + s.rdOffset += w + s.ch = r + } else { + s.offset = len(s.src) + if s.ch == '\n' { + s.lineOffset = s.offset + s.file.AddLine(s.offset) + } + s.ch = -1 // eof + } +} + +// A mode value is a set of flags (or 0). +// They control scanner behavior. +type Mode uint + +const ( + ScanComments Mode = 1 << iota // return comments as COMMENT tokens +) + +// Init prepares the scanner s to tokenize the text src by setting the +// scanner at the beginning of src. The scanner uses the file set file +// for position information and it adds line information for each line. +// It is ok to re-use the same file when re-scanning the same file as +// line information which is already present is ignored. Init causes a +// panic if the file size does not match the src size. +// +// Calls to Scan will invoke the error handler err if they encounter a +// syntax error and err is not nil. Also, for each error encountered, +// the Scanner field ErrorCount is incremented by one. The mode parameter +// determines how comments are handled. +// +// Note that Init may call err if there is an error in the first character +// of the file. +func (s *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode Mode) { + // Explicitly initialize all fields since a scanner may be reused. + if file.Size() != len(src) { + panic(fmt.Sprintf("file size (%d) does not match src len (%d)", file.Size(), len(src))) + } + s.file = file + s.dir, _ = filepath.Split(file.Name()) + s.src = src + s.err = err + s.mode = mode + + s.ch = ' ' + s.offset = 0 + s.rdOffset = 0 + s.lineOffset = 0 + s.ErrorCount = 0 + s.nextVal = false + + s.next() +} + +func (s *Scanner) error(offs int, msg string) { + if s.err != nil { + s.err(s.file.Position(s.file.Pos(offs)), msg) + } + s.ErrorCount++ +} + +func (s *Scanner) scanComment() string { + // initial [;#] already consumed + offs := s.offset - 1 // position of initial [;#] + + for s.ch != '\n' && s.ch >= 0 { + s.next() + } + return string(s.src[offs:s.offset]) +} + +func isLetter(ch rune) bool { + return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch >= 0x80 && unicode.IsLetter(ch) +} + +func isDigit(ch rune) bool { + return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch) +} + +func (s *Scanner) scanIdentifier() string { + offs := s.offset + for isLetter(s.ch) || isDigit(s.ch) || s.ch == '-' { + s.next() + } + return string(s.src[offs:s.offset]) +} + +// val indicate if we are scanning a value (vs a header) +func (s *Scanner) scanEscape(val bool) { + offs := s.offset + ch := s.ch + s.next() // always make progress + switch ch { + case '\\', '"', '\n': + // ok + case 'n', 't', 'b': + if val { + break // ok + } + fallthrough + default: + s.error(offs, "unknown escape sequence") + } +} + +func (s *Scanner) scanString() string { + // '"' opening already consumed + offs := s.offset - 1 + + for s.ch != '"' { + ch := s.ch + s.next() + if ch == '\n' || ch < 0 { + s.error(offs, "string not terminated") + break + } + if ch == '\\' { + s.scanEscape(false) + } + } + + s.next() + + return string(s.src[offs:s.offset]) +} + +func stripCR(b []byte) []byte { + c := make([]byte, len(b)) + i := 0 + for _, ch := range b { + if ch != '\r' { + c[i] = ch + i++ + } + } + return c[:i] +} + +func (s *Scanner) scanValString() string { + offs := s.offset + + hasCR := false + end := offs + inQuote := false +loop: + for inQuote || s.ch >= 0 && s.ch != '\n' && s.ch != ';' && s.ch != '#' { + ch := s.ch + s.next() + switch { + case inQuote && ch == '\\': + s.scanEscape(true) + case !inQuote && ch == '\\': + if s.ch == '\r' { + hasCR = true + s.next() + } + if s.ch != '\n' { + s.scanEscape(true) + } else { + s.next() + } + case ch == '"': + inQuote = !inQuote + case ch == '\r': + hasCR = true + case ch < 0 || inQuote && ch == '\n': + s.error(offs, "string not terminated") + break loop + } + if inQuote || !isWhiteSpace(ch) { + end = s.offset + } + } + + lit := s.src[offs:end] + if hasCR { + lit = stripCR(lit) + } + + return string(lit) +} + +func isWhiteSpace(ch rune) bool { + return ch == ' ' || ch == '\t' || ch == '\r' +} + +func (s *Scanner) skipWhitespace() { + for isWhiteSpace(s.ch) { + s.next() + } +} + +// Scan scans the next token and returns the token position, the token, +// and its literal string if applicable. The source end is indicated by +// token.EOF. +// +// If the returned token is a literal (token.IDENT, token.STRING) or +// token.COMMENT, the literal string has the corresponding value. +// +// If the returned token is token.ILLEGAL, the literal string is the +// offending character. +// +// In all other cases, Scan returns an empty literal string. +// +// For more tolerant parsing, Scan will return a valid token if +// possible even if a syntax error was encountered. Thus, even +// if the resulting token sequence contains no illegal tokens, +// a client may not assume that no error occurred. Instead it +// must check the scanner's ErrorCount or the number of calls +// of the error handler, if there was one installed. +// +// Scan adds line information to the file added to the file +// set with Init. Token positions are relative to that file +// and thus relative to the file set. +func (s *Scanner) Scan() (pos token.Pos, tok token.Token, lit string) { +scanAgain: + s.skipWhitespace() + + // current token start + pos = s.file.Pos(s.offset) + + // determine token value + switch ch := s.ch; { + case s.nextVal: + lit = s.scanValString() + tok = token.STRING + s.nextVal = false + case isLetter(ch): + lit = s.scanIdentifier() + tok = token.IDENT + default: + s.next() // always make progress + switch ch { + case -1: + tok = token.EOF + case '\n': + tok = token.EOL + case '"': + tok = token.STRING + lit = s.scanString() + case '[': + tok = token.LBRACK + case ']': + tok = token.RBRACK + case ';', '#': + // comment + lit = s.scanComment() + if s.mode&ScanComments == 0 { + // skip comment + goto scanAgain + } + tok = token.COMMENT + case '=': + tok = token.ASSIGN + s.nextVal = true + default: + s.error(s.file.Offset(pos), fmt.Sprintf("illegal character %#U", ch)) + tok = token.ILLEGAL + lit = string(ch) + } + } + + return +} diff --git a/vendor/github.com/go-git/gcfg/set.go b/vendor/github.com/go-git/gcfg/set.go new file mode 100644 index 0000000000..dc9795dbdb --- /dev/null +++ b/vendor/github.com/go-git/gcfg/set.go @@ -0,0 +1,334 @@ +package gcfg + +import ( + "bytes" + "encoding" + "encoding/gob" + "fmt" + "math/big" + "reflect" + "strings" + "unicode" + "unicode/utf8" + + "gopkg.in/warnings.v0" + + "github.com/go-git/gcfg/types" +) + +type tag struct { + ident string + intMode string +} + +func newTag(ts string) tag { + t := tag{} + s := strings.Split(ts, ",") + t.ident = s[0] + for _, tse := range s[1:] { + if strings.HasPrefix(tse, "int=") { + t.intMode = tse[len("int="):] + } + } + return t +} + +func fieldFold(v reflect.Value, name string) (reflect.Value, tag) { + var n string + r0, _ := utf8.DecodeRuneInString(name) + if unicode.IsLetter(r0) && !unicode.IsLower(r0) && !unicode.IsUpper(r0) { + n = "X" + } + n += strings.Replace(name, "-", "_", -1) + f, ok := v.Type().FieldByNameFunc(func(fieldName string) bool { + if !v.FieldByName(fieldName).CanSet() { + return false + } + f, _ := v.Type().FieldByName(fieldName) + t := newTag(f.Tag.Get("gcfg")) + if t.ident != "" { + return strings.EqualFold(t.ident, name) + } + return strings.EqualFold(n, fieldName) + }) + if !ok { + return reflect.Value{}, tag{} + } + return v.FieldByName(f.Name), newTag(f.Tag.Get("gcfg")) +} + +type setter func(destp interface{}, blank bool, val string, t tag) error + +var errUnsupportedType = fmt.Errorf("unsupported type") +var errBlankUnsupported = fmt.Errorf("blank value not supported for type") + +var setters = []setter{ + typeSetter, textUnmarshalerSetter, kindSetter, scanSetter, +} + +func textUnmarshalerSetter(d interface{}, blank bool, val string, t tag) error { + dtu, ok := d.(encoding.TextUnmarshaler) + if !ok { + return errUnsupportedType + } + if blank { + return errBlankUnsupported + } + return dtu.UnmarshalText([]byte(val)) +} + +func boolSetter(d interface{}, blank bool, val string, t tag) error { + if blank { + reflect.ValueOf(d).Elem().Set(reflect.ValueOf(true)) + return nil + } + b, err := types.ParseBool(val) + if err == nil { + reflect.ValueOf(d).Elem().Set(reflect.ValueOf(b)) + } + return err +} + +func intMode(mode string) types.IntMode { + var m types.IntMode + if strings.ContainsAny(mode, "dD") { + m |= types.Dec + } + if strings.ContainsAny(mode, "hH") { + m |= types.Hex + } + if strings.ContainsAny(mode, "oO") { + m |= types.Oct + } + return m +} + +var typeModes = map[reflect.Type]types.IntMode{ + reflect.TypeOf(int(0)): types.Dec | types.Hex, + reflect.TypeOf(int8(0)): types.Dec | types.Hex, + reflect.TypeOf(int16(0)): types.Dec | types.Hex, + reflect.TypeOf(int32(0)): types.Dec | types.Hex, + reflect.TypeOf(int64(0)): types.Dec | types.Hex, + reflect.TypeOf(uint(0)): types.Dec | types.Hex, + reflect.TypeOf(uint8(0)): types.Dec | types.Hex, + reflect.TypeOf(uint16(0)): types.Dec | types.Hex, + reflect.TypeOf(uint32(0)): types.Dec | types.Hex, + reflect.TypeOf(uint64(0)): types.Dec | types.Hex, + // use default mode (allow dec/hex/oct) for uintptr type + reflect.TypeOf(big.Int{}): types.Dec | types.Hex, +} + +func intModeDefault(t reflect.Type) types.IntMode { + m, ok := typeModes[t] + if !ok { + m = types.Dec | types.Hex | types.Oct + } + return m +} + +func intSetter(d interface{}, blank bool, val string, t tag) error { + if blank { + return errBlankUnsupported + } + mode := intMode(t.intMode) + if mode == 0 { + mode = intModeDefault(reflect.TypeOf(d).Elem()) + } + return types.ParseInt(d, val, mode) +} + +func stringSetter(d interface{}, blank bool, val string, t tag) error { + if blank { + return errBlankUnsupported + } + dsp, ok := d.(*string) + if !ok { + return errUnsupportedType + } + *dsp = val + return nil +} + +var kindSetters = map[reflect.Kind]setter{ + reflect.String: stringSetter, + reflect.Bool: boolSetter, + reflect.Int: intSetter, + reflect.Int8: intSetter, + reflect.Int16: intSetter, + reflect.Int32: intSetter, + reflect.Int64: intSetter, + reflect.Uint: intSetter, + reflect.Uint8: intSetter, + reflect.Uint16: intSetter, + reflect.Uint32: intSetter, + reflect.Uint64: intSetter, + reflect.Uintptr: intSetter, +} + +var typeSetters = map[reflect.Type]setter{ + reflect.TypeOf(big.Int{}): intSetter, +} + +func typeSetter(d interface{}, blank bool, val string, tt tag) error { + t := reflect.ValueOf(d).Type().Elem() + setter, ok := typeSetters[t] + if !ok { + return errUnsupportedType + } + return setter(d, blank, val, tt) +} + +func kindSetter(d interface{}, blank bool, val string, tt tag) error { + k := reflect.ValueOf(d).Type().Elem().Kind() + setter, ok := kindSetters[k] + if !ok { + return errUnsupportedType + } + return setter(d, blank, val, tt) +} + +func scanSetter(d interface{}, blank bool, val string, tt tag) error { + if blank { + return errBlankUnsupported + } + return types.ScanFully(d, val, 'v') +} + +func newValue(c *warnings.Collector, sect string, vCfg reflect.Value, + vType reflect.Type) (reflect.Value, error) { + // + pv := reflect.New(vType) + dfltName := "default-" + sect + dfltField, _ := fieldFold(vCfg, dfltName) + var err error + if dfltField.IsValid() { + b := bytes.NewBuffer(nil) + ge := gob.NewEncoder(b) + if err = c.Collect(ge.EncodeValue(dfltField)); err != nil { + return pv, err + } + gd := gob.NewDecoder(bytes.NewReader(b.Bytes())) + if err = c.Collect(gd.DecodeValue(pv.Elem())); err != nil { + return pv, err + } + } + return pv, nil +} + +func set(c *warnings.Collector, cfg interface{}, sect, sub, name string, + value string, blankValue bool, subsectPass bool) error { + // + vPCfg := reflect.ValueOf(cfg) + if vPCfg.Kind() != reflect.Ptr || vPCfg.Elem().Kind() != reflect.Struct { + panic(fmt.Errorf("config must be a pointer to a struct")) + } + vCfg := vPCfg.Elem() + vSect, _ := fieldFold(vCfg, sect) + if !vSect.IsValid() { + err := extraData{section: sect} + return c.Collect(err) + } + isSubsect := vSect.Kind() == reflect.Map + if subsectPass != isSubsect { + return nil + } + if isSubsect { + vst := vSect.Type() + if vst.Key().Kind() != reflect.String || + vst.Elem().Kind() != reflect.Ptr || + vst.Elem().Elem().Kind() != reflect.Struct { + panic(fmt.Errorf("map field for section must have string keys and "+ + " pointer-to-struct values: section %q", sect)) + } + if vSect.IsNil() { + vSect.Set(reflect.MakeMap(vst)) + } + k := reflect.ValueOf(sub) + pv := vSect.MapIndex(k) + if !pv.IsValid() { + vType := vSect.Type().Elem().Elem() + var err error + if pv, err = newValue(c, sect, vCfg, vType); err != nil { + return err + } + vSect.SetMapIndex(k, pv) + } + vSect = pv.Elem() + } else if vSect.Kind() != reflect.Struct { + panic(fmt.Errorf("field for section must be a map or a struct: "+ + "section %q", sect)) + } else if sub != "" { + err := extraData{section: sect, subsection: &sub} + return c.Collect(err) + } + // Empty name is a special value, meaning that only the + // section/subsection object is to be created, with no values set. + if name == "" { + return nil + } + vVar, t := fieldFold(vSect, name) + if !vVar.IsValid() { + var err error + if isSubsect { + err = extraData{section: sect, subsection: &sub, variable: &name} + } else { + err = extraData{section: sect, variable: &name} + } + return c.Collect(err) + } + // vVal is either single-valued var, or newly allocated value within multi-valued var + var vVal reflect.Value + // multi-value if unnamed slice type + isMulti := vVar.Type().Name() == "" && vVar.Kind() == reflect.Slice || + vVar.Type().Name() == "" && vVar.Kind() == reflect.Ptr && vVar.Type().Elem().Name() == "" && vVar.Type().Elem().Kind() == reflect.Slice + if isMulti && vVar.Kind() == reflect.Ptr { + if vVar.IsNil() { + vVar.Set(reflect.New(vVar.Type().Elem())) + } + vVar = vVar.Elem() + } + if isMulti && blankValue { + vVar.Set(reflect.Zero(vVar.Type())) + return nil + } + if isMulti { + vVal = reflect.New(vVar.Type().Elem()).Elem() + } else { + vVal = vVar + } + isDeref := vVal.Type().Name() == "" && vVal.Type().Kind() == reflect.Ptr + isNew := isDeref && vVal.IsNil() + // vAddr is address of value to set (dereferenced & allocated as needed) + var vAddr reflect.Value + switch { + case isNew: + vAddr = reflect.New(vVal.Type().Elem()) + case isDeref && !isNew: + vAddr = vVal + default: + vAddr = vVal.Addr() + } + vAddrI := vAddr.Interface() + err, ok := error(nil), false + for _, s := range setters { + err = s(vAddrI, blankValue, value, t) + if err == nil { + ok = true + break + } + if err != errUnsupportedType { + return err + } + } + if !ok { + // in case all setters returned errUnsupportedType + return err + } + if isNew { // set reference if it was dereferenced and newly allocated + vVal.Set(vAddr) + } + if isMulti { // append if multi-valued + vVar.Set(reflect.Append(vVar, vVal)) + } + return nil +} diff --git a/vendor/github.com/go-git/gcfg/token/position.go b/vendor/github.com/go-git/gcfg/token/position.go new file mode 100644 index 0000000000..fc45c1e769 --- /dev/null +++ b/vendor/github.com/go-git/gcfg/token/position.go @@ -0,0 +1,435 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// TODO(gri) consider making this a separate package outside the go directory. + +package token + +import ( + "fmt" + "sort" + "sync" +) + +// ----------------------------------------------------------------------------- +// Positions + +// Position describes an arbitrary source position +// including the file, line, and column location. +// A Position is valid if the line number is > 0. +// +type Position struct { + Filename string // filename, if any + Offset int // offset, starting at 0 + Line int // line number, starting at 1 + Column int // column number, starting at 1 (character count) +} + +// IsValid returns true if the position is valid. +func (pos *Position) IsValid() bool { return pos.Line > 0 } + +// String returns a string in one of several forms: +// +// file:line:column valid position with file name +// line:column valid position without file name +// file invalid position with file name +// - invalid position without file name +// +func (pos Position) String() string { + s := pos.Filename + if pos.IsValid() { + if s != "" { + s += ":" + } + s += fmt.Sprintf("%d:%d", pos.Line, pos.Column) + } + if s == "" { + s = "-" + } + return s +} + +// Pos is a compact encoding of a source position within a file set. +// It can be converted into a Position for a more convenient, but much +// larger, representation. +// +// The Pos value for a given file is a number in the range [base, base+size], +// where base and size are specified when adding the file to the file set via +// AddFile. +// +// To create the Pos value for a specific source offset, first add +// the respective file to the current file set (via FileSet.AddFile) +// and then call File.Pos(offset) for that file. Given a Pos value p +// for a specific file set fset, the corresponding Position value is +// obtained by calling fset.Position(p). +// +// Pos values can be compared directly with the usual comparison operators: +// If two Pos values p and q are in the same file, comparing p and q is +// equivalent to comparing the respective source file offsets. If p and q +// are in different files, p < q is true if the file implied by p was added +// to the respective file set before the file implied by q. +// +type Pos int + +// The zero value for Pos is NoPos; there is no file and line information +// associated with it, and NoPos().IsValid() is false. NoPos is always +// smaller than any other Pos value. The corresponding Position value +// for NoPos is the zero value for Position. +// +const NoPos Pos = 0 + +// IsValid returns true if the position is valid. +func (p Pos) IsValid() bool { + return p != NoPos +} + +// ----------------------------------------------------------------------------- +// File + +// A File is a handle for a file belonging to a FileSet. +// A File has a name, size, and line offset table. +// +type File struct { + set *FileSet + name string // file name as provided to AddFile + base int // Pos value range for this file is [base...base+size] + size int // file size as provided to AddFile + + // lines and infos are protected by set.mutex + lines []int + infos []lineInfo +} + +// Name returns the file name of file f as registered with AddFile. +func (f *File) Name() string { + return f.name +} + +// Base returns the base offset of file f as registered with AddFile. +func (f *File) Base() int { + return f.base +} + +// Size returns the size of file f as registered with AddFile. +func (f *File) Size() int { + return f.size +} + +// LineCount returns the number of lines in file f. +func (f *File) LineCount() int { + f.set.mutex.RLock() + n := len(f.lines) + f.set.mutex.RUnlock() + return n +} + +// AddLine adds the line offset for a new line. +// The line offset must be larger than the offset for the previous line +// and smaller than the file size; otherwise the line offset is ignored. +// +func (f *File) AddLine(offset int) { + f.set.mutex.Lock() + if i := len(f.lines); (i == 0 || f.lines[i-1] < offset) && offset < f.size { + f.lines = append(f.lines, offset) + } + f.set.mutex.Unlock() +} + +// SetLines sets the line offsets for a file and returns true if successful. +// The line offsets are the offsets of the first character of each line; +// for instance for the content "ab\nc\n" the line offsets are {0, 3}. +// An empty file has an empty line offset table. +// Each line offset must be larger than the offset for the previous line +// and smaller than the file size; otherwise SetLines fails and returns +// false. +// +func (f *File) SetLines(lines []int) bool { + // verify validity of lines table + size := f.size + for i, offset := range lines { + if i > 0 && offset <= lines[i-1] || size <= offset { + return false + } + } + + // set lines table + f.set.mutex.Lock() + f.lines = lines + f.set.mutex.Unlock() + return true +} + +// SetLinesForContent sets the line offsets for the given file content. +func (f *File) SetLinesForContent(content []byte) { + var lines []int + line := 0 + for offset, b := range content { + if line >= 0 { + lines = append(lines, line) + } + line = -1 + if b == '\n' { + line = offset + 1 + } + } + + // set lines table + f.set.mutex.Lock() + f.lines = lines + f.set.mutex.Unlock() +} + +// A lineInfo object describes alternative file and line number +// information (such as provided via a //line comment in a .go +// file) for a given file offset. +type lineInfo struct { + // fields are exported to make them accessible to gob + Offset int + Filename string + Line int +} + +// AddLineInfo adds alternative file and line number information for +// a given file offset. The offset must be larger than the offset for +// the previously added alternative line info and smaller than the +// file size; otherwise the information is ignored. +// +// AddLineInfo is typically used to register alternative position +// information for //line filename:line comments in source files. +// +func (f *File) AddLineInfo(offset int, filename string, line int) { + f.set.mutex.Lock() + if i := len(f.infos); i == 0 || f.infos[i-1].Offset < offset && offset < f.size { + f.infos = append(f.infos, lineInfo{offset, filename, line}) + } + f.set.mutex.Unlock() +} + +// Pos returns the Pos value for the given file offset; +// the offset must be <= f.Size(). +// f.Pos(f.Offset(p)) == p. +// +func (f *File) Pos(offset int) Pos { + if offset > f.size { + panic("illegal file offset") + } + return Pos(f.base + offset) +} + +// Offset returns the offset for the given file position p; +// p must be a valid Pos value in that file. +// f.Offset(f.Pos(offset)) == offset. +// +func (f *File) Offset(p Pos) int { + if int(p) < f.base || int(p) > f.base+f.size { + panic("illegal Pos value") + } + return int(p) - f.base +} + +// Line returns the line number for the given file position p; +// p must be a Pos value in that file or NoPos. +// +func (f *File) Line(p Pos) int { + // TODO(gri) this can be implemented much more efficiently + return f.Position(p).Line +} + +func searchLineInfos(a []lineInfo, x int) int { + return sort.Search(len(a), func(i int) bool { return a[i].Offset > x }) - 1 +} + +// info returns the file name, line, and column number for a file offset. +func (f *File) info(offset int) (filename string, line, column int) { + filename = f.name + if i := searchInts(f.lines, offset); i >= 0 { + line, column = i+1, offset-f.lines[i]+1 + } + if len(f.infos) > 0 { + // almost no files have extra line infos + if i := searchLineInfos(f.infos, offset); i >= 0 { + alt := &f.infos[i] + filename = alt.Filename + if i := searchInts(f.lines, alt.Offset); i >= 0 { + line += alt.Line - i - 1 + } + } + } + return +} + +func (f *File) position(p Pos) (pos Position) { + offset := int(p) - f.base + pos.Offset = offset + pos.Filename, pos.Line, pos.Column = f.info(offset) + return +} + +// Position returns the Position value for the given file position p; +// p must be a Pos value in that file or NoPos. +// +func (f *File) Position(p Pos) (pos Position) { + if p != NoPos { + if int(p) < f.base || int(p) > f.base+f.size { + panic("illegal Pos value") + } + pos = f.position(p) + } + return +} + +// ----------------------------------------------------------------------------- +// FileSet + +// A FileSet represents a set of source files. +// Methods of file sets are synchronized; multiple goroutines +// may invoke them concurrently. +// +type FileSet struct { + mutex sync.RWMutex // protects the file set + base int // base offset for the next file + files []*File // list of files in the order added to the set + last *File // cache of last file looked up +} + +// NewFileSet creates a new file set. +func NewFileSet() *FileSet { + s := new(FileSet) + s.base = 1 // 0 == NoPos + return s +} + +// Base returns the minimum base offset that must be provided to +// AddFile when adding the next file. +// +func (s *FileSet) Base() int { + s.mutex.RLock() + b := s.base + s.mutex.RUnlock() + return b + +} + +// AddFile adds a new file with a given filename, base offset, and file size +// to the file set s and returns the file. Multiple files may have the same +// name. The base offset must not be smaller than the FileSet's Base(), and +// size must not be negative. +// +// Adding the file will set the file set's Base() value to base + size + 1 +// as the minimum base value for the next file. The following relationship +// exists between a Pos value p for a given file offset offs: +// +// int(p) = base + offs +// +// with offs in the range [0, size] and thus p in the range [base, base+size]. +// For convenience, File.Pos may be used to create file-specific position +// values from a file offset. +// +func (s *FileSet) AddFile(filename string, base, size int) *File { + s.mutex.Lock() + defer s.mutex.Unlock() + if base < s.base || size < 0 { + panic("illegal base or size") + } + // base >= s.base && size >= 0 + f := &File{s, filename, base, size, []int{0}, nil} + base += size + 1 // +1 because EOF also has a position + if base < 0 { + panic("token.Pos offset overflow (> 2G of source code in file set)") + } + // add the file to the file set + s.base = base + s.files = append(s.files, f) + s.last = f + return f +} + +// Iterate calls f for the files in the file set in the order they were added +// until f returns false. +// +func (s *FileSet) Iterate(f func(*File) bool) { + for i := 0; ; i++ { + var file *File + s.mutex.RLock() + if i < len(s.files) { + file = s.files[i] + } + s.mutex.RUnlock() + if file == nil || !f(file) { + break + } + } +} + +func searchFiles(a []*File, x int) int { + return sort.Search(len(a), func(i int) bool { return a[i].base > x }) - 1 +} + +func (s *FileSet) file(p Pos) *File { + // common case: p is in last file + if f := s.last; f != nil && f.base <= int(p) && int(p) <= f.base+f.size { + return f + } + // p is not in last file - search all files + if i := searchFiles(s.files, int(p)); i >= 0 { + f := s.files[i] + // f.base <= int(p) by definition of searchFiles + if int(p) <= f.base+f.size { + s.last = f + return f + } + } + return nil +} + +// File returns the file that contains the position p. +// If no such file is found (for instance for p == NoPos), +// the result is nil. +// +func (s *FileSet) File(p Pos) (f *File) { + if p != NoPos { + s.mutex.RLock() + f = s.file(p) + s.mutex.RUnlock() + } + return +} + +// Position converts a Pos in the fileset into a general Position. +func (s *FileSet) Position(p Pos) (pos Position) { + if p != NoPos { + s.mutex.RLock() + if f := s.file(p); f != nil { + pos = f.position(p) + } + s.mutex.RUnlock() + } + return +} + +// ----------------------------------------------------------------------------- +// Helper functions + +func searchInts(a []int, x int) int { + // This function body is a manually inlined version of: + // + // return sort.Search(len(a), func(i int) bool { return a[i] > x }) - 1 + // + // With better compiler optimizations, this may not be needed in the + // future, but at the moment this change improves the go/printer + // benchmark performance by ~30%. This has a direct impact on the + // speed of gofmt and thus seems worthwhile (2011-04-29). + // TODO(gri): Remove this when compilers have caught up. + i, j := 0, len(a) + for i < j { + h := i + (j-i)/2 // avoid overflow when computing h + // i ≤ h < j + if a[h] <= x { + i = h + 1 + } else { + j = h + } + } + return i - 1 +} diff --git a/vendor/github.com/go-git/gcfg/token/serialize.go b/vendor/github.com/go-git/gcfg/token/serialize.go new file mode 100644 index 0000000000..4adc8f9e33 --- /dev/null +++ b/vendor/github.com/go-git/gcfg/token/serialize.go @@ -0,0 +1,56 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package token + +type serializedFile struct { + // fields correspond 1:1 to fields with same (lower-case) name in File + Name string + Base int + Size int + Lines []int + Infos []lineInfo +} + +type serializedFileSet struct { + Base int + Files []serializedFile +} + +// Read calls decode to deserialize a file set into s; s must not be nil. +func (s *FileSet) Read(decode func(interface{}) error) error { + var ss serializedFileSet + if err := decode(&ss); err != nil { + return err + } + + s.mutex.Lock() + s.base = ss.Base + files := make([]*File, len(ss.Files)) + for i := 0; i < len(ss.Files); i++ { + f := &ss.Files[i] + files[i] = &File{s, f.Name, f.Base, f.Size, f.Lines, f.Infos} + } + s.files = files + s.last = nil + s.mutex.Unlock() + + return nil +} + +// Write calls encode to serialize the file set s. +func (s *FileSet) Write(encode func(interface{}) error) error { + var ss serializedFileSet + + s.mutex.Lock() + ss.Base = s.base + files := make([]serializedFile, len(s.files)) + for i, f := range s.files { + files[i] = serializedFile{f.name, f.base, f.size, f.lines, f.infos} + } + ss.Files = files + s.mutex.Unlock() + + return encode(ss) +} diff --git a/vendor/github.com/go-git/gcfg/token/token.go b/vendor/github.com/go-git/gcfg/token/token.go new file mode 100644 index 0000000000..b3c7c83fa9 --- /dev/null +++ b/vendor/github.com/go-git/gcfg/token/token.go @@ -0,0 +1,83 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package token defines constants representing the lexical tokens of the gcfg +// configuration syntax and basic operations on tokens (printing, predicates). +// +// Note that the API for the token package may change to accommodate new +// features or implementation changes in gcfg. +// +package token + +import "strconv" + +// Token is the set of lexical tokens of the gcfg configuration syntax. +type Token int + +// The list of tokens. +const ( + // Special tokens + ILLEGAL Token = iota + EOF + COMMENT + + literal_beg + // Identifiers and basic type literals + // (these tokens stand for classes of literals) + IDENT // section-name, variable-name + STRING // "subsection-name", variable value + literal_end + + operator_beg + // Operators and delimiters + ASSIGN // = + LBRACK // [ + RBRACK // ] + EOL // \n + operator_end +) + +var tokens = [...]string{ + ILLEGAL: "ILLEGAL", + + EOF: "EOF", + COMMENT: "COMMENT", + + IDENT: "IDENT", + STRING: "STRING", + + ASSIGN: "=", + LBRACK: "[", + RBRACK: "]", + EOL: "\n", +} + +// String returns the string corresponding to the token tok. +// For operators and delimiters, the string is the actual token character +// sequence (e.g., for the token ASSIGN, the string is "="). For all other +// tokens the string corresponds to the token constant name (e.g. for the +// token IDENT, the string is "IDENT"). +// +func (tok Token) String() string { + s := "" + if 0 <= tok && tok < Token(len(tokens)) { + s = tokens[tok] + } + if s == "" { + s = "token(" + strconv.Itoa(int(tok)) + ")" + } + return s +} + +// Predicates + +// IsLiteral returns true for tokens corresponding to identifiers +// and basic type literals; it returns false otherwise. +// +func (tok Token) IsLiteral() bool { return literal_beg < tok && tok < literal_end } + +// IsOperator returns true for tokens corresponding to operators and +// delimiters; it returns false otherwise. +// +func (tok Token) IsOperator() bool { return operator_beg < tok && tok < operator_end } diff --git a/vendor/github.com/go-git/gcfg/types/bool.go b/vendor/github.com/go-git/gcfg/types/bool.go new file mode 100644 index 0000000000..8dcae0d8cf --- /dev/null +++ b/vendor/github.com/go-git/gcfg/types/bool.go @@ -0,0 +1,23 @@ +package types + +// BoolValues defines the name and value mappings for ParseBool. +var BoolValues = map[string]interface{}{ + "true": true, "yes": true, "on": true, "1": true, + "false": false, "no": false, "off": false, "0": false, +} + +var boolParser = func() *EnumParser { + ep := &EnumParser{} + ep.AddVals(BoolValues) + return ep +}() + +// ParseBool parses bool values according to the definitions in BoolValues. +// Parsing is case-insensitive. +func ParseBool(s string) (bool, error) { + v, err := boolParser.Parse(s) + if err != nil { + return false, err + } + return v.(bool), nil +} diff --git a/vendor/github.com/go-git/gcfg/types/doc.go b/vendor/github.com/go-git/gcfg/types/doc.go new file mode 100644 index 0000000000..9f9c345f6e --- /dev/null +++ b/vendor/github.com/go-git/gcfg/types/doc.go @@ -0,0 +1,4 @@ +// Package types defines helpers for type conversions. +// +// The API for this package is not finalized yet. +package types diff --git a/vendor/github.com/go-git/gcfg/types/enum.go b/vendor/github.com/go-git/gcfg/types/enum.go new file mode 100644 index 0000000000..1a0c7ef453 --- /dev/null +++ b/vendor/github.com/go-git/gcfg/types/enum.go @@ -0,0 +1,44 @@ +package types + +import ( + "fmt" + "reflect" + "strings" +) + +// EnumParser parses "enum" values; i.e. a predefined set of strings to +// predefined values. +type EnumParser struct { + Type string // type name; if not set, use type of first value added + CaseMatch bool // if true, matching of strings is case-sensitive + // PrefixMatch bool + vals map[string]interface{} +} + +// AddVals adds strings and values to an EnumParser. +func (ep *EnumParser) AddVals(vals map[string]interface{}) { + if ep.vals == nil { + ep.vals = make(map[string]interface{}) + } + for k, v := range vals { + if ep.Type == "" { + ep.Type = reflect.TypeOf(v).Name() + } + if !ep.CaseMatch { + k = strings.ToLower(k) + } + ep.vals[k] = v + } +} + +// Parse parses the string and returns the value or an error. +func (ep EnumParser) Parse(s string) (interface{}, error) { + if !ep.CaseMatch { + s = strings.ToLower(s) + } + v, ok := ep.vals[s] + if !ok { + return false, fmt.Errorf("failed to parse %s %#q", ep.Type, s) + } + return v, nil +} diff --git a/vendor/github.com/go-git/gcfg/types/int.go b/vendor/github.com/go-git/gcfg/types/int.go new file mode 100644 index 0000000000..af7e75c125 --- /dev/null +++ b/vendor/github.com/go-git/gcfg/types/int.go @@ -0,0 +1,86 @@ +package types + +import ( + "fmt" + "strings" +) + +// An IntMode is a mode for parsing integer values, representing a set of +// accepted bases. +type IntMode uint8 + +// IntMode values for ParseInt; can be combined using binary or. +const ( + Dec IntMode = 1 << iota + Hex + Oct +) + +// String returns a string representation of IntMode; e.g. `IntMode(Dec|Hex)`. +func (m IntMode) String() string { + var modes []string + if m&Dec != 0 { + modes = append(modes, "Dec") + } + if m&Hex != 0 { + modes = append(modes, "Hex") + } + if m&Oct != 0 { + modes = append(modes, "Oct") + } + return "IntMode(" + strings.Join(modes, "|") + ")" +} + +var errIntAmbig = fmt.Errorf("ambiguous integer value; must include '0' prefix") + +func prefix0(val string) bool { + return strings.HasPrefix(val, "0") || strings.HasPrefix(val, "-0") +} + +func prefix0x(val string) bool { + return strings.HasPrefix(val, "0x") || strings.HasPrefix(val, "-0x") +} + +// ParseInt parses val using mode into intptr, which must be a pointer to an +// integer kind type. Non-decimal value require prefix `0` or `0x` in the cases +// when mode permits ambiguity of base; otherwise the prefix can be omitted. +func ParseInt(intptr interface{}, val string, mode IntMode) error { + val = strings.TrimSpace(val) + verb := byte(0) + switch mode { + case Dec: + verb = 'd' + case Dec + Hex: + if prefix0x(val) { + verb = 'v' + } else { + verb = 'd' + } + case Dec + Oct: + if prefix0(val) && !prefix0x(val) { + verb = 'v' + } else { + verb = 'd' + } + case Dec + Hex + Oct: + verb = 'v' + case Hex: + if prefix0x(val) { + verb = 'v' + } else { + verb = 'x' + } + case Oct: + verb = 'o' + case Hex + Oct: + if prefix0(val) { + verb = 'v' + } else { + return errIntAmbig + } + } + if verb == 0 { + panic("unsupported mode") + } + return ScanFully(intptr, val, verb) +} diff --git a/vendor/github.com/go-git/gcfg/types/scan.go b/vendor/github.com/go-git/gcfg/types/scan.go new file mode 100644 index 0000000000..db2f6ed3ca --- /dev/null +++ b/vendor/github.com/go-git/gcfg/types/scan.go @@ -0,0 +1,23 @@ +package types + +import ( + "fmt" + "io" + "reflect" +) + +// ScanFully uses fmt.Sscanf with verb to fully scan val into ptr. +func ScanFully(ptr interface{}, val string, verb byte) error { + t := reflect.ValueOf(ptr).Elem().Type() + // attempt to read extra bytes to make sure the value is consumed + var b []byte + n, err := fmt.Sscanf(val, "%"+string(verb)+"%s", ptr, &b) + switch { + case n < 1 || n == 1 && err != io.EOF: + return fmt.Errorf("failed to parse %q as %v: %v", val, t, err) + case n > 1: + return fmt.Errorf("failed to parse %q as %v: extra characters %q", val, t, string(b)) + } + // n == 1 && err == io.EOF + return nil +} diff --git a/vendor/github.com/go-git/go-billy/v5/.gitignore b/vendor/github.com/go-git/go-billy/v5/.gitignore new file mode 100644 index 0000000000..7aeb46699c --- /dev/null +++ b/vendor/github.com/go-git/go-billy/v5/.gitignore @@ -0,0 +1,4 @@ +/coverage.txt +/vendor +Gopkg.lock +Gopkg.toml diff --git a/vendor/github.com/go-git/go-billy/v5/LICENSE b/vendor/github.com/go-git/go-billy/v5/LICENSE new file mode 100644 index 0000000000..9d60756894 --- /dev/null +++ b/vendor/github.com/go-git/go-billy/v5/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2017 Sourced Technologies S.L. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/go-git/go-billy/v5/Makefile b/vendor/github.com/go-git/go-billy/v5/Makefile new file mode 100644 index 0000000000..74dad8b491 --- /dev/null +++ b/vendor/github.com/go-git/go-billy/v5/Makefile @@ -0,0 +1,11 @@ +# Go parameters +GOCMD = go +GOTEST = $(GOCMD) test + +.PHONY: test +test: + $(GOTEST) -race ./... + +test-coverage: + echo "" > $(COVERAGE_REPORT); \ + $(GOTEST) -coverprofile=$(COVERAGE_REPORT) -coverpkg=./... -covermode=$(COVERAGE_MODE) ./... diff --git a/vendor/github.com/go-git/go-billy/v5/README.md b/vendor/github.com/go-git/go-billy/v5/README.md new file mode 100644 index 0000000000..da5c074782 --- /dev/null +++ b/vendor/github.com/go-git/go-billy/v5/README.md @@ -0,0 +1,73 @@ +# go-billy [![GoDoc](https://godoc.org/gopkg.in/go-git/go-billy.v5?status.svg)](https://pkg.go.dev/github.com/go-git/go-billy/v5) [![Test](https://github.com/go-git/go-billy/workflows/Test/badge.svg)](https://github.com/go-git/go-billy/actions?query=workflow%3ATest) + +The missing interface filesystem abstraction for Go. +Billy implements an interface based on the `os` standard library, allowing to develop applications without dependency on the underlying storage. Makes it virtually free to implement mocks and testing over filesystem operations. + +Billy was born as part of [go-git/go-git](https://github.com/go-git/go-git) project. + +## Installation + +```go +import "github.com/go-git/go-billy/v5" // with go modules enabled (GO111MODULE=on or outside GOPATH) +import "github.com/go-git/go-billy" // with go modules disabled +``` + +## Usage + +Billy exposes filesystems using the +[`Filesystem` interface](https://pkg.go.dev/github.com/go-git/go-billy/v5?tab=doc#Filesystem). +Each filesystem implementation gives you a `New` method, whose arguments depend on +the implementation itself, that returns a new `Filesystem`. + +The following example caches in memory all readable files in a directory from any +billy's filesystem implementation. + +```go +func LoadToMemory(origin billy.Filesystem, path string) (*memory.Memory, error) { + memory := memory.New() + + files, err := origin.ReadDir("/") + if err != nil { + return nil, err + } + + for _, file := range files { + if file.IsDir() { + continue + } + + src, err := origin.Open(file.Name()) + if err != nil { + return nil, err + } + + dst, err := memory.Create(file.Name()) + if err != nil { + return nil, err + } + + if _, err = io.Copy(dst, src); err != nil { + return nil, err + } + + if err := dst.Close(); err != nil { + return nil, err + } + + if err := src.Close(); err != nil { + return nil, err + } + } + + return memory, nil +} +``` + +## Why billy? + +The library billy deals with storage systems and Billy is the name of a well-known, IKEA +bookcase. That's it. + +## License + +Apache License Version 2.0, see [LICENSE](LICENSE) diff --git a/vendor/github.com/go-git/go-billy/v5/fs.go b/vendor/github.com/go-git/go-billy/v5/fs.go new file mode 100644 index 0000000000..a9efccdeb2 --- /dev/null +++ b/vendor/github.com/go-git/go-billy/v5/fs.go @@ -0,0 +1,202 @@ +package billy + +import ( + "errors" + "io" + "os" + "time" +) + +var ( + ErrReadOnly = errors.New("read-only filesystem") + ErrNotSupported = errors.New("feature not supported") + ErrCrossedBoundary = errors.New("chroot boundary crossed") +) + +// Capability holds the supported features of a billy filesystem. This does +// not mean that the capability has to be supported by the underlying storage. +// For example, a billy filesystem may support WriteCapability but the +// storage be mounted in read only mode. +type Capability uint64 + +const ( + // WriteCapability means that the fs is writable. + WriteCapability Capability = 1 << iota + // ReadCapability means that the fs is readable. + ReadCapability + // ReadAndWriteCapability is the ability to open a file in read and write mode. + ReadAndWriteCapability + // SeekCapability means it is able to move position inside the file. + SeekCapability + // TruncateCapability means that a file can be truncated. + TruncateCapability + // LockCapability is the ability to lock a file. + LockCapability + + // DefaultCapabilities lists all capable features supported by filesystems + // without Capability interface. This list should not be changed until a + // major version is released. + DefaultCapabilities Capability = WriteCapability | ReadCapability | + ReadAndWriteCapability | SeekCapability | TruncateCapability | + LockCapability + + // AllCapabilities lists all capable features. + AllCapabilities Capability = WriteCapability | ReadCapability | + ReadAndWriteCapability | SeekCapability | TruncateCapability | + LockCapability +) + +// Filesystem abstract the operations in a storage-agnostic interface. +// Each method implementation mimics the behavior of the equivalent functions +// at the os package from the standard library. +type Filesystem interface { + Basic + TempFile + Dir + Symlink + Chroot +} + +// Basic abstract the basic operations in a storage-agnostic interface as +// an extension to the Basic interface. +type Basic interface { + // Create creates the named file with mode 0666 (before umask), truncating + // it if it already exists. If successful, methods on the returned File can + // be used for I/O; the associated file descriptor has mode O_RDWR. + Create(filename string) (File, error) + // Open opens the named file for reading. If successful, methods on the + // returned file can be used for reading; the associated file descriptor has + // mode O_RDONLY. + Open(filename string) (File, error) + // OpenFile is the generalized open call; most users will use Open or Create + // instead. It opens the named file with specified flag (O_RDONLY etc.) and + // perm, (0666 etc.) if applicable. If successful, methods on the returned + // File can be used for I/O. + OpenFile(filename string, flag int, perm os.FileMode) (File, error) + // Stat returns a FileInfo describing the named file. + Stat(filename string) (os.FileInfo, error) + // Rename renames (moves) oldpath to newpath. If newpath already exists and + // is not a directory, Rename replaces it. OS-specific restrictions may + // apply when oldpath and newpath are in different directories. + Rename(oldpath, newpath string) error + // Remove removes the named file or directory. + Remove(filename string) error + // Join joins any number of path elements into a single path, adding a + // Separator if necessary. Join calls filepath.Clean on the result; in + // particular, all empty strings are ignored. On Windows, the result is a + // UNC path if and only if the first path element is a UNC path. + Join(elem ...string) string +} + +type TempFile interface { + // TempFile creates a new temporary file in the directory dir with a name + // beginning with prefix, opens the file for reading and writing, and + // returns the resulting *os.File. If dir is the empty string, TempFile + // uses the default directory for temporary files (see os.TempDir). + // Multiple programs calling TempFile simultaneously will not choose the + // same file. The caller can use f.Name() to find the pathname of the file. + // It is the caller's responsibility to remove the file when no longer + // needed. + TempFile(dir, prefix string) (File, error) +} + +// Dir abstract the dir related operations in a storage-agnostic interface as +// an extension to the Basic interface. +type Dir interface { + // ReadDir reads the directory named by dirname and returns a list of + // directory entries sorted by filename. + ReadDir(path string) ([]os.FileInfo, error) + // MkdirAll creates a directory named path, along with any necessary + // parents, and returns nil, or else returns an error. The permission bits + // perm are used for all directories that MkdirAll creates. If path is/ + // already a directory, MkdirAll does nothing and returns nil. + MkdirAll(filename string, perm os.FileMode) error +} + +// Symlink abstract the symlink related operations in a storage-agnostic +// interface as an extension to the Basic interface. +type Symlink interface { + // Lstat returns a FileInfo describing the named file. If the file is a + // symbolic link, the returned FileInfo describes the symbolic link. Lstat + // makes no attempt to follow the link. + Lstat(filename string) (os.FileInfo, error) + // Symlink creates a symbolic-link from link to target. target may be an + // absolute or relative path, and need not refer to an existing node. + // Parent directories of link are created as necessary. + Symlink(target, link string) error + // Readlink returns the target path of link. + Readlink(link string) (string, error) +} + +// Change abstract the FileInfo change related operations in a storage-agnostic +// interface as an extension to the Basic interface +type Change interface { + // Chmod changes the mode of the named file to mode. If the file is a + // symbolic link, it changes the mode of the link's target. + Chmod(name string, mode os.FileMode) error + // Lchown changes the numeric uid and gid of the named file. If the file is + // a symbolic link, it changes the uid and gid of the link itself. + Lchown(name string, uid, gid int) error + // Chown changes the numeric uid and gid of the named file. If the file is a + // symbolic link, it changes the uid and gid of the link's target. + Chown(name string, uid, gid int) error + // Chtimes changes the access and modification times of the named file, + // similar to the Unix utime() or utimes() functions. + // + // The underlying filesystem may truncate or round the values to a less + // precise time unit. + Chtimes(name string, atime time.Time, mtime time.Time) error +} + +// Chroot abstract the chroot related operations in a storage-agnostic interface +// as an extension to the Basic interface. +type Chroot interface { + // Chroot returns a new filesystem from the same type where the new root is + // the given path. Files outside of the designated directory tree cannot be + // accessed. + Chroot(path string) (Filesystem, error) + // Root returns the root path of the filesystem. + Root() string +} + +// File represent a file, being a subset of the os.File +type File interface { + // Name returns the name of the file as presented to Open. + Name() string + io.Writer + io.Reader + io.ReaderAt + io.Seeker + io.Closer + // Lock locks the file like e.g. flock. It protects against access from + // other processes. + Lock() error + // Unlock unlocks the file. + Unlock() error + // Truncate the file. + Truncate(size int64) error +} + +// Capable interface can return the available features of a filesystem. +type Capable interface { + // Capabilities returns the capabilities of a filesystem in bit flags. + Capabilities() Capability +} + +// Capabilities returns the features supported by a filesystem. If the FS +// does not implement Capable interface it returns all features. +func Capabilities(fs Basic) Capability { + capable, ok := fs.(Capable) + if !ok { + return DefaultCapabilities + } + + return capable.Capabilities() +} + +// CapabilityCheck tests the filesystem for the provided capabilities and +// returns true in case it supports all of them. +func CapabilityCheck(fs Basic, capabilities Capability) bool { + fsCaps := Capabilities(fs) + return fsCaps&capabilities == capabilities +} diff --git a/vendor/github.com/go-git/go-git/v5/LICENSE b/vendor/github.com/go-git/go-git/v5/LICENSE new file mode 100644 index 0000000000..8aa3d854cf --- /dev/null +++ b/vendor/github.com/go-git/go-git/v5/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018 Sourced Technologies, S.L. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/go-git/go-git/v5/internal/path_util/path_util.go b/vendor/github.com/go-git/go-git/v5/internal/path_util/path_util.go new file mode 100644 index 0000000000..48e4a3d0ec --- /dev/null +++ b/vendor/github.com/go-git/go-git/v5/internal/path_util/path_util.go @@ -0,0 +1,29 @@ +package path_util + +import ( + "os" + "os/user" + "strings" +) + +func ReplaceTildeWithHome(path string) (string, error) { + if strings.HasPrefix(path, "~") { + firstSlash := strings.Index(path, "/") + if firstSlash == 1 { + home, err := os.UserHomeDir() + if err != nil { + return path, err + } + return strings.Replace(path, "~", home, 1), nil + } else if firstSlash > 1 { + username := path[1:firstSlash] + userAccount, err := user.Lookup(username) + if err != nil { + return path, err + } + return strings.Replace(path, path[:firstSlash], userAccount.HomeDir, 1), nil + } + } + + return path, nil +} diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/config/common.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/config/common.go new file mode 100644 index 0000000000..6d689ea1e0 --- /dev/null +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/config/common.go @@ -0,0 +1,109 @@ +package config + +// New creates a new config instance. +func New() *Config { + return &Config{} +} + +// Config contains all the sections, comments and includes from a config file. +type Config struct { + Comment *Comment + Sections Sections + Includes Includes +} + +// Includes is a list of Includes in a config file. +type Includes []*Include + +// Include is a reference to an included config file. +type Include struct { + Path string + Config *Config +} + +// Comment string without the prefix '#' or ';'. +type Comment string + +const ( + // NoSubsection token is passed to Config.Section and Config.SetSection to + // represent the absence of a section. + NoSubsection = "" +) + +// Section returns a existing section with the given name or creates a new one. +func (c *Config) Section(name string) *Section { + for i := len(c.Sections) - 1; i >= 0; i-- { + s := c.Sections[i] + if s.IsName(name) { + return s + } + } + + s := &Section{Name: name} + c.Sections = append(c.Sections, s) + return s +} + +// HasSection checks if the Config has a section with the specified name. +func (c *Config) HasSection(name string) bool { + for _, s := range c.Sections { + if s.IsName(name) { + return true + } + } + return false +} + +// RemoveSection removes a section from a config file. +func (c *Config) RemoveSection(name string) *Config { + result := Sections{} + for _, s := range c.Sections { + if !s.IsName(name) { + result = append(result, s) + } + } + + c.Sections = result + return c +} + +// RemoveSubsection remove a subsection from a config file. +func (c *Config) RemoveSubsection(section string, subsection string) *Config { + for _, s := range c.Sections { + if s.IsName(section) { + result := Subsections{} + for _, ss := range s.Subsections { + if !ss.IsName(subsection) { + result = append(result, ss) + } + } + s.Subsections = result + } + } + + return c +} + +// AddOption adds an option to a given section and subsection. Use the +// NoSubsection constant for the subsection argument if no subsection is wanted. +func (c *Config) AddOption(section string, subsection string, key string, value string) *Config { + if subsection == "" { + c.Section(section).AddOption(key, value) + } else { + c.Section(section).Subsection(subsection).AddOption(key, value) + } + + return c +} + +// SetOption sets an option to a given section and subsection. Use the +// NoSubsection constant for the subsection argument if no subsection is wanted. +func (c *Config) SetOption(section string, subsection string, key string, value string) *Config { + if subsection == "" { + c.Section(section).SetOption(key, value) + } else { + c.Section(section).Subsection(subsection).SetOption(key, value) + } + + return c +} diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/config/decoder.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/config/decoder.go new file mode 100644 index 0000000000..8e52d57f30 --- /dev/null +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/config/decoder.go @@ -0,0 +1,37 @@ +package config + +import ( + "io" + + "github.com/go-git/gcfg" +) + +// A Decoder reads and decodes config files from an input stream. +type Decoder struct { + io.Reader +} + +// NewDecoder returns a new decoder that reads from r. +func NewDecoder(r io.Reader) *Decoder { + return &Decoder{r} +} + +// Decode reads the whole config from its input and stores it in the +// value pointed to by config. +func (d *Decoder) Decode(config *Config) error { + cb := func(s string, ss string, k string, v string, bv bool) error { + if ss == "" && k == "" { + config.Section(s) + return nil + } + + if ss != "" && k == "" { + config.Section(s).Subsection(ss) + return nil + } + + config.AddOption(s, ss, k, v) + return nil + } + return gcfg.ReadWithCallback(d, cb) +} diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/config/doc.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/config/doc.go new file mode 100644 index 0000000000..3986c83658 --- /dev/null +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/config/doc.go @@ -0,0 +1,122 @@ +// Package config implements encoding and decoding of git config files. +// +// Configuration File +// ------------------ +// +// The Git configuration file contains a number of variables that affect +// the Git commands' behavior. The `.git/config` file in each repository +// is used to store the configuration for that repository, and +// `$HOME/.gitconfig` is used to store a per-user configuration as +// fallback values for the `.git/config` file. The file `/etc/gitconfig` +// can be used to store a system-wide default configuration. +// +// The configuration variables are used by both the Git plumbing +// and the porcelains. The variables are divided into sections, wherein +// the fully qualified variable name of the variable itself is the last +// dot-separated segment and the section name is everything before the last +// dot. The variable names are case-insensitive, allow only alphanumeric +// characters and `-`, and must start with an alphabetic character. Some +// variables may appear multiple times; we say then that the variable is +// multivalued. +// +// Syntax +// ~~~~~~ +// +// The syntax is fairly flexible and permissive; whitespaces are mostly +// ignored. The '#' and ';' characters begin comments to the end of line, +// blank lines are ignored. +// +// The file consists of sections and variables. A section begins with +// the name of the section in square brackets and continues until the next +// section begins. Section names are case-insensitive. Only alphanumeric +// characters, `-` and `.` are allowed in section names. Each variable +// must belong to some section, which means that there must be a section +// header before the first setting of a variable. +// +// Sections can be further divided into subsections. To begin a subsection +// put its name in double quotes, separated by space from the section name, +// in the section header, like in the example below: +// +// -------- +// [section "subsection"] +// +// -------- +// +// Subsection names are case sensitive and can contain any characters except +// newline (doublequote `"` and backslash can be included by escaping them +// as `\"` and `\\`, respectively). Section headers cannot span multiple +// lines. Variables may belong directly to a section or to a given subsection. +// You can have `[section]` if you have `[section "subsection"]`, but you +// don't need to. +// +// There is also a deprecated `[section.subsection]` syntax. With this +// syntax, the subsection name is converted to lower-case and is also +// compared case sensitively. These subsection names follow the same +// restrictions as section names. +// +// All the other lines (and the remainder of the line after the section +// header) are recognized as setting variables, in the form +// 'name = value' (or just 'name', which is a short-hand to say that +// the variable is the boolean "true"). +// The variable names are case-insensitive, allow only alphanumeric characters +// and `-`, and must start with an alphabetic character. +// +// A line that defines a value can be continued to the next line by +// ending it with a `\`; the backquote and the end-of-line are +// stripped. Leading whitespaces after 'name =', the remainder of the +// line after the first comment character '#' or ';', and trailing +// whitespaces of the line are discarded unless they are enclosed in +// double quotes. Internal whitespaces within the value are retained +// verbatim. +// +// Inside double quotes, double quote `"` and backslash `\` characters +// must be escaped: use `\"` for `"` and `\\` for `\`. +// +// The following escape sequences (beside `\"` and `\\`) are recognized: +// `\n` for newline character (NL), `\t` for horizontal tabulation (HT, TAB) +// and `\b` for backspace (BS). Other char escape sequences (including octal +// escape sequences) are invalid. +// +// Includes +// ~~~~~~~~ +// +// You can include one config file from another by setting the special +// `include.path` variable to the name of the file to be included. The +// variable takes a pathname as its value, and is subject to tilde +// expansion. +// +// The included file is expanded immediately, as if its contents had been +// found at the location of the include directive. If the value of the +// `include.path` variable is a relative path, the path is considered to be +// relative to the configuration file in which the include directive was +// found. See below for examples. +// +// +// Example +// ~~~~~~~ +// +// # Core variables +// [core] +// ; Don't trust file modes +// filemode = false +// +// # Our diff algorithm +// [diff] +// external = /usr/local/bin/diff-wrapper +// renames = true +// +// [branch "devel"] +// remote = origin +// merge = refs/heads/devel +// +// # Proxy settings +// [core] +// gitProxy="ssh" for "kernel.org" +// gitProxy=default-proxy ; for the rest +// +// [include] +// path = /path/to/foo.inc ; include by absolute path +// path = foo ; expand "foo" relative to the current file +// path = ~/foo ; expand "foo" in your `$HOME` directory +// +package config diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/config/encoder.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/config/encoder.go new file mode 100644 index 0000000000..de069aed5e --- /dev/null +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/config/encoder.go @@ -0,0 +1,82 @@ +package config + +import ( + "fmt" + "io" + "strings" +) + +// An Encoder writes config files to an output stream. +type Encoder struct { + w io.Writer +} + +var ( + subsectionReplacer = strings.NewReplacer(`"`, `\"`, `\`, `\\`) + valueReplacer = strings.NewReplacer(`"`, `\"`, `\`, `\\`, "\n", `\n`, "\t", `\t`, "\b", `\b`) +) +// NewEncoder returns a new encoder that writes to w. +func NewEncoder(w io.Writer) *Encoder { + return &Encoder{w} +} + +// Encode writes the config in git config format to the stream of the encoder. +func (e *Encoder) Encode(cfg *Config) error { + for _, s := range cfg.Sections { + if err := e.encodeSection(s); err != nil { + return err + } + } + + return nil +} + +func (e *Encoder) encodeSection(s *Section) error { + if len(s.Options) > 0 { + if err := e.printf("[%s]\n", s.Name); err != nil { + return err + } + + if err := e.encodeOptions(s.Options); err != nil { + return err + } + } + + for _, ss := range s.Subsections { + if err := e.encodeSubsection(s.Name, ss); err != nil { + return err + } + } + + return nil +} + +func (e *Encoder) encodeSubsection(sectionName string, s *Subsection) error { + if err := e.printf("[%s \"%s\"]\n", sectionName, subsectionReplacer.Replace(s.Name)); err != nil { + return err + } + + return e.encodeOptions(s.Options) +} + +func (e *Encoder) encodeOptions(opts Options) error { + for _, o := range opts { + var value string + if strings.ContainsAny(o.Value, "#;\"\t\n\\") || strings.HasPrefix(o.Value, " ") || strings.HasSuffix(o.Value, " ") { + value = `"`+valueReplacer.Replace(o.Value)+`"` + } else { + value = o.Value + } + + if err := e.printf("\t%s = %s\n", o.Key, value); err != nil { + return err + } + } + + return nil +} + +func (e *Encoder) printf(msg string, args ...interface{}) error { + _, err := fmt.Fprintf(e.w, msg, args...) + return err +} diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/config/format.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/config/format.go new file mode 100644 index 0000000000..4873ea9258 --- /dev/null +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/config/format.go @@ -0,0 +1,53 @@ +package config + +// RepositoryFormatVersion represents the repository format version, +// as per defined at: +// +// https://git-scm.com/docs/repository-version +type RepositoryFormatVersion string + +const ( + // Version_0 is the format defined by the initial version of git, + // including but not limited to the format of the repository + // directory, the repository configuration file, and the object + // and ref storage. + // + // Specifying the complete behavior of git is beyond the scope + // of this document. + Version_0 = "0" + + // Version_1 is identical to version 0, with the following exceptions: + // + // 1. When reading the core.repositoryformatversion variable, a git + // implementation which supports version 1 MUST also read any + // configuration keys found in the extensions section of the + // configuration file. + // + // 2. If a version-1 repository specifies any extensions.* keys that + // the running git has not implemented, the operation MUST NOT proceed. + // Similarly, if the value of any known key is not understood by the + // implementation, the operation MUST NOT proceed. + // + // Note that if no extensions are specified in the config file, then + // core.repositoryformatversion SHOULD be set to 0 (setting it to 1 provides + // no benefit, and makes the repository incompatible with older + // implementations of git). + Version_1 = "1" + + // DefaultRepositoryFormatVersion holds the default repository format version. + DefaultRepositoryFormatVersion = Version_0 +) + +// ObjectFormat defines the object format. +type ObjectFormat string + +const ( + // SHA1 represents the object format used for SHA1. + SHA1 ObjectFormat = "sha1" + + // SHA256 represents the object format used for SHA256. + SHA256 ObjectFormat = "sha256" + + // DefaultObjectFormat holds the default object format. + DefaultObjectFormat = SHA1 +) diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/config/option.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/config/option.go new file mode 100644 index 0000000000..cad394810a --- /dev/null +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/config/option.go @@ -0,0 +1,127 @@ +package config + +import ( + "fmt" + "strings" +) + +// Option defines a key/value entity in a config file. +type Option struct { + // Key preserving original caseness. + // Use IsKey instead to compare key regardless of caseness. + Key string + // Original value as string, could be not normalized. + Value string +} + +type Options []*Option + +// IsKey returns true if the given key matches +// this option's key in a case-insensitive comparison. +func (o *Option) IsKey(key string) bool { + return strings.EqualFold(o.Key, key) +} + +func (opts Options) GoString() string { + var strs []string + for _, opt := range opts { + strs = append(strs, fmt.Sprintf("%#v", opt)) + } + + return strings.Join(strs, ", ") +} + +// Get gets the value for the given key if set, +// otherwise it returns the empty string. +// +// Note that there is no difference +// +// This matches git behaviour since git v1.8.1-rc1, +// if there are multiple definitions of a key, the +// last one wins. +// +// See: http://article.gmane.org/gmane.linux.kernel/1407184 +// +// In order to get all possible values for the same key, +// use GetAll. +func (opts Options) Get(key string) string { + for i := len(opts) - 1; i >= 0; i-- { + o := opts[i] + if o.IsKey(key) { + return o.Value + } + } + return "" +} + +// Has checks if an Option exist with the given key. +func (opts Options) Has(key string) bool { + for _, o := range opts { + if o.IsKey(key) { + return true + } + } + return false +} + +// GetAll returns all possible values for the same key. +func (opts Options) GetAll(key string) []string { + result := []string{} + for _, o := range opts { + if o.IsKey(key) { + result = append(result, o.Value) + } + } + return result +} + +func (opts Options) withoutOption(key string) Options { + result := Options{} + for _, o := range opts { + if !o.IsKey(key) { + result = append(result, o) + } + } + return result +} + +func (opts Options) withAddedOption(key string, value string) Options { + return append(opts, &Option{key, value}) +} + +func (opts Options) withSettedOption(key string, values ...string) Options { + var result Options + var added []string + for _, o := range opts { + if !o.IsKey(key) { + result = append(result, o) + continue + } + + if contains(values, o.Value) { + added = append(added, o.Value) + result = append(result, o) + continue + } + } + + for _, value := range values { + if contains(added, value) { + continue + } + + result = result.withAddedOption(key, value) + } + + return result +} + +func contains(haystack []string, needle string) bool { + for _, s := range haystack { + if s == needle { + return true + } + } + + return false +} diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/config/section.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/config/section.go new file mode 100644 index 0000000000..4625ac5837 --- /dev/null +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/config/section.go @@ -0,0 +1,181 @@ +package config + +import ( + "fmt" + "strings" +) + +// Section is the representation of a section inside git configuration files. +// Each Section contains Options that are used by both the Git plumbing +// and the porcelains. +// Sections can be further divided into subsections. To begin a subsection +// put its name in double quotes, separated by space from the section name, +// in the section header, like in the example below: +// +// [section "subsection"] +// +// All the other lines (and the remainder of the line after the section header) +// are recognized as option variables, in the form "name = value" (or just name, +// which is a short-hand to say that the variable is the boolean "true"). +// The variable names are case-insensitive, allow only alphanumeric characters +// and -, and must start with an alphabetic character: +// +// [section "subsection1"] +// option1 = value1 +// option2 +// [section "subsection2"] +// option3 = value2 +// +type Section struct { + Name string + Options Options + Subsections Subsections +} + +type Subsection struct { + Name string + Options Options +} + +type Sections []*Section + +func (s Sections) GoString() string { + var strs []string + for _, ss := range s { + strs = append(strs, fmt.Sprintf("%#v", ss)) + } + + return strings.Join(strs, ", ") +} + +type Subsections []*Subsection + +func (s Subsections) GoString() string { + var strs []string + for _, ss := range s { + strs = append(strs, fmt.Sprintf("%#v", ss)) + } + + return strings.Join(strs, ", ") +} + +// IsName checks if the name provided is equals to the Section name, case insensitive. +func (s *Section) IsName(name string) bool { + return strings.EqualFold(s.Name, name) +} + +// Subsection returns a Subsection from the specified Section. If the +// Subsection does not exists, new one is created and added to Section. +func (s *Section) Subsection(name string) *Subsection { + for i := len(s.Subsections) - 1; i >= 0; i-- { + ss := s.Subsections[i] + if ss.IsName(name) { + return ss + } + } + + ss := &Subsection{Name: name} + s.Subsections = append(s.Subsections, ss) + return ss +} + +// HasSubsection checks if the Section has a Subsection with the specified name. +func (s *Section) HasSubsection(name string) bool { + for _, ss := range s.Subsections { + if ss.IsName(name) { + return true + } + } + + return false +} + +// RemoveSubsection removes a subsection from a Section. +func (s *Section) RemoveSubsection(name string) *Section { + result := Subsections{} + for _, s := range s.Subsections { + if !s.IsName(name) { + result = append(result, s) + } + } + + s.Subsections = result + return s +} + +// Option returns the value for the specified key. Empty string is returned if +// key does not exists. +func (s *Section) Option(key string) string { + return s.Options.Get(key) +} + +// OptionAll returns all possible values for an option with the specified key. +// If the option does not exists, an empty slice will be returned. +func (s *Section) OptionAll(key string) []string { + return s.Options.GetAll(key) +} + +// HasOption checks if the Section has an Option with the given key. +func (s *Section) HasOption(key string) bool { + return s.Options.Has(key) +} + +// AddOption adds a new Option to the Section. The updated Section is returned. +func (s *Section) AddOption(key string, value string) *Section { + s.Options = s.Options.withAddedOption(key, value) + return s +} + +// SetOption adds a new Option to the Section. If the option already exists, is replaced. +// The updated Section is returned. +func (s *Section) SetOption(key string, value string) *Section { + s.Options = s.Options.withSettedOption(key, value) + return s +} + +// Remove an option with the specified key. The updated Section is returned. +func (s *Section) RemoveOption(key string) *Section { + s.Options = s.Options.withoutOption(key) + return s +} + +// IsName checks if the name of the subsection is exactly the specified name. +func (s *Subsection) IsName(name string) bool { + return s.Name == name +} + +// Option returns an option with the specified key. If the option does not exists, +// empty spring will be returned. +func (s *Subsection) Option(key string) string { + return s.Options.Get(key) +} + +// OptionAll returns all possible values for an option with the specified key. +// If the option does not exists, an empty slice will be returned. +func (s *Subsection) OptionAll(key string) []string { + return s.Options.GetAll(key) +} + +// HasOption checks if the Subsection has an Option with the given key. +func (s *Subsection) HasOption(key string) bool { + return s.Options.Has(key) +} + +// AddOption adds a new Option to the Subsection. The updated Subsection is returned. +func (s *Subsection) AddOption(key string, value string) *Subsection { + s.Options = s.Options.withAddedOption(key, value) + return s +} + +// SetOption adds a new Option to the Subsection. If the option already exists, is replaced. +// The updated Subsection is returned. +func (s *Subsection) SetOption(key string, value ...string) *Subsection { + s.Options = s.Options.withSettedOption(key, value...) + return s +} + +// RemoveOption removes the option with the specified key. The updated Subsection is returned. +func (s *Subsection) RemoveOption(key string) *Subsection { + s.Options = s.Options.withoutOption(key) + return s +} diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/dir.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/dir.go new file mode 100644 index 0000000000..d8fb30c166 --- /dev/null +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/dir.go @@ -0,0 +1,144 @@ +package gitignore + +import ( + "bufio" + "bytes" + "io" + "os" + "strings" + + "github.com/go-git/go-billy/v5" + "github.com/go-git/go-git/v5/internal/path_util" + "github.com/go-git/go-git/v5/plumbing/format/config" + gioutil "github.com/go-git/go-git/v5/utils/ioutil" +) + +const ( + commentPrefix = "#" + coreSection = "core" + excludesfile = "excludesfile" + gitDir = ".git" + gitignoreFile = ".gitignore" + gitconfigFile = ".gitconfig" + systemFile = "/etc/gitconfig" + infoExcludeFile = gitDir + "/info/exclude" +) + +// readIgnoreFile reads a specific git ignore file. +func readIgnoreFile(fs billy.Filesystem, path []string, ignoreFile string) (ps []Pattern, err error) { + + ignoreFile, _ = path_util.ReplaceTildeWithHome(ignoreFile) + + f, err := fs.Open(fs.Join(append(path, ignoreFile)...)) + if err == nil { + defer f.Close() + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + s := scanner.Text() + if !strings.HasPrefix(s, commentPrefix) && len(strings.TrimSpace(s)) > 0 { + ps = append(ps, ParsePattern(s, path)) + } + } + } else if !os.IsNotExist(err) { + return nil, err + } + + return +} + +// ReadPatterns reads the .git/info/exclude and then the gitignore patterns +// recursively traversing through the directory structure. The result is in +// the ascending order of priority (last higher). +func ReadPatterns(fs billy.Filesystem, path []string) (ps []Pattern, err error) { + ps, _ = readIgnoreFile(fs, path, infoExcludeFile) + + subps, _ := readIgnoreFile(fs, path, gitignoreFile) + ps = append(ps, subps...) + + var fis []os.FileInfo + fis, err = fs.ReadDir(fs.Join(path...)) + if err != nil { + return + } + + for _, fi := range fis { + if fi.IsDir() && fi.Name() != gitDir { + var subps []Pattern + subps, err = ReadPatterns(fs, append(path, fi.Name())) + if err != nil { + return + } + + if len(subps) > 0 { + ps = append(ps, subps...) + } + } + } + + return +} + +func loadPatterns(fs billy.Filesystem, path string) (ps []Pattern, err error) { + f, err := fs.Open(path) + if err != nil { + if os.IsNotExist(err) { + return nil, nil + } + return nil, err + } + + defer gioutil.CheckClose(f, &err) + + b, err := io.ReadAll(f) + if err != nil { + return + } + + d := config.NewDecoder(bytes.NewBuffer(b)) + + raw := config.New() + if err = d.Decode(raw); err != nil { + return + } + + s := raw.Section(coreSection) + efo := s.Options.Get(excludesfile) + if efo == "" { + return nil, nil + } + + ps, err = readIgnoreFile(fs, nil, efo) + if os.IsNotExist(err) { + return nil, nil + } + + return +} + +// LoadGlobalPatterns loads gitignore patterns from from the gitignore file +// declared in a user's ~/.gitconfig file. If the ~/.gitconfig file does not +// exist the function will return nil. If the core.excludesfile property +// is not declared, the function will return nil. If the file pointed to by +// the core.excludesfile property does not exist, the function will return nil. +// +// The function assumes fs is rooted at the root filesystem. +func LoadGlobalPatterns(fs billy.Filesystem) (ps []Pattern, err error) { + home, err := os.UserHomeDir() + if err != nil { + return + } + + return loadPatterns(fs, fs.Join(home, gitconfigFile)) +} + +// LoadSystemPatterns loads gitignore patterns from from the gitignore file +// declared in a system's /etc/gitconfig file. If the /etc/gitconfig file does +// not exist the function will return nil. If the core.excludesfile property +// is not declared, the function will return nil. If the file pointed to by +// the core.excludesfile property does not exist, the function will return nil. +// +// The function assumes fs is rooted at the root filesystem. +func LoadSystemPatterns(fs billy.Filesystem) (ps []Pattern, err error) { + return loadPatterns(fs, systemFile) +} diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/doc.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/doc.go new file mode 100644 index 0000000000..eecd4baccb --- /dev/null +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/doc.go @@ -0,0 +1,70 @@ +// Package gitignore implements matching file system paths to gitignore patterns that +// can be automatically read from a git repository tree in the order of definition +// priorities. It support all pattern formats as specified in the original gitignore +// documentation, copied below: +// +// Pattern format +// ============== +// +// - A blank line matches no files, so it can serve as a separator for readability. +// +// - A line starting with # serves as a comment. Put a backslash ("\") in front of +// the first hash for patterns that begin with a hash. +// +// - Trailing spaces are ignored unless they are quoted with backslash ("\"). +// +// - An optional prefix "!" which negates the pattern; any matching file excluded +// by a previous pattern will become included again. It is not possible to +// re-include a file if a parent directory of that file is excluded. +// Git doesn’t list excluded directories for performance reasons, so +// any patterns on contained files have no effect, no matter where they are +// defined. Put a backslash ("\") in front of the first "!" for patterns +// that begin with a literal "!", for example, "\!important!.txt". +// +// - If the pattern ends with a slash, it is removed for the purpose of the +// following description, but it would only find a match with a directory. +// In other words, foo/ will match a directory foo and paths underneath it, +// but will not match a regular file or a symbolic link foo (this is consistent +// with the way how pathspec works in general in Git). +// +// - If the pattern does not contain a slash /, Git treats it as a shell glob +// pattern and checks for a match against the pathname relative to the location +// of the .gitignore file (relative to the toplevel of the work tree if not +// from a .gitignore file). +// +// - Otherwise, Git treats the pattern as a shell glob suitable for consumption +// by fnmatch(3) with the FNM_PATHNAME flag: wildcards in the pattern will +// not match a / in the pathname. For example, "Documentation/*.html" matches +// "Documentation/git.html" but not "Documentation/ppc/ppc.html" or +// "tools/perf/Documentation/perf.html". +// +// - A leading slash matches the beginning of the pathname. For example, +// "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c". +// +// Two consecutive asterisks ("**") in patterns matched against full pathname +// may have special meaning: +// +// - A leading "**" followed by a slash means match in all directories. +// For example, "**/foo" matches file or directory "foo" anywhere, the same as +// pattern "foo". "**/foo/bar" matches file or directory "bar" +// anywhere that is directly under directory "foo". +// +// - A trailing "/**" matches everything inside. For example, "abc/**" matches +// all files inside directory "abc", relative to the location of the +// .gitignore file, with infinite depth. +// +// - A slash followed by two consecutive asterisks then a slash matches +// zero or more directories. For example, "a/**/b" matches "a/b", "a/x/b", +// "a/x/y/b" and so on. +// +// - Other consecutive asterisks are considered invalid. +// +// Copyright and license +// ===================== +// +// Copyright (c) Oleg Sklyar, Silvertern and source{d} +// +// The package code was donated to source{d} to include, modify and develop +// further as a part of the `go-git` project, release it on the license of +// the whole project or delete it from the project. +package gitignore diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/matcher.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/matcher.go new file mode 100644 index 0000000000..bd1e9e2d4c --- /dev/null +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/matcher.go @@ -0,0 +1,30 @@ +package gitignore + +// Matcher defines a global multi-pattern matcher for gitignore patterns +type Matcher interface { + // Match matches patterns in the order of priorities. As soon as an inclusion or + // exclusion is found, not further matching is performed. + Match(path []string, isDir bool) bool +} + +// NewMatcher constructs a new global matcher. Patterns must be given in the order of +// increasing priority. That is most generic settings files first, then the content of +// the repo .gitignore, then content of .gitignore down the path or the repo and then +// the content command line arguments. +func NewMatcher(ps []Pattern) Matcher { + return &matcher{ps} +} + +type matcher struct { + patterns []Pattern +} + +func (m *matcher) Match(path []string, isDir bool) bool { + n := len(m.patterns) + for i := n - 1; i >= 0; i-- { + if match := m.patterns[i].Match(path, isDir); match > NoMatch { + return match == Exclude + } + } + return false +} diff --git a/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/pattern.go b/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/pattern.go new file mode 100644 index 0000000000..450b3cdf72 --- /dev/null +++ b/vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/pattern.go @@ -0,0 +1,155 @@ +package gitignore + +import ( + "path/filepath" + "strings" +) + +// MatchResult defines outcomes of a match, no match, exclusion or inclusion. +type MatchResult int + +const ( + // NoMatch defines the no match outcome of a match check + NoMatch MatchResult = iota + // Exclude defines an exclusion of a file as a result of a match check + Exclude + // Include defines an explicit inclusion of a file as a result of a match check + Include +) + +const ( + inclusionPrefix = "!" + zeroToManyDirs = "**" + patternDirSep = "/" +) + +// Pattern defines a single gitignore pattern. +type Pattern interface { + // Match matches the given path to the pattern. + Match(path []string, isDir bool) MatchResult +} + +type pattern struct { + domain []string + pattern []string + inclusion bool + dirOnly bool + isGlob bool +} + +// ParsePattern parses a gitignore pattern string into the Pattern structure. +func ParsePattern(p string, domain []string) Pattern { + // storing domain, copy it to ensure it isn't changed externally + domain = append([]string(nil), domain...) + res := pattern{domain: domain} + + if strings.HasPrefix(p, inclusionPrefix) { + res.inclusion = true + p = p[1:] + } + + if !strings.HasSuffix(p, "\\ ") { + p = strings.TrimRight(p, " ") + } + + if strings.HasSuffix(p, patternDirSep) { + res.dirOnly = true + p = p[:len(p)-1] + } + + if strings.Contains(p, patternDirSep) { + res.isGlob = true + } + + res.pattern = strings.Split(p, patternDirSep) + return &res +} + +func (p *pattern) Match(path []string, isDir bool) MatchResult { + if len(path) <= len(p.domain) { + return NoMatch + } + for i, e := range p.domain { + if path[i] != e { + return NoMatch + } + } + + path = path[len(p.domain):] + if p.isGlob && !p.globMatch(path, isDir) { + return NoMatch + } else if !p.isGlob && !p.simpleNameMatch(path, isDir) { + return NoMatch + } + + if p.inclusion { + return Include + } else { + return Exclude + } +} + +func (p *pattern) simpleNameMatch(path []string, isDir bool) bool { + for i, name := range path { + if match, err := filepath.Match(p.pattern[0], name); err != nil { + return false + } else if !match { + continue + } + if p.dirOnly && !isDir && i == len(path)-1 { + return false + } + return true + } + return false +} + +func (p *pattern) globMatch(path []string, isDir bool) bool { + matched := false + canTraverse := false + for i, pattern := range p.pattern { + if pattern == "" { + canTraverse = false + continue + } + if pattern == zeroToManyDirs { + if i == len(p.pattern)-1 { + break + } + canTraverse = true + continue + } + if strings.Contains(pattern, zeroToManyDirs) { + return false + } + if len(path) == 0 { + return false + } + if canTraverse { + canTraverse = false + for len(path) > 0 { + e := path[0] + path = path[1:] + if match, err := filepath.Match(pattern, e); err != nil { + return false + } else if match { + matched = true + break + } else if len(path) == 0 { + // if nothing left then fail + matched = false + } + } + } else { + if match, err := filepath.Match(pattern, path[0]); err != nil || !match { + return false + } + matched = true + path = path[1:] + } + } + if matched && p.dirOnly && !isDir && len(path) == 0 { + matched = false + } + return matched +} diff --git a/vendor/github.com/go-git/go-git/v5/utils/ioutil/common.go b/vendor/github.com/go-git/go-git/v5/utils/ioutil/common.go new file mode 100644 index 0000000000..235af717bc --- /dev/null +++ b/vendor/github.com/go-git/go-git/v5/utils/ioutil/common.go @@ -0,0 +1,210 @@ +// Package ioutil implements some I/O utility functions. +package ioutil + +import ( + "bufio" + "context" + "errors" + "io" + + ctxio "github.com/jbenet/go-context/io" +) + +type readPeeker interface { + io.Reader + Peek(int) ([]byte, error) +} + +var ( + ErrEmptyReader = errors.New("reader is empty") +) + +// NonEmptyReader takes a reader and returns it if it is not empty, or +// `ErrEmptyReader` if it is empty. If there is an error when reading the first +// byte of the given reader, it will be propagated. +func NonEmptyReader(r io.Reader) (io.Reader, error) { + pr, ok := r.(readPeeker) + if !ok { + pr = bufio.NewReader(r) + } + + _, err := pr.Peek(1) + if err == io.EOF { + return nil, ErrEmptyReader + } + + if err != nil { + return nil, err + } + + return pr, nil +} + +type readCloser struct { + io.Reader + closer io.Closer +} + +func (r *readCloser) Close() error { + return r.closer.Close() +} + +// NewReadCloser creates an `io.ReadCloser` with the given `io.Reader` and +// `io.Closer`. +func NewReadCloser(r io.Reader, c io.Closer) io.ReadCloser { + return &readCloser{Reader: r, closer: c} +} + +type readCloserCloser struct { + io.ReadCloser + closer func() error +} + +func (r *readCloserCloser) Close() (err error) { + defer func() { + if err == nil { + err = r.closer() + return + } + _ = r.closer() + }() + return r.ReadCloser.Close() +} + +// NewReadCloserWithCloser creates an `io.ReadCloser` with the given `io.ReaderCloser` and +// `io.Closer` that ensures that the closer is closed on close +func NewReadCloserWithCloser(r io.ReadCloser, c func() error) io.ReadCloser { + return &readCloserCloser{ReadCloser: r, closer: c} +} + +type writeCloser struct { + io.Writer + closer io.Closer +} + +func (r *writeCloser) Close() error { + return r.closer.Close() +} + +// NewWriteCloser creates an `io.WriteCloser` with the given `io.Writer` and +// `io.Closer`. +func NewWriteCloser(w io.Writer, c io.Closer) io.WriteCloser { + return &writeCloser{Writer: w, closer: c} +} + +type writeNopCloser struct { + io.Writer +} + +func (writeNopCloser) Close() error { return nil } + +// WriteNopCloser returns a WriteCloser with a no-op Close method wrapping +// the provided Writer w. +func WriteNopCloser(w io.Writer) io.WriteCloser { + return writeNopCloser{w} +} + +type readerAtAsReader struct { + io.ReaderAt + offset int64 +} + +func (r *readerAtAsReader) Read(bs []byte) (int, error) { + n, err := r.ReaderAt.ReadAt(bs, r.offset) + r.offset += int64(n) + return n, err +} + +func NewReaderUsingReaderAt(r io.ReaderAt, offset int64) io.Reader { + return &readerAtAsReader{ + ReaderAt: r, + offset: offset, + } +} + +// CheckClose calls Close on the given io.Closer. If the given *error points to +// nil, it will be assigned the error returned by Close. Otherwise, any error +// returned by Close will be ignored. CheckClose is usually called with defer. +func CheckClose(c io.Closer, err *error) { + if cerr := c.Close(); cerr != nil && *err == nil { + *err = cerr + } +} + +// NewContextWriter wraps a writer to make it respect given Context. +// If there is a blocking write, the returned Writer will return whenever the +// context is cancelled (the return values are n=0 and err=ctx.Err()). +func NewContextWriter(ctx context.Context, w io.Writer) io.Writer { + return ctxio.NewWriter(ctx, w) +} + +// NewContextReader wraps a reader to make it respect given Context. +// If there is a blocking read, the returned Reader will return whenever the +// context is cancelled (the return values are n=0 and err=ctx.Err()). +func NewContextReader(ctx context.Context, r io.Reader) io.Reader { + return ctxio.NewReader(ctx, r) +} + +// NewContextWriteCloser as NewContextWriter but with io.Closer interface. +func NewContextWriteCloser(ctx context.Context, w io.WriteCloser) io.WriteCloser { + ctxw := ctxio.NewWriter(ctx, w) + return NewWriteCloser(ctxw, w) +} + +// NewContextReadCloser as NewContextReader but with io.Closer interface. +func NewContextReadCloser(ctx context.Context, r io.ReadCloser) io.ReadCloser { + ctxr := ctxio.NewReader(ctx, r) + return NewReadCloser(ctxr, r) +} + +type readerOnError struct { + io.Reader + notify func(error) +} + +// NewReaderOnError returns a io.Reader that call the notify function when an +// unexpected (!io.EOF) error happens, after call Read function. +func NewReaderOnError(r io.Reader, notify func(error)) io.Reader { + return &readerOnError{r, notify} +} + +// NewReadCloserOnError returns a io.ReadCloser that call the notify function +// when an unexpected (!io.EOF) error happens, after call Read function. +func NewReadCloserOnError(r io.ReadCloser, notify func(error)) io.ReadCloser { + return NewReadCloser(NewReaderOnError(r, notify), r) +} + +func (r *readerOnError) Read(buf []byte) (n int, err error) { + n, err = r.Reader.Read(buf) + if err != nil && err != io.EOF { + r.notify(err) + } + + return +} + +type writerOnError struct { + io.Writer + notify func(error) +} + +// NewWriterOnError returns a io.Writer that call the notify function when an +// unexpected (!io.EOF) error happens, after call Write function. +func NewWriterOnError(w io.Writer, notify func(error)) io.Writer { + return &writerOnError{w, notify} +} + +// NewWriteCloserOnError returns a io.WriteCloser that call the notify function +// when an unexpected (!io.EOF) error happens, after call Write function. +func NewWriteCloserOnError(w io.WriteCloser, notify func(error)) io.WriteCloser { + return NewWriteCloser(NewWriterOnError(w, notify), w) +} + +func (r *writerOnError) Write(p []byte) (n int, err error) { + n, err = r.Writer.Write(p) + if err != nil && err != io.EOF { + r.notify(err) + } + + return +} diff --git a/vendor/github.com/gorilla/websocket/.gitignore b/vendor/github.com/gorilla/websocket/.gitignore new file mode 100644 index 0000000000..cd3fcd1ef7 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/.gitignore @@ -0,0 +1,25 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe + +.idea/ +*.iml diff --git a/vendor/github.com/gorilla/websocket/AUTHORS b/vendor/github.com/gorilla/websocket/AUTHORS new file mode 100644 index 0000000000..1931f40068 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/AUTHORS @@ -0,0 +1,9 @@ +# This is the official list of Gorilla WebSocket authors for copyright +# purposes. +# +# Please keep the list sorted. + +Gary Burd +Google LLC (https://opensource.google.com/) +Joachim Bauch + diff --git a/vendor/github.com/gorilla/websocket/LICENSE b/vendor/github.com/gorilla/websocket/LICENSE new file mode 100644 index 0000000000..9171c97225 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2013 The Gorilla WebSocket 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. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/gorilla/websocket/README.md b/vendor/github.com/gorilla/websocket/README.md new file mode 100644 index 0000000000..2517a28715 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/README.md @@ -0,0 +1,39 @@ +# Gorilla WebSocket + +[![GoDoc](https://godoc.org/github.com/gorilla/websocket?status.svg)](https://godoc.org/github.com/gorilla/websocket) +[![CircleCI](https://circleci.com/gh/gorilla/websocket.svg?style=svg)](https://circleci.com/gh/gorilla/websocket) + +Gorilla WebSocket is a [Go](http://golang.org/) implementation of the +[WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol. + + +--- + +⚠️ **[The Gorilla WebSocket Package is looking for a new maintainer](https://github.com/gorilla/websocket/issues/370)** + +--- + +### Documentation + +* [API Reference](https://pkg.go.dev/github.com/gorilla/websocket?tab=doc) +* [Chat example](https://github.com/gorilla/websocket/tree/master/examples/chat) +* [Command example](https://github.com/gorilla/websocket/tree/master/examples/command) +* [Client and server example](https://github.com/gorilla/websocket/tree/master/examples/echo) +* [File watch example](https://github.com/gorilla/websocket/tree/master/examples/filewatch) + +### Status + +The Gorilla WebSocket package provides a complete and tested implementation of +the [WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol. The +package API is stable. + +### Installation + + go get github.com/gorilla/websocket + +### Protocol Compliance + +The Gorilla WebSocket package passes the server tests in the [Autobahn Test +Suite](https://github.com/crossbario/autobahn-testsuite) using the application in the [examples/autobahn +subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn). + diff --git a/vendor/github.com/gorilla/websocket/client.go b/vendor/github.com/gorilla/websocket/client.go new file mode 100644 index 0000000000..2efd83555d --- /dev/null +++ b/vendor/github.com/gorilla/websocket/client.go @@ -0,0 +1,422 @@ +// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package websocket + +import ( + "bytes" + "context" + "crypto/tls" + "errors" + "io" + "io/ioutil" + "net" + "net/http" + "net/http/httptrace" + "net/url" + "strings" + "time" +) + +// ErrBadHandshake is returned when the server response to opening handshake is +// invalid. +var ErrBadHandshake = errors.New("websocket: bad handshake") + +var errInvalidCompression = errors.New("websocket: invalid compression negotiation") + +// NewClient creates a new client connection using the given net connection. +// The URL u specifies the host and request URI. Use requestHeader to specify +// the origin (Origin), subprotocols (Sec-WebSocket-Protocol) and cookies +// (Cookie). Use the response.Header to get the selected subprotocol +// (Sec-WebSocket-Protocol) and cookies (Set-Cookie). +// +// If the WebSocket handshake fails, ErrBadHandshake is returned along with a +// non-nil *http.Response so that callers can handle redirects, authentication, +// etc. +// +// Deprecated: Use Dialer instead. +func NewClient(netConn net.Conn, u *url.URL, requestHeader http.Header, readBufSize, writeBufSize int) (c *Conn, response *http.Response, err error) { + d := Dialer{ + ReadBufferSize: readBufSize, + WriteBufferSize: writeBufSize, + NetDial: func(net, addr string) (net.Conn, error) { + return netConn, nil + }, + } + return d.Dial(u.String(), requestHeader) +} + +// A Dialer contains options for connecting to WebSocket server. +// +// It is safe to call Dialer's methods concurrently. +type Dialer struct { + // NetDial specifies the dial function for creating TCP connections. If + // NetDial is nil, net.Dial is used. + NetDial func(network, addr string) (net.Conn, error) + + // NetDialContext specifies the dial function for creating TCP connections. If + // NetDialContext is nil, NetDial is used. + NetDialContext func(ctx context.Context, network, addr string) (net.Conn, error) + + // NetDialTLSContext specifies the dial function for creating TLS/TCP connections. If + // NetDialTLSContext is nil, NetDialContext is used. + // If NetDialTLSContext is set, Dial assumes the TLS handshake is done there and + // TLSClientConfig is ignored. + NetDialTLSContext func(ctx context.Context, network, addr string) (net.Conn, error) + + // Proxy specifies a function to return a proxy for a given + // Request. If the function returns a non-nil error, the + // request is aborted with the provided error. + // If Proxy is nil or returns a nil *URL, no proxy is used. + Proxy func(*http.Request) (*url.URL, error) + + // TLSClientConfig specifies the TLS configuration to use with tls.Client. + // If nil, the default configuration is used. + // If either NetDialTLS or NetDialTLSContext are set, Dial assumes the TLS handshake + // is done there and TLSClientConfig is ignored. + TLSClientConfig *tls.Config + + // HandshakeTimeout specifies the duration for the handshake to complete. + HandshakeTimeout time.Duration + + // ReadBufferSize and WriteBufferSize specify I/O buffer sizes in bytes. If a buffer + // size is zero, then a useful default size is used. The I/O buffer sizes + // do not limit the size of the messages that can be sent or received. + ReadBufferSize, WriteBufferSize int + + // WriteBufferPool is a pool of buffers for write operations. If the value + // is not set, then write buffers are allocated to the connection for the + // lifetime of the connection. + // + // A pool is most useful when the application has a modest volume of writes + // across a large number of connections. + // + // Applications should use a single pool for each unique value of + // WriteBufferSize. + WriteBufferPool BufferPool + + // Subprotocols specifies the client's requested subprotocols. + Subprotocols []string + + // EnableCompression specifies if the client should attempt to negotiate + // per message compression (RFC 7692). Setting this value to true does not + // guarantee that compression will be supported. Currently only "no context + // takeover" modes are supported. + EnableCompression bool + + // Jar specifies the cookie jar. + // If Jar is nil, cookies are not sent in requests and ignored + // in responses. + Jar http.CookieJar +} + +// Dial creates a new client connection by calling DialContext with a background context. +func (d *Dialer) Dial(urlStr string, requestHeader http.Header) (*Conn, *http.Response, error) { + return d.DialContext(context.Background(), urlStr, requestHeader) +} + +var errMalformedURL = errors.New("malformed ws or wss URL") + +func hostPortNoPort(u *url.URL) (hostPort, hostNoPort string) { + hostPort = u.Host + hostNoPort = u.Host + if i := strings.LastIndex(u.Host, ":"); i > strings.LastIndex(u.Host, "]") { + hostNoPort = hostNoPort[:i] + } else { + switch u.Scheme { + case "wss": + hostPort += ":443" + case "https": + hostPort += ":443" + default: + hostPort += ":80" + } + } + return hostPort, hostNoPort +} + +// DefaultDialer is a dialer with all fields set to the default values. +var DefaultDialer = &Dialer{ + Proxy: http.ProxyFromEnvironment, + HandshakeTimeout: 45 * time.Second, +} + +// nilDialer is dialer to use when receiver is nil. +var nilDialer = *DefaultDialer + +// DialContext creates a new client connection. Use requestHeader to specify the +// origin (Origin), subprotocols (Sec-WebSocket-Protocol) and cookies (Cookie). +// Use the response.Header to get the selected subprotocol +// (Sec-WebSocket-Protocol) and cookies (Set-Cookie). +// +// The context will be used in the request and in the Dialer. +// +// If the WebSocket handshake fails, ErrBadHandshake is returned along with a +// non-nil *http.Response so that callers can handle redirects, authentication, +// etcetera. The response body may not contain the entire response and does not +// need to be closed by the application. +func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader http.Header) (*Conn, *http.Response, error) { + if d == nil { + d = &nilDialer + } + + challengeKey, err := generateChallengeKey() + if err != nil { + return nil, nil, err + } + + u, err := url.Parse(urlStr) + if err != nil { + return nil, nil, err + } + + switch u.Scheme { + case "ws": + u.Scheme = "http" + case "wss": + u.Scheme = "https" + default: + return nil, nil, errMalformedURL + } + + if u.User != nil { + // User name and password are not allowed in websocket URIs. + return nil, nil, errMalformedURL + } + + req := &http.Request{ + Method: http.MethodGet, + URL: u, + Proto: "HTTP/1.1", + ProtoMajor: 1, + ProtoMinor: 1, + Header: make(http.Header), + Host: u.Host, + } + req = req.WithContext(ctx) + + // Set the cookies present in the cookie jar of the dialer + if d.Jar != nil { + for _, cookie := range d.Jar.Cookies(u) { + req.AddCookie(cookie) + } + } + + // Set the request headers using the capitalization for names and values in + // RFC examples. Although the capitalization shouldn't matter, there are + // servers that depend on it. The Header.Set method is not used because the + // method canonicalizes the header names. + req.Header["Upgrade"] = []string{"websocket"} + req.Header["Connection"] = []string{"Upgrade"} + req.Header["Sec-WebSocket-Key"] = []string{challengeKey} + req.Header["Sec-WebSocket-Version"] = []string{"13"} + if len(d.Subprotocols) > 0 { + req.Header["Sec-WebSocket-Protocol"] = []string{strings.Join(d.Subprotocols, ", ")} + } + for k, vs := range requestHeader { + switch { + case k == "Host": + if len(vs) > 0 { + req.Host = vs[0] + } + case k == "Upgrade" || + k == "Connection" || + k == "Sec-Websocket-Key" || + k == "Sec-Websocket-Version" || + k == "Sec-Websocket-Extensions" || + (k == "Sec-Websocket-Protocol" && len(d.Subprotocols) > 0): + return nil, nil, errors.New("websocket: duplicate header not allowed: " + k) + case k == "Sec-Websocket-Protocol": + req.Header["Sec-WebSocket-Protocol"] = vs + default: + req.Header[k] = vs + } + } + + if d.EnableCompression { + req.Header["Sec-WebSocket-Extensions"] = []string{"permessage-deflate; server_no_context_takeover; client_no_context_takeover"} + } + + if d.HandshakeTimeout != 0 { + var cancel func() + ctx, cancel = context.WithTimeout(ctx, d.HandshakeTimeout) + defer cancel() + } + + // Get network dial function. + var netDial func(network, add string) (net.Conn, error) + + switch u.Scheme { + case "http": + if d.NetDialContext != nil { + netDial = func(network, addr string) (net.Conn, error) { + return d.NetDialContext(ctx, network, addr) + } + } else if d.NetDial != nil { + netDial = d.NetDial + } + case "https": + if d.NetDialTLSContext != nil { + netDial = func(network, addr string) (net.Conn, error) { + return d.NetDialTLSContext(ctx, network, addr) + } + } else if d.NetDialContext != nil { + netDial = func(network, addr string) (net.Conn, error) { + return d.NetDialContext(ctx, network, addr) + } + } else if d.NetDial != nil { + netDial = d.NetDial + } + default: + return nil, nil, errMalformedURL + } + + if netDial == nil { + netDialer := &net.Dialer{} + netDial = func(network, addr string) (net.Conn, error) { + return netDialer.DialContext(ctx, network, addr) + } + } + + // If needed, wrap the dial function to set the connection deadline. + if deadline, ok := ctx.Deadline(); ok { + forwardDial := netDial + netDial = func(network, addr string) (net.Conn, error) { + c, err := forwardDial(network, addr) + if err != nil { + return nil, err + } + err = c.SetDeadline(deadline) + if err != nil { + c.Close() + return nil, err + } + return c, nil + } + } + + // If needed, wrap the dial function to connect through a proxy. + if d.Proxy != nil { + proxyURL, err := d.Proxy(req) + if err != nil { + return nil, nil, err + } + if proxyURL != nil { + dialer, err := proxy_FromURL(proxyURL, netDialerFunc(netDial)) + if err != nil { + return nil, nil, err + } + netDial = dialer.Dial + } + } + + hostPort, hostNoPort := hostPortNoPort(u) + trace := httptrace.ContextClientTrace(ctx) + if trace != nil && trace.GetConn != nil { + trace.GetConn(hostPort) + } + + netConn, err := netDial("tcp", hostPort) + if trace != nil && trace.GotConn != nil { + trace.GotConn(httptrace.GotConnInfo{ + Conn: netConn, + }) + } + if err != nil { + return nil, nil, err + } + + defer func() { + if netConn != nil { + netConn.Close() + } + }() + + if u.Scheme == "https" && d.NetDialTLSContext == nil { + // If NetDialTLSContext is set, assume that the TLS handshake has already been done + + cfg := cloneTLSConfig(d.TLSClientConfig) + if cfg.ServerName == "" { + cfg.ServerName = hostNoPort + } + tlsConn := tls.Client(netConn, cfg) + netConn = tlsConn + + if trace != nil && trace.TLSHandshakeStart != nil { + trace.TLSHandshakeStart() + } + err := doHandshake(ctx, tlsConn, cfg) + if trace != nil && trace.TLSHandshakeDone != nil { + trace.TLSHandshakeDone(tlsConn.ConnectionState(), err) + } + + if err != nil { + return nil, nil, err + } + } + + conn := newConn(netConn, false, d.ReadBufferSize, d.WriteBufferSize, d.WriteBufferPool, nil, nil) + + if err := req.Write(netConn); err != nil { + return nil, nil, err + } + + if trace != nil && trace.GotFirstResponseByte != nil { + if peek, err := conn.br.Peek(1); err == nil && len(peek) == 1 { + trace.GotFirstResponseByte() + } + } + + resp, err := http.ReadResponse(conn.br, req) + if err != nil { + return nil, nil, err + } + + if d.Jar != nil { + if rc := resp.Cookies(); len(rc) > 0 { + d.Jar.SetCookies(u, rc) + } + } + + if resp.StatusCode != 101 || + !tokenListContainsValue(resp.Header, "Upgrade", "websocket") || + !tokenListContainsValue(resp.Header, "Connection", "upgrade") || + resp.Header.Get("Sec-Websocket-Accept") != computeAcceptKey(challengeKey) { + // Before closing the network connection on return from this + // function, slurp up some of the response to aid application + // debugging. + buf := make([]byte, 1024) + n, _ := io.ReadFull(resp.Body, buf) + resp.Body = ioutil.NopCloser(bytes.NewReader(buf[:n])) + return nil, resp, ErrBadHandshake + } + + for _, ext := range parseExtensions(resp.Header) { + if ext[""] != "permessage-deflate" { + continue + } + _, snct := ext["server_no_context_takeover"] + _, cnct := ext["client_no_context_takeover"] + if !snct || !cnct { + return nil, resp, errInvalidCompression + } + conn.newCompressionWriter = compressNoContextTakeover + conn.newDecompressionReader = decompressNoContextTakeover + break + } + + resp.Body = ioutil.NopCloser(bytes.NewReader([]byte{})) + conn.subprotocol = resp.Header.Get("Sec-Websocket-Protocol") + + netConn.SetDeadline(time.Time{}) + netConn = nil // to avoid close in defer. + return conn, resp, nil +} + +func cloneTLSConfig(cfg *tls.Config) *tls.Config { + if cfg == nil { + return &tls.Config{} + } + return cfg.Clone() +} diff --git a/vendor/github.com/gorilla/websocket/compression.go b/vendor/github.com/gorilla/websocket/compression.go new file mode 100644 index 0000000000..813ffb1e84 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/compression.go @@ -0,0 +1,148 @@ +// Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package websocket + +import ( + "compress/flate" + "errors" + "io" + "strings" + "sync" +) + +const ( + minCompressionLevel = -2 // flate.HuffmanOnly not defined in Go < 1.6 + maxCompressionLevel = flate.BestCompression + defaultCompressionLevel = 1 +) + +var ( + flateWriterPools [maxCompressionLevel - minCompressionLevel + 1]sync.Pool + flateReaderPool = sync.Pool{New: func() interface{} { + return flate.NewReader(nil) + }} +) + +func decompressNoContextTakeover(r io.Reader) io.ReadCloser { + const tail = + // Add four bytes as specified in RFC + "\x00\x00\xff\xff" + + // Add final block to squelch unexpected EOF error from flate reader. + "\x01\x00\x00\xff\xff" + + fr, _ := flateReaderPool.Get().(io.ReadCloser) + fr.(flate.Resetter).Reset(io.MultiReader(r, strings.NewReader(tail)), nil) + return &flateReadWrapper{fr} +} + +func isValidCompressionLevel(level int) bool { + return minCompressionLevel <= level && level <= maxCompressionLevel +} + +func compressNoContextTakeover(w io.WriteCloser, level int) io.WriteCloser { + p := &flateWriterPools[level-minCompressionLevel] + tw := &truncWriter{w: w} + fw, _ := p.Get().(*flate.Writer) + if fw == nil { + fw, _ = flate.NewWriter(tw, level) + } else { + fw.Reset(tw) + } + return &flateWriteWrapper{fw: fw, tw: tw, p: p} +} + +// truncWriter is an io.Writer that writes all but the last four bytes of the +// stream to another io.Writer. +type truncWriter struct { + w io.WriteCloser + n int + p [4]byte +} + +func (w *truncWriter) Write(p []byte) (int, error) { + n := 0 + + // fill buffer first for simplicity. + if w.n < len(w.p) { + n = copy(w.p[w.n:], p) + p = p[n:] + w.n += n + if len(p) == 0 { + return n, nil + } + } + + m := len(p) + if m > len(w.p) { + m = len(w.p) + } + + if nn, err := w.w.Write(w.p[:m]); err != nil { + return n + nn, err + } + + copy(w.p[:], w.p[m:]) + copy(w.p[len(w.p)-m:], p[len(p)-m:]) + nn, err := w.w.Write(p[:len(p)-m]) + return n + nn, err +} + +type flateWriteWrapper struct { + fw *flate.Writer + tw *truncWriter + p *sync.Pool +} + +func (w *flateWriteWrapper) Write(p []byte) (int, error) { + if w.fw == nil { + return 0, errWriteClosed + } + return w.fw.Write(p) +} + +func (w *flateWriteWrapper) Close() error { + if w.fw == nil { + return errWriteClosed + } + err1 := w.fw.Flush() + w.p.Put(w.fw) + w.fw = nil + if w.tw.p != [4]byte{0, 0, 0xff, 0xff} { + return errors.New("websocket: internal error, unexpected bytes at end of flate stream") + } + err2 := w.tw.w.Close() + if err1 != nil { + return err1 + } + return err2 +} + +type flateReadWrapper struct { + fr io.ReadCloser +} + +func (r *flateReadWrapper) Read(p []byte) (int, error) { + if r.fr == nil { + return 0, io.ErrClosedPipe + } + n, err := r.fr.Read(p) + if err == io.EOF { + // Preemptively place the reader back in the pool. This helps with + // scenarios where the application does not call NextReader() soon after + // this final read. + r.Close() + } + return n, err +} + +func (r *flateReadWrapper) Close() error { + if r.fr == nil { + return io.ErrClosedPipe + } + err := r.fr.Close() + flateReaderPool.Put(r.fr) + r.fr = nil + return err +} diff --git a/vendor/github.com/gorilla/websocket/conn.go b/vendor/github.com/gorilla/websocket/conn.go new file mode 100644 index 0000000000..331eebc850 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/conn.go @@ -0,0 +1,1230 @@ +// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package websocket + +import ( + "bufio" + "encoding/binary" + "errors" + "io" + "io/ioutil" + "math/rand" + "net" + "strconv" + "strings" + "sync" + "time" + "unicode/utf8" +) + +const ( + // Frame header byte 0 bits from Section 5.2 of RFC 6455 + finalBit = 1 << 7 + rsv1Bit = 1 << 6 + rsv2Bit = 1 << 5 + rsv3Bit = 1 << 4 + + // Frame header byte 1 bits from Section 5.2 of RFC 6455 + maskBit = 1 << 7 + + maxFrameHeaderSize = 2 + 8 + 4 // Fixed header + length + mask + maxControlFramePayloadSize = 125 + + writeWait = time.Second + + defaultReadBufferSize = 4096 + defaultWriteBufferSize = 4096 + + continuationFrame = 0 + noFrame = -1 +) + +// Close codes defined in RFC 6455, section 11.7. +const ( + CloseNormalClosure = 1000 + CloseGoingAway = 1001 + CloseProtocolError = 1002 + CloseUnsupportedData = 1003 + CloseNoStatusReceived = 1005 + CloseAbnormalClosure = 1006 + CloseInvalidFramePayloadData = 1007 + ClosePolicyViolation = 1008 + CloseMessageTooBig = 1009 + CloseMandatoryExtension = 1010 + CloseInternalServerErr = 1011 + CloseServiceRestart = 1012 + CloseTryAgainLater = 1013 + CloseTLSHandshake = 1015 +) + +// The message types are defined in RFC 6455, section 11.8. +const ( + // TextMessage denotes a text data message. The text message payload is + // interpreted as UTF-8 encoded text data. + TextMessage = 1 + + // BinaryMessage denotes a binary data message. + BinaryMessage = 2 + + // CloseMessage denotes a close control message. The optional message + // payload contains a numeric code and text. Use the FormatCloseMessage + // function to format a close message payload. + CloseMessage = 8 + + // PingMessage denotes a ping control message. The optional message payload + // is UTF-8 encoded text. + PingMessage = 9 + + // PongMessage denotes a pong control message. The optional message payload + // is UTF-8 encoded text. + PongMessage = 10 +) + +// ErrCloseSent is returned when the application writes a message to the +// connection after sending a close message. +var ErrCloseSent = errors.New("websocket: close sent") + +// ErrReadLimit is returned when reading a message that is larger than the +// read limit set for the connection. +var ErrReadLimit = errors.New("websocket: read limit exceeded") + +// netError satisfies the net Error interface. +type netError struct { + msg string + temporary bool + timeout bool +} + +func (e *netError) Error() string { return e.msg } +func (e *netError) Temporary() bool { return e.temporary } +func (e *netError) Timeout() bool { return e.timeout } + +// CloseError represents a close message. +type CloseError struct { + // Code is defined in RFC 6455, section 11.7. + Code int + + // Text is the optional text payload. + Text string +} + +func (e *CloseError) Error() string { + s := []byte("websocket: close ") + s = strconv.AppendInt(s, int64(e.Code), 10) + switch e.Code { + case CloseNormalClosure: + s = append(s, " (normal)"...) + case CloseGoingAway: + s = append(s, " (going away)"...) + case CloseProtocolError: + s = append(s, " (protocol error)"...) + case CloseUnsupportedData: + s = append(s, " (unsupported data)"...) + case CloseNoStatusReceived: + s = append(s, " (no status)"...) + case CloseAbnormalClosure: + s = append(s, " (abnormal closure)"...) + case CloseInvalidFramePayloadData: + s = append(s, " (invalid payload data)"...) + case ClosePolicyViolation: + s = append(s, " (policy violation)"...) + case CloseMessageTooBig: + s = append(s, " (message too big)"...) + case CloseMandatoryExtension: + s = append(s, " (mandatory extension missing)"...) + case CloseInternalServerErr: + s = append(s, " (internal server error)"...) + case CloseTLSHandshake: + s = append(s, " (TLS handshake error)"...) + } + if e.Text != "" { + s = append(s, ": "...) + s = append(s, e.Text...) + } + return string(s) +} + +// IsCloseError returns boolean indicating whether the error is a *CloseError +// with one of the specified codes. +func IsCloseError(err error, codes ...int) bool { + if e, ok := err.(*CloseError); ok { + for _, code := range codes { + if e.Code == code { + return true + } + } + } + return false +} + +// IsUnexpectedCloseError returns boolean indicating whether the error is a +// *CloseError with a code not in the list of expected codes. +func IsUnexpectedCloseError(err error, expectedCodes ...int) bool { + if e, ok := err.(*CloseError); ok { + for _, code := range expectedCodes { + if e.Code == code { + return false + } + } + return true + } + return false +} + +var ( + errWriteTimeout = &netError{msg: "websocket: write timeout", timeout: true, temporary: true} + errUnexpectedEOF = &CloseError{Code: CloseAbnormalClosure, Text: io.ErrUnexpectedEOF.Error()} + errBadWriteOpCode = errors.New("websocket: bad write message type") + errWriteClosed = errors.New("websocket: write closed") + errInvalidControlFrame = errors.New("websocket: invalid control frame") +) + +func newMaskKey() [4]byte { + n := rand.Uint32() + return [4]byte{byte(n), byte(n >> 8), byte(n >> 16), byte(n >> 24)} +} + +func hideTempErr(err error) error { + if e, ok := err.(net.Error); ok && e.Temporary() { + err = &netError{msg: e.Error(), timeout: e.Timeout()} + } + return err +} + +func isControl(frameType int) bool { + return frameType == CloseMessage || frameType == PingMessage || frameType == PongMessage +} + +func isData(frameType int) bool { + return frameType == TextMessage || frameType == BinaryMessage +} + +var validReceivedCloseCodes = map[int]bool{ + // see http://www.iana.org/assignments/websocket/websocket.xhtml#close-code-number + + CloseNormalClosure: true, + CloseGoingAway: true, + CloseProtocolError: true, + CloseUnsupportedData: true, + CloseNoStatusReceived: false, + CloseAbnormalClosure: false, + CloseInvalidFramePayloadData: true, + ClosePolicyViolation: true, + CloseMessageTooBig: true, + CloseMandatoryExtension: true, + CloseInternalServerErr: true, + CloseServiceRestart: true, + CloseTryAgainLater: true, + CloseTLSHandshake: false, +} + +func isValidReceivedCloseCode(code int) bool { + return validReceivedCloseCodes[code] || (code >= 3000 && code <= 4999) +} + +// BufferPool represents a pool of buffers. The *sync.Pool type satisfies this +// interface. The type of the value stored in a pool is not specified. +type BufferPool interface { + // Get gets a value from the pool or returns nil if the pool is empty. + Get() interface{} + // Put adds a value to the pool. + Put(interface{}) +} + +// writePoolData is the type added to the write buffer pool. This wrapper is +// used to prevent applications from peeking at and depending on the values +// added to the pool. +type writePoolData struct{ buf []byte } + +// The Conn type represents a WebSocket connection. +type Conn struct { + conn net.Conn + isServer bool + subprotocol string + + // Write fields + mu chan struct{} // used as mutex to protect write to conn + writeBuf []byte // frame is constructed in this buffer. + writePool BufferPool + writeBufSize int + writeDeadline time.Time + writer io.WriteCloser // the current writer returned to the application + isWriting bool // for best-effort concurrent write detection + + writeErrMu sync.Mutex + writeErr error + + enableWriteCompression bool + compressionLevel int + newCompressionWriter func(io.WriteCloser, int) io.WriteCloser + + // Read fields + reader io.ReadCloser // the current reader returned to the application + readErr error + br *bufio.Reader + // bytes remaining in current frame. + // set setReadRemaining to safely update this value and prevent overflow + readRemaining int64 + readFinal bool // true the current message has more frames. + readLength int64 // Message size. + readLimit int64 // Maximum message size. + readMaskPos int + readMaskKey [4]byte + handlePong func(string) error + handlePing func(string) error + handleClose func(int, string) error + readErrCount int + messageReader *messageReader // the current low-level reader + + readDecompress bool // whether last read frame had RSV1 set + newDecompressionReader func(io.Reader) io.ReadCloser +} + +func newConn(conn net.Conn, isServer bool, readBufferSize, writeBufferSize int, writeBufferPool BufferPool, br *bufio.Reader, writeBuf []byte) *Conn { + + if br == nil { + if readBufferSize == 0 { + readBufferSize = defaultReadBufferSize + } else if readBufferSize < maxControlFramePayloadSize { + // must be large enough for control frame + readBufferSize = maxControlFramePayloadSize + } + br = bufio.NewReaderSize(conn, readBufferSize) + } + + if writeBufferSize <= 0 { + writeBufferSize = defaultWriteBufferSize + } + writeBufferSize += maxFrameHeaderSize + + if writeBuf == nil && writeBufferPool == nil { + writeBuf = make([]byte, writeBufferSize) + } + + mu := make(chan struct{}, 1) + mu <- struct{}{} + c := &Conn{ + isServer: isServer, + br: br, + conn: conn, + mu: mu, + readFinal: true, + writeBuf: writeBuf, + writePool: writeBufferPool, + writeBufSize: writeBufferSize, + enableWriteCompression: true, + compressionLevel: defaultCompressionLevel, + } + c.SetCloseHandler(nil) + c.SetPingHandler(nil) + c.SetPongHandler(nil) + return c +} + +// setReadRemaining tracks the number of bytes remaining on the connection. If n +// overflows, an ErrReadLimit is returned. +func (c *Conn) setReadRemaining(n int64) error { + if n < 0 { + return ErrReadLimit + } + + c.readRemaining = n + return nil +} + +// Subprotocol returns the negotiated protocol for the connection. +func (c *Conn) Subprotocol() string { + return c.subprotocol +} + +// Close closes the underlying network connection without sending or waiting +// for a close message. +func (c *Conn) Close() error { + return c.conn.Close() +} + +// LocalAddr returns the local network address. +func (c *Conn) LocalAddr() net.Addr { + return c.conn.LocalAddr() +} + +// RemoteAddr returns the remote network address. +func (c *Conn) RemoteAddr() net.Addr { + return c.conn.RemoteAddr() +} + +// Write methods + +func (c *Conn) writeFatal(err error) error { + err = hideTempErr(err) + c.writeErrMu.Lock() + if c.writeErr == nil { + c.writeErr = err + } + c.writeErrMu.Unlock() + return err +} + +func (c *Conn) read(n int) ([]byte, error) { + p, err := c.br.Peek(n) + if err == io.EOF { + err = errUnexpectedEOF + } + c.br.Discard(len(p)) + return p, err +} + +func (c *Conn) write(frameType int, deadline time.Time, buf0, buf1 []byte) error { + <-c.mu + defer func() { c.mu <- struct{}{} }() + + c.writeErrMu.Lock() + err := c.writeErr + c.writeErrMu.Unlock() + if err != nil { + return err + } + + c.conn.SetWriteDeadline(deadline) + if len(buf1) == 0 { + _, err = c.conn.Write(buf0) + } else { + err = c.writeBufs(buf0, buf1) + } + if err != nil { + return c.writeFatal(err) + } + if frameType == CloseMessage { + c.writeFatal(ErrCloseSent) + } + return nil +} + +func (c *Conn) writeBufs(bufs ...[]byte) error { + b := net.Buffers(bufs) + _, err := b.WriteTo(c.conn) + return err +} + +// WriteControl writes a control message with the given deadline. The allowed +// message types are CloseMessage, PingMessage and PongMessage. +func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) error { + if !isControl(messageType) { + return errBadWriteOpCode + } + if len(data) > maxControlFramePayloadSize { + return errInvalidControlFrame + } + + b0 := byte(messageType) | finalBit + b1 := byte(len(data)) + if !c.isServer { + b1 |= maskBit + } + + buf := make([]byte, 0, maxFrameHeaderSize+maxControlFramePayloadSize) + buf = append(buf, b0, b1) + + if c.isServer { + buf = append(buf, data...) + } else { + key := newMaskKey() + buf = append(buf, key[:]...) + buf = append(buf, data...) + maskBytes(key, 0, buf[6:]) + } + + d := 1000 * time.Hour + if !deadline.IsZero() { + d = deadline.Sub(time.Now()) + if d < 0 { + return errWriteTimeout + } + } + + timer := time.NewTimer(d) + select { + case <-c.mu: + timer.Stop() + case <-timer.C: + return errWriteTimeout + } + defer func() { c.mu <- struct{}{} }() + + c.writeErrMu.Lock() + err := c.writeErr + c.writeErrMu.Unlock() + if err != nil { + return err + } + + c.conn.SetWriteDeadline(deadline) + _, err = c.conn.Write(buf) + if err != nil { + return c.writeFatal(err) + } + if messageType == CloseMessage { + c.writeFatal(ErrCloseSent) + } + return err +} + +// beginMessage prepares a connection and message writer for a new message. +func (c *Conn) beginMessage(mw *messageWriter, messageType int) error { + // Close previous writer if not already closed by the application. It's + // probably better to return an error in this situation, but we cannot + // change this without breaking existing applications. + if c.writer != nil { + c.writer.Close() + c.writer = nil + } + + if !isControl(messageType) && !isData(messageType) { + return errBadWriteOpCode + } + + c.writeErrMu.Lock() + err := c.writeErr + c.writeErrMu.Unlock() + if err != nil { + return err + } + + mw.c = c + mw.frameType = messageType + mw.pos = maxFrameHeaderSize + + if c.writeBuf == nil { + wpd, ok := c.writePool.Get().(writePoolData) + if ok { + c.writeBuf = wpd.buf + } else { + c.writeBuf = make([]byte, c.writeBufSize) + } + } + return nil +} + +// NextWriter returns a writer for the next message to send. The writer's Close +// method flushes the complete message to the network. +// +// There can be at most one open writer on a connection. NextWriter closes the +// previous writer if the application has not already done so. +// +// All message types (TextMessage, BinaryMessage, CloseMessage, PingMessage and +// PongMessage) are supported. +func (c *Conn) NextWriter(messageType int) (io.WriteCloser, error) { + var mw messageWriter + if err := c.beginMessage(&mw, messageType); err != nil { + return nil, err + } + c.writer = &mw + if c.newCompressionWriter != nil && c.enableWriteCompression && isData(messageType) { + w := c.newCompressionWriter(c.writer, c.compressionLevel) + mw.compress = true + c.writer = w + } + return c.writer, nil +} + +type messageWriter struct { + c *Conn + compress bool // whether next call to flushFrame should set RSV1 + pos int // end of data in writeBuf. + frameType int // type of the current frame. + err error +} + +func (w *messageWriter) endMessage(err error) error { + if w.err != nil { + return err + } + c := w.c + w.err = err + c.writer = nil + if c.writePool != nil { + c.writePool.Put(writePoolData{buf: c.writeBuf}) + c.writeBuf = nil + } + return err +} + +// flushFrame writes buffered data and extra as a frame to the network. The +// final argument indicates that this is the last frame in the message. +func (w *messageWriter) flushFrame(final bool, extra []byte) error { + c := w.c + length := w.pos - maxFrameHeaderSize + len(extra) + + // Check for invalid control frames. + if isControl(w.frameType) && + (!final || length > maxControlFramePayloadSize) { + return w.endMessage(errInvalidControlFrame) + } + + b0 := byte(w.frameType) + if final { + b0 |= finalBit + } + if w.compress { + b0 |= rsv1Bit + } + w.compress = false + + b1 := byte(0) + if !c.isServer { + b1 |= maskBit + } + + // Assume that the frame starts at beginning of c.writeBuf. + framePos := 0 + if c.isServer { + // Adjust up if mask not included in the header. + framePos = 4 + } + + switch { + case length >= 65536: + c.writeBuf[framePos] = b0 + c.writeBuf[framePos+1] = b1 | 127 + binary.BigEndian.PutUint64(c.writeBuf[framePos+2:], uint64(length)) + case length > 125: + framePos += 6 + c.writeBuf[framePos] = b0 + c.writeBuf[framePos+1] = b1 | 126 + binary.BigEndian.PutUint16(c.writeBuf[framePos+2:], uint16(length)) + default: + framePos += 8 + c.writeBuf[framePos] = b0 + c.writeBuf[framePos+1] = b1 | byte(length) + } + + if !c.isServer { + key := newMaskKey() + copy(c.writeBuf[maxFrameHeaderSize-4:], key[:]) + maskBytes(key, 0, c.writeBuf[maxFrameHeaderSize:w.pos]) + if len(extra) > 0 { + return w.endMessage(c.writeFatal(errors.New("websocket: internal error, extra used in client mode"))) + } + } + + // Write the buffers to the connection with best-effort detection of + // concurrent writes. See the concurrency section in the package + // documentation for more info. + + if c.isWriting { + panic("concurrent write to websocket connection") + } + c.isWriting = true + + err := c.write(w.frameType, c.writeDeadline, c.writeBuf[framePos:w.pos], extra) + + if !c.isWriting { + panic("concurrent write to websocket connection") + } + c.isWriting = false + + if err != nil { + return w.endMessage(err) + } + + if final { + w.endMessage(errWriteClosed) + return nil + } + + // Setup for next frame. + w.pos = maxFrameHeaderSize + w.frameType = continuationFrame + return nil +} + +func (w *messageWriter) ncopy(max int) (int, error) { + n := len(w.c.writeBuf) - w.pos + if n <= 0 { + if err := w.flushFrame(false, nil); err != nil { + return 0, err + } + n = len(w.c.writeBuf) - w.pos + } + if n > max { + n = max + } + return n, nil +} + +func (w *messageWriter) Write(p []byte) (int, error) { + if w.err != nil { + return 0, w.err + } + + if len(p) > 2*len(w.c.writeBuf) && w.c.isServer { + // Don't buffer large messages. + err := w.flushFrame(false, p) + if err != nil { + return 0, err + } + return len(p), nil + } + + nn := len(p) + for len(p) > 0 { + n, err := w.ncopy(len(p)) + if err != nil { + return 0, err + } + copy(w.c.writeBuf[w.pos:], p[:n]) + w.pos += n + p = p[n:] + } + return nn, nil +} + +func (w *messageWriter) WriteString(p string) (int, error) { + if w.err != nil { + return 0, w.err + } + + nn := len(p) + for len(p) > 0 { + n, err := w.ncopy(len(p)) + if err != nil { + return 0, err + } + copy(w.c.writeBuf[w.pos:], p[:n]) + w.pos += n + p = p[n:] + } + return nn, nil +} + +func (w *messageWriter) ReadFrom(r io.Reader) (nn int64, err error) { + if w.err != nil { + return 0, w.err + } + for { + if w.pos == len(w.c.writeBuf) { + err = w.flushFrame(false, nil) + if err != nil { + break + } + } + var n int + n, err = r.Read(w.c.writeBuf[w.pos:]) + w.pos += n + nn += int64(n) + if err != nil { + if err == io.EOF { + err = nil + } + break + } + } + return nn, err +} + +func (w *messageWriter) Close() error { + if w.err != nil { + return w.err + } + return w.flushFrame(true, nil) +} + +// WritePreparedMessage writes prepared message into connection. +func (c *Conn) WritePreparedMessage(pm *PreparedMessage) error { + frameType, frameData, err := pm.frame(prepareKey{ + isServer: c.isServer, + compress: c.newCompressionWriter != nil && c.enableWriteCompression && isData(pm.messageType), + compressionLevel: c.compressionLevel, + }) + if err != nil { + return err + } + if c.isWriting { + panic("concurrent write to websocket connection") + } + c.isWriting = true + err = c.write(frameType, c.writeDeadline, frameData, nil) + if !c.isWriting { + panic("concurrent write to websocket connection") + } + c.isWriting = false + return err +} + +// WriteMessage is a helper method for getting a writer using NextWriter, +// writing the message and closing the writer. +func (c *Conn) WriteMessage(messageType int, data []byte) error { + + if c.isServer && (c.newCompressionWriter == nil || !c.enableWriteCompression) { + // Fast path with no allocations and single frame. + + var mw messageWriter + if err := c.beginMessage(&mw, messageType); err != nil { + return err + } + n := copy(c.writeBuf[mw.pos:], data) + mw.pos += n + data = data[n:] + return mw.flushFrame(true, data) + } + + w, err := c.NextWriter(messageType) + if err != nil { + return err + } + if _, err = w.Write(data); err != nil { + return err + } + return w.Close() +} + +// SetWriteDeadline sets the write deadline on the underlying network +// connection. After a write has timed out, the websocket state is corrupt and +// all future writes will return an error. A zero value for t means writes will +// not time out. +func (c *Conn) SetWriteDeadline(t time.Time) error { + c.writeDeadline = t + return nil +} + +// Read methods + +func (c *Conn) advanceFrame() (int, error) { + // 1. Skip remainder of previous frame. + + if c.readRemaining > 0 { + if _, err := io.CopyN(ioutil.Discard, c.br, c.readRemaining); err != nil { + return noFrame, err + } + } + + // 2. Read and parse first two bytes of frame header. + // To aid debugging, collect and report all errors in the first two bytes + // of the header. + + var errors []string + + p, err := c.read(2) + if err != nil { + return noFrame, err + } + + frameType := int(p[0] & 0xf) + final := p[0]&finalBit != 0 + rsv1 := p[0]&rsv1Bit != 0 + rsv2 := p[0]&rsv2Bit != 0 + rsv3 := p[0]&rsv3Bit != 0 + mask := p[1]&maskBit != 0 + c.setReadRemaining(int64(p[1] & 0x7f)) + + c.readDecompress = false + if rsv1 { + if c.newDecompressionReader != nil { + c.readDecompress = true + } else { + errors = append(errors, "RSV1 set") + } + } + + if rsv2 { + errors = append(errors, "RSV2 set") + } + + if rsv3 { + errors = append(errors, "RSV3 set") + } + + switch frameType { + case CloseMessage, PingMessage, PongMessage: + if c.readRemaining > maxControlFramePayloadSize { + errors = append(errors, "len > 125 for control") + } + if !final { + errors = append(errors, "FIN not set on control") + } + case TextMessage, BinaryMessage: + if !c.readFinal { + errors = append(errors, "data before FIN") + } + c.readFinal = final + case continuationFrame: + if c.readFinal { + errors = append(errors, "continuation after FIN") + } + c.readFinal = final + default: + errors = append(errors, "bad opcode "+strconv.Itoa(frameType)) + } + + if mask != c.isServer { + errors = append(errors, "bad MASK") + } + + if len(errors) > 0 { + return noFrame, c.handleProtocolError(strings.Join(errors, ", ")) + } + + // 3. Read and parse frame length as per + // https://tools.ietf.org/html/rfc6455#section-5.2 + // + // The length of the "Payload data", in bytes: if 0-125, that is the payload + // length. + // - If 126, the following 2 bytes interpreted as a 16-bit unsigned + // integer are the payload length. + // - If 127, the following 8 bytes interpreted as + // a 64-bit unsigned integer (the most significant bit MUST be 0) are the + // payload length. Multibyte length quantities are expressed in network byte + // order. + + switch c.readRemaining { + case 126: + p, err := c.read(2) + if err != nil { + return noFrame, err + } + + if err := c.setReadRemaining(int64(binary.BigEndian.Uint16(p))); err != nil { + return noFrame, err + } + case 127: + p, err := c.read(8) + if err != nil { + return noFrame, err + } + + if err := c.setReadRemaining(int64(binary.BigEndian.Uint64(p))); err != nil { + return noFrame, err + } + } + + // 4. Handle frame masking. + + if mask { + c.readMaskPos = 0 + p, err := c.read(len(c.readMaskKey)) + if err != nil { + return noFrame, err + } + copy(c.readMaskKey[:], p) + } + + // 5. For text and binary messages, enforce read limit and return. + + if frameType == continuationFrame || frameType == TextMessage || frameType == BinaryMessage { + + c.readLength += c.readRemaining + // Don't allow readLength to overflow in the presence of a large readRemaining + // counter. + if c.readLength < 0 { + return noFrame, ErrReadLimit + } + + if c.readLimit > 0 && c.readLength > c.readLimit { + c.WriteControl(CloseMessage, FormatCloseMessage(CloseMessageTooBig, ""), time.Now().Add(writeWait)) + return noFrame, ErrReadLimit + } + + return frameType, nil + } + + // 6. Read control frame payload. + + var payload []byte + if c.readRemaining > 0 { + payload, err = c.read(int(c.readRemaining)) + c.setReadRemaining(0) + if err != nil { + return noFrame, err + } + if c.isServer { + maskBytes(c.readMaskKey, 0, payload) + } + } + + // 7. Process control frame payload. + + switch frameType { + case PongMessage: + if err := c.handlePong(string(payload)); err != nil { + return noFrame, err + } + case PingMessage: + if err := c.handlePing(string(payload)); err != nil { + return noFrame, err + } + case CloseMessage: + closeCode := CloseNoStatusReceived + closeText := "" + if len(payload) >= 2 { + closeCode = int(binary.BigEndian.Uint16(payload)) + if !isValidReceivedCloseCode(closeCode) { + return noFrame, c.handleProtocolError("bad close code " + strconv.Itoa(closeCode)) + } + closeText = string(payload[2:]) + if !utf8.ValidString(closeText) { + return noFrame, c.handleProtocolError("invalid utf8 payload in close frame") + } + } + if err := c.handleClose(closeCode, closeText); err != nil { + return noFrame, err + } + return noFrame, &CloseError{Code: closeCode, Text: closeText} + } + + return frameType, nil +} + +func (c *Conn) handleProtocolError(message string) error { + data := FormatCloseMessage(CloseProtocolError, message) + if len(data) > maxControlFramePayloadSize { + data = data[:maxControlFramePayloadSize] + } + c.WriteControl(CloseMessage, data, time.Now().Add(writeWait)) + return errors.New("websocket: " + message) +} + +// NextReader returns the next data message received from the peer. The +// returned messageType is either TextMessage or BinaryMessage. +// +// There can be at most one open reader on a connection. NextReader discards +// the previous message if the application has not already consumed it. +// +// Applications must break out of the application's read loop when this method +// returns a non-nil error value. Errors returned from this method are +// permanent. Once this method returns a non-nil error, all subsequent calls to +// this method return the same error. +func (c *Conn) NextReader() (messageType int, r io.Reader, err error) { + // Close previous reader, only relevant for decompression. + if c.reader != nil { + c.reader.Close() + c.reader = nil + } + + c.messageReader = nil + c.readLength = 0 + + for c.readErr == nil { + frameType, err := c.advanceFrame() + if err != nil { + c.readErr = hideTempErr(err) + break + } + + if frameType == TextMessage || frameType == BinaryMessage { + c.messageReader = &messageReader{c} + c.reader = c.messageReader + if c.readDecompress { + c.reader = c.newDecompressionReader(c.reader) + } + return frameType, c.reader, nil + } + } + + // Applications that do handle the error returned from this method spin in + // tight loop on connection failure. To help application developers detect + // this error, panic on repeated reads to the failed connection. + c.readErrCount++ + if c.readErrCount >= 1000 { + panic("repeated read on failed websocket connection") + } + + return noFrame, nil, c.readErr +} + +type messageReader struct{ c *Conn } + +func (r *messageReader) Read(b []byte) (int, error) { + c := r.c + if c.messageReader != r { + return 0, io.EOF + } + + for c.readErr == nil { + + if c.readRemaining > 0 { + if int64(len(b)) > c.readRemaining { + b = b[:c.readRemaining] + } + n, err := c.br.Read(b) + c.readErr = hideTempErr(err) + if c.isServer { + c.readMaskPos = maskBytes(c.readMaskKey, c.readMaskPos, b[:n]) + } + rem := c.readRemaining + rem -= int64(n) + c.setReadRemaining(rem) + if c.readRemaining > 0 && c.readErr == io.EOF { + c.readErr = errUnexpectedEOF + } + return n, c.readErr + } + + if c.readFinal { + c.messageReader = nil + return 0, io.EOF + } + + frameType, err := c.advanceFrame() + switch { + case err != nil: + c.readErr = hideTempErr(err) + case frameType == TextMessage || frameType == BinaryMessage: + c.readErr = errors.New("websocket: internal error, unexpected text or binary in Reader") + } + } + + err := c.readErr + if err == io.EOF && c.messageReader == r { + err = errUnexpectedEOF + } + return 0, err +} + +func (r *messageReader) Close() error { + return nil +} + +// ReadMessage is a helper method for getting a reader using NextReader and +// reading from that reader to a buffer. +func (c *Conn) ReadMessage() (messageType int, p []byte, err error) { + var r io.Reader + messageType, r, err = c.NextReader() + if err != nil { + return messageType, nil, err + } + p, err = ioutil.ReadAll(r) + return messageType, p, err +} + +// SetReadDeadline sets the read deadline on the underlying network connection. +// After a read has timed out, the websocket connection state is corrupt and +// all future reads will return an error. A zero value for t means reads will +// not time out. +func (c *Conn) SetReadDeadline(t time.Time) error { + return c.conn.SetReadDeadline(t) +} + +// SetReadLimit sets the maximum size in bytes for a message read from the peer. If a +// message exceeds the limit, the connection sends a close message to the peer +// and returns ErrReadLimit to the application. +func (c *Conn) SetReadLimit(limit int64) { + c.readLimit = limit +} + +// CloseHandler returns the current close handler +func (c *Conn) CloseHandler() func(code int, text string) error { + return c.handleClose +} + +// SetCloseHandler sets the handler for close messages received from the peer. +// The code argument to h is the received close code or CloseNoStatusReceived +// if the close message is empty. The default close handler sends a close +// message back to the peer. +// +// The handler function is called from the NextReader, ReadMessage and message +// reader Read methods. The application must read the connection to process +// close messages as described in the section on Control Messages above. +// +// The connection read methods return a CloseError when a close message is +// received. Most applications should handle close messages as part of their +// normal error handling. Applications should only set a close handler when the +// application must perform some action before sending a close message back to +// the peer. +func (c *Conn) SetCloseHandler(h func(code int, text string) error) { + if h == nil { + h = func(code int, text string) error { + message := FormatCloseMessage(code, "") + c.WriteControl(CloseMessage, message, time.Now().Add(writeWait)) + return nil + } + } + c.handleClose = h +} + +// PingHandler returns the current ping handler +func (c *Conn) PingHandler() func(appData string) error { + return c.handlePing +} + +// SetPingHandler sets the handler for ping messages received from the peer. +// The appData argument to h is the PING message application data. The default +// ping handler sends a pong to the peer. +// +// The handler function is called from the NextReader, ReadMessage and message +// reader Read methods. The application must read the connection to process +// ping messages as described in the section on Control Messages above. +func (c *Conn) SetPingHandler(h func(appData string) error) { + if h == nil { + h = func(message string) error { + err := c.WriteControl(PongMessage, []byte(message), time.Now().Add(writeWait)) + if err == ErrCloseSent { + return nil + } else if e, ok := err.(net.Error); ok && e.Temporary() { + return nil + } + return err + } + } + c.handlePing = h +} + +// PongHandler returns the current pong handler +func (c *Conn) PongHandler() func(appData string) error { + return c.handlePong +} + +// SetPongHandler sets the handler for pong messages received from the peer. +// The appData argument to h is the PONG message application data. The default +// pong handler does nothing. +// +// The handler function is called from the NextReader, ReadMessage and message +// reader Read methods. The application must read the connection to process +// pong messages as described in the section on Control Messages above. +func (c *Conn) SetPongHandler(h func(appData string) error) { + if h == nil { + h = func(string) error { return nil } + } + c.handlePong = h +} + +// UnderlyingConn returns the internal net.Conn. This can be used to further +// modifications to connection specific flags. +func (c *Conn) UnderlyingConn() net.Conn { + return c.conn +} + +// EnableWriteCompression enables and disables write compression of +// subsequent text and binary messages. This function is a noop if +// compression was not negotiated with the peer. +func (c *Conn) EnableWriteCompression(enable bool) { + c.enableWriteCompression = enable +} + +// SetCompressionLevel sets the flate compression level for subsequent text and +// binary messages. This function is a noop if compression was not negotiated +// with the peer. See the compress/flate package for a description of +// compression levels. +func (c *Conn) SetCompressionLevel(level int) error { + if !isValidCompressionLevel(level) { + return errors.New("websocket: invalid compression level") + } + c.compressionLevel = level + return nil +} + +// FormatCloseMessage formats closeCode and text as a WebSocket close message. +// An empty message is returned for code CloseNoStatusReceived. +func FormatCloseMessage(closeCode int, text string) []byte { + if closeCode == CloseNoStatusReceived { + // Return empty message because it's illegal to send + // CloseNoStatusReceived. Return non-nil value in case application + // checks for nil. + return []byte{} + } + buf := make([]byte, 2+len(text)) + binary.BigEndian.PutUint16(buf, uint16(closeCode)) + copy(buf[2:], text) + return buf +} diff --git a/vendor/github.com/gorilla/websocket/doc.go b/vendor/github.com/gorilla/websocket/doc.go new file mode 100644 index 0000000000..8db0cef95a --- /dev/null +++ b/vendor/github.com/gorilla/websocket/doc.go @@ -0,0 +1,227 @@ +// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package websocket implements the WebSocket protocol defined in RFC 6455. +// +// Overview +// +// The Conn type represents a WebSocket connection. A server application calls +// the Upgrader.Upgrade method from an HTTP request handler to get a *Conn: +// +// var upgrader = websocket.Upgrader{ +// ReadBufferSize: 1024, +// WriteBufferSize: 1024, +// } +// +// func handler(w http.ResponseWriter, r *http.Request) { +// conn, err := upgrader.Upgrade(w, r, nil) +// if err != nil { +// log.Println(err) +// return +// } +// ... Use conn to send and receive messages. +// } +// +// Call the connection's WriteMessage and ReadMessage methods to send and +// receive messages as a slice of bytes. This snippet of code shows how to echo +// messages using these methods: +// +// for { +// messageType, p, err := conn.ReadMessage() +// if err != nil { +// log.Println(err) +// return +// } +// if err := conn.WriteMessage(messageType, p); err != nil { +// log.Println(err) +// return +// } +// } +// +// In above snippet of code, p is a []byte and messageType is an int with value +// websocket.BinaryMessage or websocket.TextMessage. +// +// An application can also send and receive messages using the io.WriteCloser +// and io.Reader interfaces. To send a message, call the connection NextWriter +// method to get an io.WriteCloser, write the message to the writer and close +// the writer when done. To receive a message, call the connection NextReader +// method to get an io.Reader and read until io.EOF is returned. This snippet +// shows how to echo messages using the NextWriter and NextReader methods: +// +// for { +// messageType, r, err := conn.NextReader() +// if err != nil { +// return +// } +// w, err := conn.NextWriter(messageType) +// if err != nil { +// return err +// } +// if _, err := io.Copy(w, r); err != nil { +// return err +// } +// if err := w.Close(); err != nil { +// return err +// } +// } +// +// Data Messages +// +// The WebSocket protocol distinguishes between text and binary data messages. +// Text messages are interpreted as UTF-8 encoded text. The interpretation of +// binary messages is left to the application. +// +// This package uses the TextMessage and BinaryMessage integer constants to +// identify the two data message types. The ReadMessage and NextReader methods +// return the type of the received message. The messageType argument to the +// WriteMessage and NextWriter methods specifies the type of a sent message. +// +// It is the application's responsibility to ensure that text messages are +// valid UTF-8 encoded text. +// +// Control Messages +// +// The WebSocket protocol defines three types of control messages: close, ping +// and pong. Call the connection WriteControl, WriteMessage or NextWriter +// methods to send a control message to the peer. +// +// Connections handle received close messages by calling the handler function +// set with the SetCloseHandler method and by returning a *CloseError from the +// NextReader, ReadMessage or the message Read method. The default close +// handler sends a close message to the peer. +// +// Connections handle received ping messages by calling the handler function +// set with the SetPingHandler method. The default ping handler sends a pong +// message to the peer. +// +// Connections handle received pong messages by calling the handler function +// set with the SetPongHandler method. The default pong handler does nothing. +// If an application sends ping messages, then the application should set a +// pong handler to receive the corresponding pong. +// +// The control message handler functions are called from the NextReader, +// ReadMessage and message reader Read methods. The default close and ping +// handlers can block these methods for a short time when the handler writes to +// the connection. +// +// The application must read the connection to process close, ping and pong +// messages sent from the peer. If the application is not otherwise interested +// in messages from the peer, then the application should start a goroutine to +// read and discard messages from the peer. A simple example is: +// +// func readLoop(c *websocket.Conn) { +// for { +// if _, _, err := c.NextReader(); err != nil { +// c.Close() +// break +// } +// } +// } +// +// Concurrency +// +// Connections support one concurrent reader and one concurrent writer. +// +// Applications are responsible for ensuring that no more than one goroutine +// calls the write methods (NextWriter, SetWriteDeadline, WriteMessage, +// WriteJSON, EnableWriteCompression, SetCompressionLevel) concurrently and +// that no more than one goroutine calls the read methods (NextReader, +// SetReadDeadline, ReadMessage, ReadJSON, SetPongHandler, SetPingHandler) +// concurrently. +// +// The Close and WriteControl methods can be called concurrently with all other +// methods. +// +// Origin Considerations +// +// Web browsers allow Javascript applications to open a WebSocket connection to +// any host. It's up to the server to enforce an origin policy using the Origin +// request header sent by the browser. +// +// The Upgrader calls the function specified in the CheckOrigin field to check +// the origin. If the CheckOrigin function returns false, then the Upgrade +// method fails the WebSocket handshake with HTTP status 403. +// +// If the CheckOrigin field is nil, then the Upgrader uses a safe default: fail +// the handshake if the Origin request header is present and the Origin host is +// not equal to the Host request header. +// +// The deprecated package-level Upgrade function does not perform origin +// checking. The application is responsible for checking the Origin header +// before calling the Upgrade function. +// +// Buffers +// +// Connections buffer network input and output to reduce the number +// of system calls when reading or writing messages. +// +// Write buffers are also used for constructing WebSocket frames. See RFC 6455, +// Section 5 for a discussion of message framing. A WebSocket frame header is +// written to the network each time a write buffer is flushed to the network. +// Decreasing the size of the write buffer can increase the amount of framing +// overhead on the connection. +// +// The buffer sizes in bytes are specified by the ReadBufferSize and +// WriteBufferSize fields in the Dialer and Upgrader. The Dialer uses a default +// size of 4096 when a buffer size field is set to zero. The Upgrader reuses +// buffers created by the HTTP server when a buffer size field is set to zero. +// The HTTP server buffers have a size of 4096 at the time of this writing. +// +// The buffer sizes do not limit the size of a message that can be read or +// written by a connection. +// +// Buffers are held for the lifetime of the connection by default. If the +// Dialer or Upgrader WriteBufferPool field is set, then a connection holds the +// write buffer only when writing a message. +// +// Applications should tune the buffer sizes to balance memory use and +// performance. Increasing the buffer size uses more memory, but can reduce the +// number of system calls to read or write the network. In the case of writing, +// increasing the buffer size can reduce the number of frame headers written to +// the network. +// +// Some guidelines for setting buffer parameters are: +// +// Limit the buffer sizes to the maximum expected message size. Buffers larger +// than the largest message do not provide any benefit. +// +// Depending on the distribution of message sizes, setting the buffer size to +// a value less than the maximum expected message size can greatly reduce memory +// use with a small impact on performance. Here's an example: If 99% of the +// messages are smaller than 256 bytes and the maximum message size is 512 +// bytes, then a buffer size of 256 bytes will result in 1.01 more system calls +// than a buffer size of 512 bytes. The memory savings is 50%. +// +// A write buffer pool is useful when the application has a modest number +// writes over a large number of connections. when buffers are pooled, a larger +// buffer size has a reduced impact on total memory use and has the benefit of +// reducing system calls and frame overhead. +// +// Compression EXPERIMENTAL +// +// Per message compression extensions (RFC 7692) are experimentally supported +// by this package in a limited capacity. Setting the EnableCompression option +// to true in Dialer or Upgrader will attempt to negotiate per message deflate +// support. +// +// var upgrader = websocket.Upgrader{ +// EnableCompression: true, +// } +// +// If compression was successfully negotiated with the connection's peer, any +// message received in compressed form will be automatically decompressed. +// All Read methods will return uncompressed bytes. +// +// Per message compression of messages written to a connection can be enabled +// or disabled by calling the corresponding Conn method: +// +// conn.EnableWriteCompression(false) +// +// Currently this package does not support compression with "context takeover". +// This means that messages must be compressed and decompressed in isolation, +// without retaining sliding window or dictionary state across messages. For +// more details refer to RFC 7692. +// +// Use of compression is experimental and may result in decreased performance. +package websocket diff --git a/vendor/github.com/gorilla/websocket/join.go b/vendor/github.com/gorilla/websocket/join.go new file mode 100644 index 0000000000..c64f8c8290 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/join.go @@ -0,0 +1,42 @@ +// Copyright 2019 The Gorilla WebSocket Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package websocket + +import ( + "io" + "strings" +) + +// JoinMessages concatenates received messages to create a single io.Reader. +// The string term is appended to each message. The returned reader does not +// support concurrent calls to the Read method. +func JoinMessages(c *Conn, term string) io.Reader { + return &joinReader{c: c, term: term} +} + +type joinReader struct { + c *Conn + term string + r io.Reader +} + +func (r *joinReader) Read(p []byte) (int, error) { + if r.r == nil { + var err error + _, r.r, err = r.c.NextReader() + if err != nil { + return 0, err + } + if r.term != "" { + r.r = io.MultiReader(r.r, strings.NewReader(r.term)) + } + } + n, err := r.r.Read(p) + if err == io.EOF { + err = nil + r.r = nil + } + return n, err +} diff --git a/vendor/github.com/gorilla/websocket/json.go b/vendor/github.com/gorilla/websocket/json.go new file mode 100644 index 0000000000..dc2c1f6415 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/json.go @@ -0,0 +1,60 @@ +// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package websocket + +import ( + "encoding/json" + "io" +) + +// WriteJSON writes the JSON encoding of v as a message. +// +// Deprecated: Use c.WriteJSON instead. +func WriteJSON(c *Conn, v interface{}) error { + return c.WriteJSON(v) +} + +// WriteJSON writes the JSON encoding of v as a message. +// +// See the documentation for encoding/json Marshal for details about the +// conversion of Go values to JSON. +func (c *Conn) WriteJSON(v interface{}) error { + w, err := c.NextWriter(TextMessage) + if err != nil { + return err + } + err1 := json.NewEncoder(w).Encode(v) + err2 := w.Close() + if err1 != nil { + return err1 + } + return err2 +} + +// ReadJSON reads the next JSON-encoded message from the connection and stores +// it in the value pointed to by v. +// +// Deprecated: Use c.ReadJSON instead. +func ReadJSON(c *Conn, v interface{}) error { + return c.ReadJSON(v) +} + +// ReadJSON reads the next JSON-encoded message from the connection and stores +// it in the value pointed to by v. +// +// See the documentation for the encoding/json Unmarshal function for details +// about the conversion of JSON to a Go value. +func (c *Conn) ReadJSON(v interface{}) error { + _, r, err := c.NextReader() + if err != nil { + return err + } + err = json.NewDecoder(r).Decode(v) + if err == io.EOF { + // One value is expected in the message. + err = io.ErrUnexpectedEOF + } + return err +} diff --git a/vendor/github.com/gorilla/websocket/mask.go b/vendor/github.com/gorilla/websocket/mask.go new file mode 100644 index 0000000000..d0742bf2a5 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/mask.go @@ -0,0 +1,55 @@ +// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of +// this source code is governed by a BSD-style license that can be found in the +// LICENSE file. + +//go:build !appengine +// +build !appengine + +package websocket + +import "unsafe" + +const wordSize = int(unsafe.Sizeof(uintptr(0))) + +func maskBytes(key [4]byte, pos int, b []byte) int { + // Mask one byte at a time for small buffers. + if len(b) < 2*wordSize { + for i := range b { + b[i] ^= key[pos&3] + pos++ + } + return pos & 3 + } + + // Mask one byte at a time to word boundary. + if n := int(uintptr(unsafe.Pointer(&b[0]))) % wordSize; n != 0 { + n = wordSize - n + for i := range b[:n] { + b[i] ^= key[pos&3] + pos++ + } + b = b[n:] + } + + // Create aligned word size key. + var k [wordSize]byte + for i := range k { + k[i] = key[(pos+i)&3] + } + kw := *(*uintptr)(unsafe.Pointer(&k)) + + // Mask one word at a time. + n := (len(b) / wordSize) * wordSize + for i := 0; i < n; i += wordSize { + *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&b[0])) + uintptr(i))) ^= kw + } + + // Mask one byte at a time for remaining bytes. + b = b[n:] + for i := range b { + b[i] ^= key[pos&3] + pos++ + } + + return pos & 3 +} diff --git a/vendor/github.com/gorilla/websocket/mask_safe.go b/vendor/github.com/gorilla/websocket/mask_safe.go new file mode 100644 index 0000000000..36250ca7c4 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/mask_safe.go @@ -0,0 +1,16 @@ +// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved. Use of +// this source code is governed by a BSD-style license that can be found in the +// LICENSE file. + +//go:build appengine +// +build appengine + +package websocket + +func maskBytes(key [4]byte, pos int, b []byte) int { + for i := range b { + b[i] ^= key[pos&3] + pos++ + } + return pos & 3 +} diff --git a/vendor/github.com/gorilla/websocket/prepared.go b/vendor/github.com/gorilla/websocket/prepared.go new file mode 100644 index 0000000000..c854225e96 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/prepared.go @@ -0,0 +1,102 @@ +// Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package websocket + +import ( + "bytes" + "net" + "sync" + "time" +) + +// PreparedMessage caches on the wire representations of a message payload. +// Use PreparedMessage to efficiently send a message payload to multiple +// connections. PreparedMessage is especially useful when compression is used +// because the CPU and memory expensive compression operation can be executed +// once for a given set of compression options. +type PreparedMessage struct { + messageType int + data []byte + mu sync.Mutex + frames map[prepareKey]*preparedFrame +} + +// prepareKey defines a unique set of options to cache prepared frames in PreparedMessage. +type prepareKey struct { + isServer bool + compress bool + compressionLevel int +} + +// preparedFrame contains data in wire representation. +type preparedFrame struct { + once sync.Once + data []byte +} + +// NewPreparedMessage returns an initialized PreparedMessage. You can then send +// it to connection using WritePreparedMessage method. Valid wire +// representation will be calculated lazily only once for a set of current +// connection options. +func NewPreparedMessage(messageType int, data []byte) (*PreparedMessage, error) { + pm := &PreparedMessage{ + messageType: messageType, + frames: make(map[prepareKey]*preparedFrame), + data: data, + } + + // Prepare a plain server frame. + _, frameData, err := pm.frame(prepareKey{isServer: true, compress: false}) + if err != nil { + return nil, err + } + + // To protect against caller modifying the data argument, remember the data + // copied to the plain server frame. + pm.data = frameData[len(frameData)-len(data):] + return pm, nil +} + +func (pm *PreparedMessage) frame(key prepareKey) (int, []byte, error) { + pm.mu.Lock() + frame, ok := pm.frames[key] + if !ok { + frame = &preparedFrame{} + pm.frames[key] = frame + } + pm.mu.Unlock() + + var err error + frame.once.Do(func() { + // Prepare a frame using a 'fake' connection. + // TODO: Refactor code in conn.go to allow more direct construction of + // the frame. + mu := make(chan struct{}, 1) + mu <- struct{}{} + var nc prepareConn + c := &Conn{ + conn: &nc, + mu: mu, + isServer: key.isServer, + compressionLevel: key.compressionLevel, + enableWriteCompression: true, + writeBuf: make([]byte, defaultWriteBufferSize+maxFrameHeaderSize), + } + if key.compress { + c.newCompressionWriter = compressNoContextTakeover + } + err = c.WriteMessage(pm.messageType, pm.data) + frame.data = nc.buf.Bytes() + }) + return pm.messageType, frame.data, err +} + +type prepareConn struct { + buf bytes.Buffer + net.Conn +} + +func (pc *prepareConn) Write(p []byte) (int, error) { return pc.buf.Write(p) } +func (pc *prepareConn) SetWriteDeadline(t time.Time) error { return nil } diff --git a/vendor/github.com/gorilla/websocket/proxy.go b/vendor/github.com/gorilla/websocket/proxy.go new file mode 100644 index 0000000000..e0f466b72f --- /dev/null +++ b/vendor/github.com/gorilla/websocket/proxy.go @@ -0,0 +1,77 @@ +// Copyright 2017 The Gorilla WebSocket Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package websocket + +import ( + "bufio" + "encoding/base64" + "errors" + "net" + "net/http" + "net/url" + "strings" +) + +type netDialerFunc func(network, addr string) (net.Conn, error) + +func (fn netDialerFunc) Dial(network, addr string) (net.Conn, error) { + return fn(network, addr) +} + +func init() { + proxy_RegisterDialerType("http", func(proxyURL *url.URL, forwardDialer proxy_Dialer) (proxy_Dialer, error) { + return &httpProxyDialer{proxyURL: proxyURL, forwardDial: forwardDialer.Dial}, nil + }) +} + +type httpProxyDialer struct { + proxyURL *url.URL + forwardDial func(network, addr string) (net.Conn, error) +} + +func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error) { + hostPort, _ := hostPortNoPort(hpd.proxyURL) + conn, err := hpd.forwardDial(network, hostPort) + if err != nil { + return nil, err + } + + connectHeader := make(http.Header) + if user := hpd.proxyURL.User; user != nil { + proxyUser := user.Username() + if proxyPassword, passwordSet := user.Password(); passwordSet { + credential := base64.StdEncoding.EncodeToString([]byte(proxyUser + ":" + proxyPassword)) + connectHeader.Set("Proxy-Authorization", "Basic "+credential) + } + } + + connectReq := &http.Request{ + Method: http.MethodConnect, + URL: &url.URL{Opaque: addr}, + Host: addr, + Header: connectHeader, + } + + if err := connectReq.Write(conn); err != nil { + conn.Close() + return nil, err + } + + // Read response. It's OK to use and discard buffered reader here becaue + // the remote server does not speak until spoken to. + br := bufio.NewReader(conn) + resp, err := http.ReadResponse(br, connectReq) + if err != nil { + conn.Close() + return nil, err + } + + if resp.StatusCode != 200 { + conn.Close() + f := strings.SplitN(resp.Status, " ", 2) + return nil, errors.New(f[1]) + } + return conn, nil +} diff --git a/vendor/github.com/gorilla/websocket/server.go b/vendor/github.com/gorilla/websocket/server.go new file mode 100644 index 0000000000..24d53b38ab --- /dev/null +++ b/vendor/github.com/gorilla/websocket/server.go @@ -0,0 +1,365 @@ +// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package websocket + +import ( + "bufio" + "errors" + "io" + "net/http" + "net/url" + "strings" + "time" +) + +// HandshakeError describes an error with the handshake from the peer. +type HandshakeError struct { + message string +} + +func (e HandshakeError) Error() string { return e.message } + +// Upgrader specifies parameters for upgrading an HTTP connection to a +// WebSocket connection. +// +// It is safe to call Upgrader's methods concurrently. +type Upgrader struct { + // HandshakeTimeout specifies the duration for the handshake to complete. + HandshakeTimeout time.Duration + + // ReadBufferSize and WriteBufferSize specify I/O buffer sizes in bytes. If a buffer + // size is zero, then buffers allocated by the HTTP server are used. The + // I/O buffer sizes do not limit the size of the messages that can be sent + // or received. + ReadBufferSize, WriteBufferSize int + + // WriteBufferPool is a pool of buffers for write operations. If the value + // is not set, then write buffers are allocated to the connection for the + // lifetime of the connection. + // + // A pool is most useful when the application has a modest volume of writes + // across a large number of connections. + // + // Applications should use a single pool for each unique value of + // WriteBufferSize. + WriteBufferPool BufferPool + + // Subprotocols specifies the server's supported protocols in order of + // preference. If this field is not nil, then the Upgrade method negotiates a + // subprotocol by selecting the first match in this list with a protocol + // requested by the client. If there's no match, then no protocol is + // negotiated (the Sec-Websocket-Protocol header is not included in the + // handshake response). + Subprotocols []string + + // Error specifies the function for generating HTTP error responses. If Error + // is nil, then http.Error is used to generate the HTTP response. + Error func(w http.ResponseWriter, r *http.Request, status int, reason error) + + // CheckOrigin returns true if the request Origin header is acceptable. If + // CheckOrigin is nil, then a safe default is used: return false if the + // Origin request header is present and the origin host is not equal to + // request Host header. + // + // A CheckOrigin function should carefully validate the request origin to + // prevent cross-site request forgery. + CheckOrigin func(r *http.Request) bool + + // EnableCompression specify if the server should attempt to negotiate per + // message compression (RFC 7692). Setting this value to true does not + // guarantee that compression will be supported. Currently only "no context + // takeover" modes are supported. + EnableCompression bool +} + +func (u *Upgrader) returnError(w http.ResponseWriter, r *http.Request, status int, reason string) (*Conn, error) { + err := HandshakeError{reason} + if u.Error != nil { + u.Error(w, r, status, err) + } else { + w.Header().Set("Sec-Websocket-Version", "13") + http.Error(w, http.StatusText(status), status) + } + return nil, err +} + +// checkSameOrigin returns true if the origin is not set or is equal to the request host. +func checkSameOrigin(r *http.Request) bool { + origin := r.Header["Origin"] + if len(origin) == 0 { + return true + } + u, err := url.Parse(origin[0]) + if err != nil { + return false + } + return equalASCIIFold(u.Host, r.Host) +} + +func (u *Upgrader) selectSubprotocol(r *http.Request, responseHeader http.Header) string { + if u.Subprotocols != nil { + clientProtocols := Subprotocols(r) + for _, serverProtocol := range u.Subprotocols { + for _, clientProtocol := range clientProtocols { + if clientProtocol == serverProtocol { + return clientProtocol + } + } + } + } else if responseHeader != nil { + return responseHeader.Get("Sec-Websocket-Protocol") + } + return "" +} + +// Upgrade upgrades the HTTP server connection to the WebSocket protocol. +// +// The responseHeader is included in the response to the client's upgrade +// request. Use the responseHeader to specify cookies (Set-Cookie). To specify +// subprotocols supported by the server, set Upgrader.Subprotocols directly. +// +// If the upgrade fails, then Upgrade replies to the client with an HTTP error +// response. +func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeader http.Header) (*Conn, error) { + const badHandshake = "websocket: the client is not using the websocket protocol: " + + if !tokenListContainsValue(r.Header, "Connection", "upgrade") { + return u.returnError(w, r, http.StatusBadRequest, badHandshake+"'upgrade' token not found in 'Connection' header") + } + + if !tokenListContainsValue(r.Header, "Upgrade", "websocket") { + return u.returnError(w, r, http.StatusBadRequest, badHandshake+"'websocket' token not found in 'Upgrade' header") + } + + if r.Method != http.MethodGet { + return u.returnError(w, r, http.StatusMethodNotAllowed, badHandshake+"request method is not GET") + } + + if !tokenListContainsValue(r.Header, "Sec-Websocket-Version", "13") { + return u.returnError(w, r, http.StatusBadRequest, "websocket: unsupported version: 13 not found in 'Sec-Websocket-Version' header") + } + + if _, ok := responseHeader["Sec-Websocket-Extensions"]; ok { + return u.returnError(w, r, http.StatusInternalServerError, "websocket: application specific 'Sec-WebSocket-Extensions' headers are unsupported") + } + + checkOrigin := u.CheckOrigin + if checkOrigin == nil { + checkOrigin = checkSameOrigin + } + if !checkOrigin(r) { + return u.returnError(w, r, http.StatusForbidden, "websocket: request origin not allowed by Upgrader.CheckOrigin") + } + + challengeKey := r.Header.Get("Sec-Websocket-Key") + if challengeKey == "" { + return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'Sec-WebSocket-Key' header is missing or blank") + } + + subprotocol := u.selectSubprotocol(r, responseHeader) + + // Negotiate PMCE + var compress bool + if u.EnableCompression { + for _, ext := range parseExtensions(r.Header) { + if ext[""] != "permessage-deflate" { + continue + } + compress = true + break + } + } + + h, ok := w.(http.Hijacker) + if !ok { + return u.returnError(w, r, http.StatusInternalServerError, "websocket: response does not implement http.Hijacker") + } + var brw *bufio.ReadWriter + netConn, brw, err := h.Hijack() + if err != nil { + return u.returnError(w, r, http.StatusInternalServerError, err.Error()) + } + + if brw.Reader.Buffered() > 0 { + netConn.Close() + return nil, errors.New("websocket: client sent data before handshake is complete") + } + + var br *bufio.Reader + if u.ReadBufferSize == 0 && bufioReaderSize(netConn, brw.Reader) > 256 { + // Reuse hijacked buffered reader as connection reader. + br = brw.Reader + } + + buf := bufioWriterBuffer(netConn, brw.Writer) + + var writeBuf []byte + if u.WriteBufferPool == nil && u.WriteBufferSize == 0 && len(buf) >= maxFrameHeaderSize+256 { + // Reuse hijacked write buffer as connection buffer. + writeBuf = buf + } + + c := newConn(netConn, true, u.ReadBufferSize, u.WriteBufferSize, u.WriteBufferPool, br, writeBuf) + c.subprotocol = subprotocol + + if compress { + c.newCompressionWriter = compressNoContextTakeover + c.newDecompressionReader = decompressNoContextTakeover + } + + // Use larger of hijacked buffer and connection write buffer for header. + p := buf + if len(c.writeBuf) > len(p) { + p = c.writeBuf + } + p = p[:0] + + p = append(p, "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: "...) + p = append(p, computeAcceptKey(challengeKey)...) + p = append(p, "\r\n"...) + if c.subprotocol != "" { + p = append(p, "Sec-WebSocket-Protocol: "...) + p = append(p, c.subprotocol...) + p = append(p, "\r\n"...) + } + if compress { + p = append(p, "Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover\r\n"...) + } + for k, vs := range responseHeader { + if k == "Sec-Websocket-Protocol" { + continue + } + for _, v := range vs { + p = append(p, k...) + p = append(p, ": "...) + for i := 0; i < len(v); i++ { + b := v[i] + if b <= 31 { + // prevent response splitting. + b = ' ' + } + p = append(p, b) + } + p = append(p, "\r\n"...) + } + } + p = append(p, "\r\n"...) + + // Clear deadlines set by HTTP server. + netConn.SetDeadline(time.Time{}) + + if u.HandshakeTimeout > 0 { + netConn.SetWriteDeadline(time.Now().Add(u.HandshakeTimeout)) + } + if _, err = netConn.Write(p); err != nil { + netConn.Close() + return nil, err + } + if u.HandshakeTimeout > 0 { + netConn.SetWriteDeadline(time.Time{}) + } + + return c, nil +} + +// Upgrade upgrades the HTTP server connection to the WebSocket protocol. +// +// Deprecated: Use websocket.Upgrader instead. +// +// Upgrade does not perform origin checking. The application is responsible for +// checking the Origin header before calling Upgrade. An example implementation +// of the same origin policy check is: +// +// if req.Header.Get("Origin") != "http://"+req.Host { +// http.Error(w, "Origin not allowed", http.StatusForbidden) +// return +// } +// +// If the endpoint supports subprotocols, then the application is responsible +// for negotiating the protocol used on the connection. Use the Subprotocols() +// function to get the subprotocols requested by the client. Use the +// Sec-Websocket-Protocol response header to specify the subprotocol selected +// by the application. +// +// The responseHeader is included in the response to the client's upgrade +// request. Use the responseHeader to specify cookies (Set-Cookie) and the +// negotiated subprotocol (Sec-Websocket-Protocol). +// +// The connection buffers IO to the underlying network connection. The +// readBufSize and writeBufSize parameters specify the size of the buffers to +// use. Messages can be larger than the buffers. +// +// If the request is not a valid WebSocket handshake, then Upgrade returns an +// error of type HandshakeError. Applications should handle this error by +// replying to the client with an HTTP error response. +func Upgrade(w http.ResponseWriter, r *http.Request, responseHeader http.Header, readBufSize, writeBufSize int) (*Conn, error) { + u := Upgrader{ReadBufferSize: readBufSize, WriteBufferSize: writeBufSize} + u.Error = func(w http.ResponseWriter, r *http.Request, status int, reason error) { + // don't return errors to maintain backwards compatibility + } + u.CheckOrigin = func(r *http.Request) bool { + // allow all connections by default + return true + } + return u.Upgrade(w, r, responseHeader) +} + +// Subprotocols returns the subprotocols requested by the client in the +// Sec-Websocket-Protocol header. +func Subprotocols(r *http.Request) []string { + h := strings.TrimSpace(r.Header.Get("Sec-Websocket-Protocol")) + if h == "" { + return nil + } + protocols := strings.Split(h, ",") + for i := range protocols { + protocols[i] = strings.TrimSpace(protocols[i]) + } + return protocols +} + +// IsWebSocketUpgrade returns true if the client requested upgrade to the +// WebSocket protocol. +func IsWebSocketUpgrade(r *http.Request) bool { + return tokenListContainsValue(r.Header, "Connection", "upgrade") && + tokenListContainsValue(r.Header, "Upgrade", "websocket") +} + +// bufioReaderSize size returns the size of a bufio.Reader. +func bufioReaderSize(originalReader io.Reader, br *bufio.Reader) int { + // This code assumes that peek on a reset reader returns + // bufio.Reader.buf[:0]. + // TODO: Use bufio.Reader.Size() after Go 1.10 + br.Reset(originalReader) + if p, err := br.Peek(0); err == nil { + return cap(p) + } + return 0 +} + +// writeHook is an io.Writer that records the last slice passed to it vio +// io.Writer.Write. +type writeHook struct { + p []byte +} + +func (wh *writeHook) Write(p []byte) (int, error) { + wh.p = p + return len(p), nil +} + +// bufioWriterBuffer grabs the buffer from a bufio.Writer. +func bufioWriterBuffer(originalWriter io.Writer, bw *bufio.Writer) []byte { + // This code assumes that bufio.Writer.buf[:1] is passed to the + // bufio.Writer's underlying writer. + var wh writeHook + bw.Reset(&wh) + bw.WriteByte(0) + bw.Flush() + + bw.Reset(originalWriter) + + return wh.p[:cap(wh.p)] +} diff --git a/vendor/github.com/gorilla/websocket/tls_handshake.go b/vendor/github.com/gorilla/websocket/tls_handshake.go new file mode 100644 index 0000000000..a62b68ccb1 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/tls_handshake.go @@ -0,0 +1,21 @@ +//go:build go1.17 +// +build go1.17 + +package websocket + +import ( + "context" + "crypto/tls" +) + +func doHandshake(ctx context.Context, tlsConn *tls.Conn, cfg *tls.Config) error { + if err := tlsConn.HandshakeContext(ctx); err != nil { + return err + } + if !cfg.InsecureSkipVerify { + if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/gorilla/websocket/tls_handshake_116.go b/vendor/github.com/gorilla/websocket/tls_handshake_116.go new file mode 100644 index 0000000000..e1b2b44f6e --- /dev/null +++ b/vendor/github.com/gorilla/websocket/tls_handshake_116.go @@ -0,0 +1,21 @@ +//go:build !go1.17 +// +build !go1.17 + +package websocket + +import ( + "context" + "crypto/tls" +) + +func doHandshake(ctx context.Context, tlsConn *tls.Conn, cfg *tls.Config) error { + if err := tlsConn.Handshake(); err != nil { + return err + } + if !cfg.InsecureSkipVerify { + if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/gorilla/websocket/util.go b/vendor/github.com/gorilla/websocket/util.go new file mode 100644 index 0000000000..7bf2f66c67 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/util.go @@ -0,0 +1,283 @@ +// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package websocket + +import ( + "crypto/rand" + "crypto/sha1" + "encoding/base64" + "io" + "net/http" + "strings" + "unicode/utf8" +) + +var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11") + +func computeAcceptKey(challengeKey string) string { + h := sha1.New() + h.Write([]byte(challengeKey)) + h.Write(keyGUID) + return base64.StdEncoding.EncodeToString(h.Sum(nil)) +} + +func generateChallengeKey() (string, error) { + p := make([]byte, 16) + if _, err := io.ReadFull(rand.Reader, p); err != nil { + return "", err + } + return base64.StdEncoding.EncodeToString(p), nil +} + +// Token octets per RFC 2616. +var isTokenOctet = [256]bool{ + '!': true, + '#': true, + '$': true, + '%': true, + '&': true, + '\'': true, + '*': true, + '+': true, + '-': true, + '.': true, + '0': true, + '1': true, + '2': true, + '3': true, + '4': true, + '5': true, + '6': true, + '7': true, + '8': true, + '9': true, + 'A': true, + 'B': true, + 'C': true, + 'D': true, + 'E': true, + 'F': true, + 'G': true, + 'H': true, + 'I': true, + 'J': true, + 'K': true, + 'L': true, + 'M': true, + 'N': true, + 'O': true, + 'P': true, + 'Q': true, + 'R': true, + 'S': true, + 'T': true, + 'U': true, + 'W': true, + 'V': true, + 'X': true, + 'Y': true, + 'Z': true, + '^': true, + '_': true, + '`': true, + 'a': true, + 'b': true, + 'c': true, + 'd': true, + 'e': true, + 'f': true, + 'g': true, + 'h': true, + 'i': true, + 'j': true, + 'k': true, + 'l': true, + 'm': true, + 'n': true, + 'o': true, + 'p': true, + 'q': true, + 'r': true, + 's': true, + 't': true, + 'u': true, + 'v': true, + 'w': true, + 'x': true, + 'y': true, + 'z': true, + '|': true, + '~': true, +} + +// skipSpace returns a slice of the string s with all leading RFC 2616 linear +// whitespace removed. +func skipSpace(s string) (rest string) { + i := 0 + for ; i < len(s); i++ { + if b := s[i]; b != ' ' && b != '\t' { + break + } + } + return s[i:] +} + +// nextToken returns the leading RFC 2616 token of s and the string following +// the token. +func nextToken(s string) (token, rest string) { + i := 0 + for ; i < len(s); i++ { + if !isTokenOctet[s[i]] { + break + } + } + return s[:i], s[i:] +} + +// nextTokenOrQuoted returns the leading token or quoted string per RFC 2616 +// and the string following the token or quoted string. +func nextTokenOrQuoted(s string) (value string, rest string) { + if !strings.HasPrefix(s, "\"") { + return nextToken(s) + } + s = s[1:] + for i := 0; i < len(s); i++ { + switch s[i] { + case '"': + return s[:i], s[i+1:] + case '\\': + p := make([]byte, len(s)-1) + j := copy(p, s[:i]) + escape := true + for i = i + 1; i < len(s); i++ { + b := s[i] + switch { + case escape: + escape = false + p[j] = b + j++ + case b == '\\': + escape = true + case b == '"': + return string(p[:j]), s[i+1:] + default: + p[j] = b + j++ + } + } + return "", "" + } + } + return "", "" +} + +// equalASCIIFold returns true if s is equal to t with ASCII case folding as +// defined in RFC 4790. +func equalASCIIFold(s, t string) bool { + for s != "" && t != "" { + sr, size := utf8.DecodeRuneInString(s) + s = s[size:] + tr, size := utf8.DecodeRuneInString(t) + t = t[size:] + if sr == tr { + continue + } + if 'A' <= sr && sr <= 'Z' { + sr = sr + 'a' - 'A' + } + if 'A' <= tr && tr <= 'Z' { + tr = tr + 'a' - 'A' + } + if sr != tr { + return false + } + } + return s == t +} + +// tokenListContainsValue returns true if the 1#token header with the given +// name contains a token equal to value with ASCII case folding. +func tokenListContainsValue(header http.Header, name string, value string) bool { +headers: + for _, s := range header[name] { + for { + var t string + t, s = nextToken(skipSpace(s)) + if t == "" { + continue headers + } + s = skipSpace(s) + if s != "" && s[0] != ',' { + continue headers + } + if equalASCIIFold(t, value) { + return true + } + if s == "" { + continue headers + } + s = s[1:] + } + } + return false +} + +// parseExtensions parses WebSocket extensions from a header. +func parseExtensions(header http.Header) []map[string]string { + // From RFC 6455: + // + // Sec-WebSocket-Extensions = extension-list + // extension-list = 1#extension + // extension = extension-token *( ";" extension-param ) + // extension-token = registered-token + // registered-token = token + // extension-param = token [ "=" (token | quoted-string) ] + // ;When using the quoted-string syntax variant, the value + // ;after quoted-string unescaping MUST conform to the + // ;'token' ABNF. + + var result []map[string]string +headers: + for _, s := range header["Sec-Websocket-Extensions"] { + for { + var t string + t, s = nextToken(skipSpace(s)) + if t == "" { + continue headers + } + ext := map[string]string{"": t} + for { + s = skipSpace(s) + if !strings.HasPrefix(s, ";") { + break + } + var k string + k, s = nextToken(skipSpace(s[1:])) + if k == "" { + continue headers + } + s = skipSpace(s) + var v string + if strings.HasPrefix(s, "=") { + v, s = nextTokenOrQuoted(skipSpace(s[1:])) + s = skipSpace(s) + } + if s != "" && s[0] != ',' && s[0] != ';' { + continue headers + } + ext[k] = v + } + if s != "" && s[0] != ',' { + continue headers + } + result = append(result, ext) + if s == "" { + continue headers + } + s = s[1:] + } + } + return result +} diff --git a/vendor/github.com/gorilla/websocket/x_net_proxy.go b/vendor/github.com/gorilla/websocket/x_net_proxy.go new file mode 100644 index 0000000000..2e668f6b88 --- /dev/null +++ b/vendor/github.com/gorilla/websocket/x_net_proxy.go @@ -0,0 +1,473 @@ +// Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT. +//go:generate bundle -o x_net_proxy.go golang.org/x/net/proxy + +// Package proxy provides support for a variety of protocols to proxy network +// data. +// + +package websocket + +import ( + "errors" + "io" + "net" + "net/url" + "os" + "strconv" + "strings" + "sync" +) + +type proxy_direct struct{} + +// Direct is a direct proxy: one that makes network connections directly. +var proxy_Direct = proxy_direct{} + +func (proxy_direct) Dial(network, addr string) (net.Conn, error) { + return net.Dial(network, addr) +} + +// A PerHost directs connections to a default Dialer unless the host name +// requested matches one of a number of exceptions. +type proxy_PerHost struct { + def, bypass proxy_Dialer + + bypassNetworks []*net.IPNet + bypassIPs []net.IP + bypassZones []string + bypassHosts []string +} + +// NewPerHost returns a PerHost Dialer that directs connections to either +// defaultDialer or bypass, depending on whether the connection matches one of +// the configured rules. +func proxy_NewPerHost(defaultDialer, bypass proxy_Dialer) *proxy_PerHost { + return &proxy_PerHost{ + def: defaultDialer, + bypass: bypass, + } +} + +// Dial connects to the address addr on the given network through either +// defaultDialer or bypass. +func (p *proxy_PerHost) Dial(network, addr string) (c net.Conn, err error) { + host, _, err := net.SplitHostPort(addr) + if err != nil { + return nil, err + } + + return p.dialerForRequest(host).Dial(network, addr) +} + +func (p *proxy_PerHost) dialerForRequest(host string) proxy_Dialer { + if ip := net.ParseIP(host); ip != nil { + for _, net := range p.bypassNetworks { + if net.Contains(ip) { + return p.bypass + } + } + for _, bypassIP := range p.bypassIPs { + if bypassIP.Equal(ip) { + return p.bypass + } + } + return p.def + } + + for _, zone := range p.bypassZones { + if strings.HasSuffix(host, zone) { + return p.bypass + } + if host == zone[1:] { + // For a zone ".example.com", we match "example.com" + // too. + return p.bypass + } + } + for _, bypassHost := range p.bypassHosts { + if bypassHost == host { + return p.bypass + } + } + return p.def +} + +// AddFromString parses a string that contains comma-separated values +// specifying hosts that should use the bypass proxy. Each value is either an +// IP address, a CIDR range, a zone (*.example.com) or a host name +// (localhost). A best effort is made to parse the string and errors are +// ignored. +func (p *proxy_PerHost) AddFromString(s string) { + hosts := strings.Split(s, ",") + for _, host := range hosts { + host = strings.TrimSpace(host) + if len(host) == 0 { + continue + } + if strings.Contains(host, "/") { + // We assume that it's a CIDR address like 127.0.0.0/8 + if _, net, err := net.ParseCIDR(host); err == nil { + p.AddNetwork(net) + } + continue + } + if ip := net.ParseIP(host); ip != nil { + p.AddIP(ip) + continue + } + if strings.HasPrefix(host, "*.") { + p.AddZone(host[1:]) + continue + } + p.AddHost(host) + } +} + +// AddIP specifies an IP address that will use the bypass proxy. Note that +// this will only take effect if a literal IP address is dialed. A connection +// to a named host will never match an IP. +func (p *proxy_PerHost) AddIP(ip net.IP) { + p.bypassIPs = append(p.bypassIPs, ip) +} + +// AddNetwork specifies an IP range that will use the bypass proxy. Note that +// this will only take effect if a literal IP address is dialed. A connection +// to a named host will never match. +func (p *proxy_PerHost) AddNetwork(net *net.IPNet) { + p.bypassNetworks = append(p.bypassNetworks, net) +} + +// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of +// "example.com" matches "example.com" and all of its subdomains. +func (p *proxy_PerHost) AddZone(zone string) { + if strings.HasSuffix(zone, ".") { + zone = zone[:len(zone)-1] + } + if !strings.HasPrefix(zone, ".") { + zone = "." + zone + } + p.bypassZones = append(p.bypassZones, zone) +} + +// AddHost specifies a host name that will use the bypass proxy. +func (p *proxy_PerHost) AddHost(host string) { + if strings.HasSuffix(host, ".") { + host = host[:len(host)-1] + } + p.bypassHosts = append(p.bypassHosts, host) +} + +// A Dialer is a means to establish a connection. +type proxy_Dialer interface { + // Dial connects to the given address via the proxy. + Dial(network, addr string) (c net.Conn, err error) +} + +// Auth contains authentication parameters that specific Dialers may require. +type proxy_Auth struct { + User, Password string +} + +// FromEnvironment returns the dialer specified by the proxy related variables in +// the environment. +func proxy_FromEnvironment() proxy_Dialer { + allProxy := proxy_allProxyEnv.Get() + if len(allProxy) == 0 { + return proxy_Direct + } + + proxyURL, err := url.Parse(allProxy) + if err != nil { + return proxy_Direct + } + proxy, err := proxy_FromURL(proxyURL, proxy_Direct) + if err != nil { + return proxy_Direct + } + + noProxy := proxy_noProxyEnv.Get() + if len(noProxy) == 0 { + return proxy + } + + perHost := proxy_NewPerHost(proxy, proxy_Direct) + perHost.AddFromString(noProxy) + return perHost +} + +// proxySchemes is a map from URL schemes to a function that creates a Dialer +// from a URL with such a scheme. +var proxy_proxySchemes map[string]func(*url.URL, proxy_Dialer) (proxy_Dialer, error) + +// RegisterDialerType takes a URL scheme and a function to generate Dialers from +// a URL with that scheme and a forwarding Dialer. Registered schemes are used +// by FromURL. +func proxy_RegisterDialerType(scheme string, f func(*url.URL, proxy_Dialer) (proxy_Dialer, error)) { + if proxy_proxySchemes == nil { + proxy_proxySchemes = make(map[string]func(*url.URL, proxy_Dialer) (proxy_Dialer, error)) + } + proxy_proxySchemes[scheme] = f +} + +// FromURL returns a Dialer given a URL specification and an underlying +// Dialer for it to make network requests. +func proxy_FromURL(u *url.URL, forward proxy_Dialer) (proxy_Dialer, error) { + var auth *proxy_Auth + if u.User != nil { + auth = new(proxy_Auth) + auth.User = u.User.Username() + if p, ok := u.User.Password(); ok { + auth.Password = p + } + } + + switch u.Scheme { + case "socks5": + return proxy_SOCKS5("tcp", u.Host, auth, forward) + } + + // If the scheme doesn't match any of the built-in schemes, see if it + // was registered by another package. + if proxy_proxySchemes != nil { + if f, ok := proxy_proxySchemes[u.Scheme]; ok { + return f(u, forward) + } + } + + return nil, errors.New("proxy: unknown scheme: " + u.Scheme) +} + +var ( + proxy_allProxyEnv = &proxy_envOnce{ + names: []string{"ALL_PROXY", "all_proxy"}, + } + proxy_noProxyEnv = &proxy_envOnce{ + names: []string{"NO_PROXY", "no_proxy"}, + } +) + +// envOnce looks up an environment variable (optionally by multiple +// names) once. It mitigates expensive lookups on some platforms +// (e.g. Windows). +// (Borrowed from net/http/transport.go) +type proxy_envOnce struct { + names []string + once sync.Once + val string +} + +func (e *proxy_envOnce) Get() string { + e.once.Do(e.init) + return e.val +} + +func (e *proxy_envOnce) init() { + for _, n := range e.names { + e.val = os.Getenv(n) + if e.val != "" { + return + } + } +} + +// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address +// with an optional username and password. See RFC 1928 and RFC 1929. +func proxy_SOCKS5(network, addr string, auth *proxy_Auth, forward proxy_Dialer) (proxy_Dialer, error) { + s := &proxy_socks5{ + network: network, + addr: addr, + forward: forward, + } + if auth != nil { + s.user = auth.User + s.password = auth.Password + } + + return s, nil +} + +type proxy_socks5 struct { + user, password string + network, addr string + forward proxy_Dialer +} + +const proxy_socks5Version = 5 + +const ( + proxy_socks5AuthNone = 0 + proxy_socks5AuthPassword = 2 +) + +const proxy_socks5Connect = 1 + +const ( + proxy_socks5IP4 = 1 + proxy_socks5Domain = 3 + proxy_socks5IP6 = 4 +) + +var proxy_socks5Errors = []string{ + "", + "general failure", + "connection forbidden", + "network unreachable", + "host unreachable", + "connection refused", + "TTL expired", + "command not supported", + "address type not supported", +} + +// Dial connects to the address addr on the given network via the SOCKS5 proxy. +func (s *proxy_socks5) Dial(network, addr string) (net.Conn, error) { + switch network { + case "tcp", "tcp6", "tcp4": + default: + return nil, errors.New("proxy: no support for SOCKS5 proxy connections of type " + network) + } + + conn, err := s.forward.Dial(s.network, s.addr) + if err != nil { + return nil, err + } + if err := s.connect(conn, addr); err != nil { + conn.Close() + return nil, err + } + return conn, nil +} + +// connect takes an existing connection to a socks5 proxy server, +// and commands the server to extend that connection to target, +// which must be a canonical address with a host and port. +func (s *proxy_socks5) connect(conn net.Conn, target string) error { + host, portStr, err := net.SplitHostPort(target) + if err != nil { + return err + } + + port, err := strconv.Atoi(portStr) + if err != nil { + return errors.New("proxy: failed to parse port number: " + portStr) + } + if port < 1 || port > 0xffff { + return errors.New("proxy: port number out of range: " + portStr) + } + + // the size here is just an estimate + buf := make([]byte, 0, 6+len(host)) + + buf = append(buf, proxy_socks5Version) + if len(s.user) > 0 && len(s.user) < 256 && len(s.password) < 256 { + buf = append(buf, 2 /* num auth methods */, proxy_socks5AuthNone, proxy_socks5AuthPassword) + } else { + buf = append(buf, 1 /* num auth methods */, proxy_socks5AuthNone) + } + + if _, err := conn.Write(buf); err != nil { + return errors.New("proxy: failed to write greeting to SOCKS5 proxy at " + s.addr + ": " + err.Error()) + } + + if _, err := io.ReadFull(conn, buf[:2]); err != nil { + return errors.New("proxy: failed to read greeting from SOCKS5 proxy at " + s.addr + ": " + err.Error()) + } + if buf[0] != 5 { + return errors.New("proxy: SOCKS5 proxy at " + s.addr + " has unexpected version " + strconv.Itoa(int(buf[0]))) + } + if buf[1] == 0xff { + return errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication") + } + + // See RFC 1929 + if buf[1] == proxy_socks5AuthPassword { + buf = buf[:0] + buf = append(buf, 1 /* password protocol version */) + buf = append(buf, uint8(len(s.user))) + buf = append(buf, s.user...) + buf = append(buf, uint8(len(s.password))) + buf = append(buf, s.password...) + + if _, err := conn.Write(buf); err != nil { + return errors.New("proxy: failed to write authentication request to SOCKS5 proxy at " + s.addr + ": " + err.Error()) + } + + if _, err := io.ReadFull(conn, buf[:2]); err != nil { + return errors.New("proxy: failed to read authentication reply from SOCKS5 proxy at " + s.addr + ": " + err.Error()) + } + + if buf[1] != 0 { + return errors.New("proxy: SOCKS5 proxy at " + s.addr + " rejected username/password") + } + } + + buf = buf[:0] + buf = append(buf, proxy_socks5Version, proxy_socks5Connect, 0 /* reserved */) + + if ip := net.ParseIP(host); ip != nil { + if ip4 := ip.To4(); ip4 != nil { + buf = append(buf, proxy_socks5IP4) + ip = ip4 + } else { + buf = append(buf, proxy_socks5IP6) + } + buf = append(buf, ip...) + } else { + if len(host) > 255 { + return errors.New("proxy: destination host name too long: " + host) + } + buf = append(buf, proxy_socks5Domain) + buf = append(buf, byte(len(host))) + buf = append(buf, host...) + } + buf = append(buf, byte(port>>8), byte(port)) + + if _, err := conn.Write(buf); err != nil { + return errors.New("proxy: failed to write connect request to SOCKS5 proxy at " + s.addr + ": " + err.Error()) + } + + if _, err := io.ReadFull(conn, buf[:4]); err != nil { + return errors.New("proxy: failed to read connect reply from SOCKS5 proxy at " + s.addr + ": " + err.Error()) + } + + failure := "unknown error" + if int(buf[1]) < len(proxy_socks5Errors) { + failure = proxy_socks5Errors[buf[1]] + } + + if len(failure) > 0 { + return errors.New("proxy: SOCKS5 proxy at " + s.addr + " failed to connect: " + failure) + } + + bytesToDiscard := 0 + switch buf[3] { + case proxy_socks5IP4: + bytesToDiscard = net.IPv4len + case proxy_socks5IP6: + bytesToDiscard = net.IPv6len + case proxy_socks5Domain: + _, err := io.ReadFull(conn, buf[:1]) + if err != nil { + return errors.New("proxy: failed to read domain length from SOCKS5 proxy at " + s.addr + ": " + err.Error()) + } + bytesToDiscard = int(buf[0]) + default: + return errors.New("proxy: got unknown address type " + strconv.Itoa(int(buf[3])) + " from SOCKS5 proxy at " + s.addr) + } + + if cap(buf) < bytesToDiscard { + buf = make([]byte, bytesToDiscard) + } else { + buf = buf[:bytesToDiscard] + } + if _, err := io.ReadFull(conn, buf); err != nil { + return errors.New("proxy: failed to read address from SOCKS5 proxy at " + s.addr + ": " + err.Error()) + } + + // Also need to discard the port number + if _, err := io.ReadFull(conn, buf[:2]); err != nil { + return errors.New("proxy: failed to read port from SOCKS5 proxy at " + s.addr + ": " + err.Error()) + } + + return nil +} diff --git a/vendor/github.com/jbenet/go-context/LICENSE b/vendor/github.com/jbenet/go-context/LICENSE new file mode 100644 index 0000000000..c7386b3c94 --- /dev/null +++ b/vendor/github.com/jbenet/go-context/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Juan Batiz-Benet + +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/jbenet/go-context/io/ctxio.go b/vendor/github.com/jbenet/go-context/io/ctxio.go new file mode 100644 index 0000000000..b4f2454235 --- /dev/null +++ b/vendor/github.com/jbenet/go-context/io/ctxio.go @@ -0,0 +1,120 @@ +// Package ctxio provides io.Reader and io.Writer wrappers that +// respect context.Contexts. Use these at the interface between +// your context code and your io. +// +// WARNING: read the code. see how writes and reads will continue +// until you cancel the io. Maybe this package should provide +// versions of io.ReadCloser and io.WriteCloser that automatically +// call .Close when the context expires. But for now -- since in my +// use cases I have long-lived connections with ephemeral io wrappers +// -- this has yet to be a need. +package ctxio + +import ( + "io" + + context "golang.org/x/net/context" +) + +type ioret struct { + n int + err error +} + +type Writer interface { + io.Writer +} + +type ctxWriter struct { + w io.Writer + ctx context.Context +} + +// NewWriter wraps a writer to make it respect given Context. +// If there is a blocking write, the returned Writer will return +// whenever the context is cancelled (the return values are n=0 +// and err=ctx.Err().) +// +// Note well: this wrapper DOES NOT ACTUALLY cancel the underlying +// write-- there is no way to do that with the standard go io +// interface. So the read and write _will_ happen or hang. So, use +// this sparingly, make sure to cancel the read or write as necesary +// (e.g. closing a connection whose context is up, etc.) +// +// Furthermore, in order to protect your memory from being read +// _after_ you've cancelled the context, this io.Writer will +// first make a **copy** of the buffer. +func NewWriter(ctx context.Context, w io.Writer) *ctxWriter { + if ctx == nil { + ctx = context.Background() + } + return &ctxWriter{ctx: ctx, w: w} +} + +func (w *ctxWriter) Write(buf []byte) (int, error) { + buf2 := make([]byte, len(buf)) + copy(buf2, buf) + + c := make(chan ioret, 1) + + go func() { + n, err := w.w.Write(buf2) + c <- ioret{n, err} + close(c) + }() + + select { + case r := <-c: + return r.n, r.err + case <-w.ctx.Done(): + return 0, w.ctx.Err() + } +} + +type Reader interface { + io.Reader +} + +type ctxReader struct { + r io.Reader + ctx context.Context +} + +// NewReader wraps a reader to make it respect given Context. +// If there is a blocking read, the returned Reader will return +// whenever the context is cancelled (the return values are n=0 +// and err=ctx.Err().) +// +// Note well: this wrapper DOES NOT ACTUALLY cancel the underlying +// write-- there is no way to do that with the standard go io +// interface. So the read and write _will_ happen or hang. So, use +// this sparingly, make sure to cancel the read or write as necesary +// (e.g. closing a connection whose context is up, etc.) +// +// Furthermore, in order to protect your memory from being read +// _before_ you've cancelled the context, this io.Reader will +// allocate a buffer of the same size, and **copy** into the client's +// if the read succeeds in time. +func NewReader(ctx context.Context, r io.Reader) *ctxReader { + return &ctxReader{ctx: ctx, r: r} +} + +func (r *ctxReader) Read(buf []byte) (int, error) { + buf2 := make([]byte, len(buf)) + + c := make(chan ioret, 1) + + go func() { + n, err := r.r.Read(buf2) + c <- ioret{n, err} + close(c) + }() + + select { + case ret := <-c: + copy(buf, buf2) + return ret.n, ret.err + case <-r.ctx.Done(): + return 0, r.ctx.Err() + } +} diff --git a/vendor/github.com/joelanford/ignore/.gitignore b/vendor/github.com/joelanford/ignore/.gitignore new file mode 100644 index 0000000000..a09c56df5c --- /dev/null +++ b/vendor/github.com/joelanford/ignore/.gitignore @@ -0,0 +1 @@ +/.idea diff --git a/vendor/github.com/joelanford/ignore/.golangci.yml b/vendor/github.com/joelanford/ignore/.golangci.yml new file mode 100644 index 0000000000..74cfe977e7 --- /dev/null +++ b/vendor/github.com/joelanford/ignore/.golangci.yml @@ -0,0 +1,17 @@ +run: + timeout: 5m +linters: + disable-all: true + enable: + - govet + - errcheck + - staticcheck + - unused + - gosimple + - structcheck + - varcheck + - ineffassign + - deadcode + - typecheck + - gofmt + - goconst diff --git a/vendor/github.com/joelanford/ignore/LICENSE b/vendor/github.com/joelanford/ignore/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/vendor/github.com/joelanford/ignore/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/joelanford/ignore/ignore.go b/vendor/github.com/joelanford/ignore/ignore.go new file mode 100644 index 0000000000..5245b6a490 --- /dev/null +++ b/vendor/github.com/joelanford/ignore/ignore.go @@ -0,0 +1,70 @@ +package ignore + +import ( + "bufio" + "io/fs" + "path/filepath" + "strings" + + "github.com/go-git/go-git/v5/plumbing/format/gitignore" +) + +type Matcher interface { + Match(path string, isDir bool) bool +} + +type matcher struct { + m gitignore.Matcher +} + +func (m matcher) Match(path string, isDir bool) bool { + return m.m.Match(strings.Split(path, string(filepath.Separator)), isDir) +} + +func NewMatcher(root fs.FS, ignoreFile string) (Matcher, error) { + patterns := []gitignore.Pattern{} + if err := fs.WalkDir(root, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if d.Name() != ignoreFile || d.IsDir() { + return nil + } + ps, err := loadPatterns(root, path) + if err != nil { + return err + } + patterns = append(patterns, ps...) + return nil + }); err != nil { + return nil, err + } + return &matcher{gitignore.NewMatcher(patterns)}, nil +} + +func loadPatterns(root fs.FS, path string) ([]gitignore.Pattern, error) { + domain := strings.Split(filepath.Dir(path), string(filepath.Separator)) + if len(domain) == 1 && domain[0] == "." { + domain = []string{} + } + f, err := root.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + + patterns := []gitignore.Pattern{} + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + + if strings.HasPrefix(line, "#") || line == "" { + continue + } + patterns = append(patterns, gitignore.ParsePattern(line, domain)) + } + if err := scanner.Err(); err != nil { + return nil, err + } + return patterns, nil +} diff --git a/vendor/github.com/liggitt/tabwriter/.travis.yml b/vendor/github.com/liggitt/tabwriter/.travis.yml new file mode 100644 index 0000000000..2768dc0727 --- /dev/null +++ b/vendor/github.com/liggitt/tabwriter/.travis.yml @@ -0,0 +1,11 @@ +language: go + +go: + - "1.8" + - "1.9" + - "1.10" + - "1.11" + - "1.12" + - master + +script: go test -v ./... diff --git a/vendor/github.com/liggitt/tabwriter/LICENSE b/vendor/github.com/liggitt/tabwriter/LICENSE new file mode 100644 index 0000000000..6a66aea5ea --- /dev/null +++ b/vendor/github.com/liggitt/tabwriter/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/liggitt/tabwriter/README.md b/vendor/github.com/liggitt/tabwriter/README.md new file mode 100644 index 0000000000..e75d35672e --- /dev/null +++ b/vendor/github.com/liggitt/tabwriter/README.md @@ -0,0 +1,7 @@ +This repo is a drop-in replacement for the golang [text/tabwriter](https://golang.org/pkg/text/tabwriter/) package. + +It is based on that package at [cf2c2ea8](https://github.com/golang/go/tree/cf2c2ea89d09d486bb018b1817c5874388038c3a/src/text/tabwriter) and inherits its license. + +The following additional features are supported: +* `RememberWidths` flag allows remembering maximum widths seen per column even after Flush() is called. +* `RememberedWidths() []int` and `SetRememberedWidths([]int) *Writer` allows obtaining and transferring remembered column width between writers. diff --git a/vendor/github.com/liggitt/tabwriter/tabwriter.go b/vendor/github.com/liggitt/tabwriter/tabwriter.go new file mode 100644 index 0000000000..fd3431fb03 --- /dev/null +++ b/vendor/github.com/liggitt/tabwriter/tabwriter.go @@ -0,0 +1,637 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package tabwriter implements a write filter (tabwriter.Writer) that +// translates tabbed columns in input into properly aligned text. +// +// It is a drop-in replacement for the golang text/tabwriter package (https://golang.org/pkg/text/tabwriter), +// based on that package at https://github.com/golang/go/tree/cf2c2ea89d09d486bb018b1817c5874388038c3a +// with support for additional features. +// +// The package is using the Elastic Tabstops algorithm described at +// http://nickgravgaard.com/elastictabstops/index.html. +package tabwriter + +import ( + "io" + "unicode/utf8" +) + +// ---------------------------------------------------------------------------- +// Filter implementation + +// A cell represents a segment of text terminated by tabs or line breaks. +// The text itself is stored in a separate buffer; cell only describes the +// segment's size in bytes, its width in runes, and whether it's an htab +// ('\t') terminated cell. +// +type cell struct { + size int // cell size in bytes + width int // cell width in runes + htab bool // true if the cell is terminated by an htab ('\t') +} + +// A Writer is a filter that inserts padding around tab-delimited +// columns in its input to align them in the output. +// +// The Writer treats incoming bytes as UTF-8-encoded text consisting +// of cells terminated by horizontal ('\t') or vertical ('\v') tabs, +// and newline ('\n') or formfeed ('\f') characters; both newline and +// formfeed act as line breaks. +// +// Tab-terminated cells in contiguous lines constitute a column. The +// Writer inserts padding as needed to make all cells in a column have +// the same width, effectively aligning the columns. It assumes that +// all characters have the same width, except for tabs for which a +// tabwidth must be specified. Column cells must be tab-terminated, not +// tab-separated: non-tab terminated trailing text at the end of a line +// forms a cell but that cell is not part of an aligned column. +// For instance, in this example (where | stands for a horizontal tab): +// +// aaaa|bbb|d +// aa |b |dd +// a | +// aa |cccc|eee +// +// the b and c are in distinct columns (the b column is not contiguous +// all the way). The d and e are not in a column at all (there's no +// terminating tab, nor would the column be contiguous). +// +// The Writer assumes that all Unicode code points have the same width; +// this may not be true in some fonts or if the string contains combining +// characters. +// +// If DiscardEmptyColumns is set, empty columns that are terminated +// entirely by vertical (or "soft") tabs are discarded. Columns +// terminated by horizontal (or "hard") tabs are not affected by +// this flag. +// +// If a Writer is configured to filter HTML, HTML tags and entities +// are passed through. The widths of tags and entities are +// assumed to be zero (tags) and one (entities) for formatting purposes. +// +// A segment of text may be escaped by bracketing it with Escape +// characters. The tabwriter passes escaped text segments through +// unchanged. In particular, it does not interpret any tabs or line +// breaks within the segment. If the StripEscape flag is set, the +// Escape characters are stripped from the output; otherwise they +// are passed through as well. For the purpose of formatting, the +// width of the escaped text is always computed excluding the Escape +// characters. +// +// The formfeed character acts like a newline but it also terminates +// all columns in the current line (effectively calling Flush). Tab- +// terminated cells in the next line start new columns. Unless found +// inside an HTML tag or inside an escaped text segment, formfeed +// characters appear as newlines in the output. +// +// The Writer must buffer input internally, because proper spacing +// of one line may depend on the cells in future lines. Clients must +// call Flush when done calling Write. +// +type Writer struct { + // configuration + output io.Writer + minwidth int + tabwidth int + padding int + padbytes [8]byte + flags uint + + // current state + buf []byte // collected text excluding tabs or line breaks + pos int // buffer position up to which cell.width of incomplete cell has been computed + cell cell // current incomplete cell; cell.width is up to buf[pos] excluding ignored sections + endChar byte // terminating char of escaped sequence (Escape for escapes, '>', ';' for HTML tags/entities, or 0) + lines [][]cell // list of lines; each line is a list of cells + widths []int // list of column widths in runes - re-used during formatting + + maxwidths []int // list of max column widths in runes +} + +// addLine adds a new line. +// flushed is a hint indicating whether the underlying writer was just flushed. +// If so, the previous line is not likely to be a good indicator of the new line's cells. +func (b *Writer) addLine(flushed bool) { + // Grow slice instead of appending, + // as that gives us an opportunity + // to re-use an existing []cell. + if n := len(b.lines) + 1; n <= cap(b.lines) { + b.lines = b.lines[:n] + b.lines[n-1] = b.lines[n-1][:0] + } else { + b.lines = append(b.lines, nil) + } + + if !flushed { + // The previous line is probably a good indicator + // of how many cells the current line will have. + // If the current line's capacity is smaller than that, + // abandon it and make a new one. + if n := len(b.lines); n >= 2 { + if prev := len(b.lines[n-2]); prev > cap(b.lines[n-1]) { + b.lines[n-1] = make([]cell, 0, prev) + } + } + } +} + +// Reset the current state. +func (b *Writer) reset() { + b.buf = b.buf[:0] + b.pos = 0 + b.cell = cell{} + b.endChar = 0 + b.lines = b.lines[0:0] + b.widths = b.widths[0:0] + b.addLine(true) +} + +// Internal representation (current state): +// +// - all text written is appended to buf; tabs and line breaks are stripped away +// - at any given time there is a (possibly empty) incomplete cell at the end +// (the cell starts after a tab or line break) +// - cell.size is the number of bytes belonging to the cell so far +// - cell.width is text width in runes of that cell from the start of the cell to +// position pos; html tags and entities are excluded from this width if html +// filtering is enabled +// - the sizes and widths of processed text are kept in the lines list +// which contains a list of cells for each line +// - the widths list is a temporary list with current widths used during +// formatting; it is kept in Writer because it's re-used +// +// |<---------- size ---------->| +// | | +// |<- width ->|<- ignored ->| | +// | | | | +// [---processed---tab------------......] +// ^ ^ ^ +// | | | +// buf start of incomplete cell pos + +// Formatting can be controlled with these flags. +const ( + // Ignore html tags and treat entities (starting with '&' + // and ending in ';') as single characters (width = 1). + FilterHTML uint = 1 << iota + + // Strip Escape characters bracketing escaped text segments + // instead of passing them through unchanged with the text. + StripEscape + + // Force right-alignment of cell content. + // Default is left-alignment. + AlignRight + + // Handle empty columns as if they were not present in + // the input in the first place. + DiscardEmptyColumns + + // Always use tabs for indentation columns (i.e., padding of + // leading empty cells on the left) independent of padchar. + TabIndent + + // Print a vertical bar ('|') between columns (after formatting). + // Discarded columns appear as zero-width columns ("||"). + Debug + + // Remember maximum widths seen per column even after Flush() is called. + RememberWidths +) + +// A Writer must be initialized with a call to Init. The first parameter (output) +// specifies the filter output. The remaining parameters control the formatting: +// +// minwidth minimal cell width including any padding +// tabwidth width of tab characters (equivalent number of spaces) +// padding padding added to a cell before computing its width +// padchar ASCII char used for padding +// if padchar == '\t', the Writer will assume that the +// width of a '\t' in the formatted output is tabwidth, +// and cells are left-aligned independent of align_left +// (for correct-looking results, tabwidth must correspond +// to the tab width in the viewer displaying the result) +// flags formatting control +// +func (b *Writer) Init(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer { + if minwidth < 0 || tabwidth < 0 || padding < 0 { + panic("negative minwidth, tabwidth, or padding") + } + b.output = output + b.minwidth = minwidth + b.tabwidth = tabwidth + b.padding = padding + for i := range b.padbytes { + b.padbytes[i] = padchar + } + if padchar == '\t' { + // tab padding enforces left-alignment + flags &^= AlignRight + } + b.flags = flags + + b.reset() + + return b +} + +// debugging support (keep code around) +func (b *Writer) dump() { + pos := 0 + for i, line := range b.lines { + print("(", i, ") ") + for _, c := range line { + print("[", string(b.buf[pos:pos+c.size]), "]") + pos += c.size + } + print("\n") + } + print("\n") +} + +// local error wrapper so we can distinguish errors we want to return +// as errors from genuine panics (which we don't want to return as errors) +type osError struct { + err error +} + +func (b *Writer) write0(buf []byte) { + n, err := b.output.Write(buf) + if n != len(buf) && err == nil { + err = io.ErrShortWrite + } + if err != nil { + panic(osError{err}) + } +} + +func (b *Writer) writeN(src []byte, n int) { + for n > len(src) { + b.write0(src) + n -= len(src) + } + b.write0(src[0:n]) +} + +var ( + newline = []byte{'\n'} + tabs = []byte("\t\t\t\t\t\t\t\t") +) + +func (b *Writer) writePadding(textw, cellw int, useTabs bool) { + if b.padbytes[0] == '\t' || useTabs { + // padding is done with tabs + if b.tabwidth == 0 { + return // tabs have no width - can't do any padding + } + // make cellw the smallest multiple of b.tabwidth + cellw = (cellw + b.tabwidth - 1) / b.tabwidth * b.tabwidth + n := cellw - textw // amount of padding + if n < 0 { + panic("internal error") + } + b.writeN(tabs, (n+b.tabwidth-1)/b.tabwidth) + return + } + + // padding is done with non-tab characters + b.writeN(b.padbytes[0:], cellw-textw) +} + +var vbar = []byte{'|'} + +func (b *Writer) writeLines(pos0 int, line0, line1 int) (pos int) { + pos = pos0 + for i := line0; i < line1; i++ { + line := b.lines[i] + + // if TabIndent is set, use tabs to pad leading empty cells + useTabs := b.flags&TabIndent != 0 + + for j, c := range line { + if j > 0 && b.flags&Debug != 0 { + // indicate column break + b.write0(vbar) + } + + if c.size == 0 { + // empty cell + if j < len(b.widths) { + b.writePadding(c.width, b.widths[j], useTabs) + } + } else { + // non-empty cell + useTabs = false + if b.flags&AlignRight == 0 { // align left + b.write0(b.buf[pos : pos+c.size]) + pos += c.size + if j < len(b.widths) { + b.writePadding(c.width, b.widths[j], false) + } + } else { // align right + if j < len(b.widths) { + b.writePadding(c.width, b.widths[j], false) + } + b.write0(b.buf[pos : pos+c.size]) + pos += c.size + } + } + } + + if i+1 == len(b.lines) { + // last buffered line - we don't have a newline, so just write + // any outstanding buffered data + b.write0(b.buf[pos : pos+b.cell.size]) + pos += b.cell.size + } else { + // not the last line - write newline + b.write0(newline) + } + } + return +} + +// Format the text between line0 and line1 (excluding line1); pos +// is the buffer position corresponding to the beginning of line0. +// Returns the buffer position corresponding to the beginning of +// line1 and an error, if any. +// +func (b *Writer) format(pos0 int, line0, line1 int) (pos int) { + pos = pos0 + column := len(b.widths) + for this := line0; this < line1; this++ { + line := b.lines[this] + + if column >= len(line)-1 { + continue + } + // cell exists in this column => this line + // has more cells than the previous line + // (the last cell per line is ignored because cells are + // tab-terminated; the last cell per line describes the + // text before the newline/formfeed and does not belong + // to a column) + + // print unprinted lines until beginning of block + pos = b.writeLines(pos, line0, this) + line0 = this + + // column block begin + width := b.minwidth // minimal column width + discardable := true // true if all cells in this column are empty and "soft" + for ; this < line1; this++ { + line = b.lines[this] + if column >= len(line)-1 { + break + } + // cell exists in this column + c := line[column] + // update width + if w := c.width + b.padding; w > width { + width = w + } + // update discardable + if c.width > 0 || c.htab { + discardable = false + } + } + // column block end + + // discard empty columns if necessary + if discardable && b.flags&DiscardEmptyColumns != 0 { + width = 0 + } + + if b.flags&RememberWidths != 0 { + if len(b.maxwidths) < len(b.widths) { + b.maxwidths = append(b.maxwidths, b.widths[len(b.maxwidths):]...) + } + + switch { + case len(b.maxwidths) == len(b.widths): + b.maxwidths = append(b.maxwidths, width) + case b.maxwidths[len(b.widths)] > width: + width = b.maxwidths[len(b.widths)] + case b.maxwidths[len(b.widths)] < width: + b.maxwidths[len(b.widths)] = width + } + } + + // format and print all columns to the right of this column + // (we know the widths of this column and all columns to the left) + b.widths = append(b.widths, width) // push width + pos = b.format(pos, line0, this) + b.widths = b.widths[0 : len(b.widths)-1] // pop width + line0 = this + } + + // print unprinted lines until end + return b.writeLines(pos, line0, line1) +} + +// Append text to current cell. +func (b *Writer) append(text []byte) { + b.buf = append(b.buf, text...) + b.cell.size += len(text) +} + +// Update the cell width. +func (b *Writer) updateWidth() { + b.cell.width += utf8.RuneCount(b.buf[b.pos:]) + b.pos = len(b.buf) +} + +// To escape a text segment, bracket it with Escape characters. +// For instance, the tab in this string "Ignore this tab: \xff\t\xff" +// does not terminate a cell and constitutes a single character of +// width one for formatting purposes. +// +// The value 0xff was chosen because it cannot appear in a valid UTF-8 sequence. +// +const Escape = '\xff' + +// Start escaped mode. +func (b *Writer) startEscape(ch byte) { + switch ch { + case Escape: + b.endChar = Escape + case '<': + b.endChar = '>' + case '&': + b.endChar = ';' + } +} + +// Terminate escaped mode. If the escaped text was an HTML tag, its width +// is assumed to be zero for formatting purposes; if it was an HTML entity, +// its width is assumed to be one. In all other cases, the width is the +// unicode width of the text. +// +func (b *Writer) endEscape() { + switch b.endChar { + case Escape: + b.updateWidth() + if b.flags&StripEscape == 0 { + b.cell.width -= 2 // don't count the Escape chars + } + case '>': // tag of zero width + case ';': + b.cell.width++ // entity, count as one rune + } + b.pos = len(b.buf) + b.endChar = 0 +} + +// Terminate the current cell by adding it to the list of cells of the +// current line. Returns the number of cells in that line. +// +func (b *Writer) terminateCell(htab bool) int { + b.cell.htab = htab + line := &b.lines[len(b.lines)-1] + *line = append(*line, b.cell) + b.cell = cell{} + return len(*line) +} + +func handlePanic(err *error, op string) { + if e := recover(); e != nil { + if nerr, ok := e.(osError); ok { + *err = nerr.err + return + } + panic("tabwriter: panic during " + op) + } +} + +// RememberedWidths returns a copy of the remembered per-column maximum widths. +// Requires use of the RememberWidths flag, and is not threadsafe. +func (b *Writer) RememberedWidths() []int { + retval := make([]int, len(b.maxwidths)) + copy(retval, b.maxwidths) + return retval +} + +// SetRememberedWidths sets the remembered per-column maximum widths. +// Requires use of the RememberWidths flag, and is not threadsafe. +func (b *Writer) SetRememberedWidths(widths []int) *Writer { + b.maxwidths = make([]int, len(widths)) + copy(b.maxwidths, widths) + return b +} + +// Flush should be called after the last call to Write to ensure +// that any data buffered in the Writer is written to output. Any +// incomplete escape sequence at the end is considered +// complete for formatting purposes. +func (b *Writer) Flush() error { + return b.flush() +} + +func (b *Writer) flush() (err error) { + defer b.reset() // even in the presence of errors + defer handlePanic(&err, "Flush") + + // add current cell if not empty + if b.cell.size > 0 { + if b.endChar != 0 { + // inside escape - terminate it even if incomplete + b.endEscape() + } + b.terminateCell(false) + } + + // format contents of buffer + b.format(0, 0, len(b.lines)) + return nil +} + +var hbar = []byte("---\n") + +// Write writes buf to the writer b. +// The only errors returned are ones encountered +// while writing to the underlying output stream. +// +func (b *Writer) Write(buf []byte) (n int, err error) { + defer handlePanic(&err, "Write") + + // split text into cells + n = 0 + for i, ch := range buf { + if b.endChar == 0 { + // outside escape + switch ch { + case '\t', '\v', '\n', '\f': + // end of cell + b.append(buf[n:i]) + b.updateWidth() + n = i + 1 // ch consumed + ncells := b.terminateCell(ch == '\t') + if ch == '\n' || ch == '\f' { + // terminate line + b.addLine(ch == '\f') + if ch == '\f' || ncells == 1 { + // A '\f' always forces a flush. Otherwise, if the previous + // line has only one cell which does not have an impact on + // the formatting of the following lines (the last cell per + // line is ignored by format()), thus we can flush the + // Writer contents. + if err = b.Flush(); err != nil { + return + } + if ch == '\f' && b.flags&Debug != 0 { + // indicate section break + b.write0(hbar) + } + } + } + + case Escape: + // start of escaped sequence + b.append(buf[n:i]) + b.updateWidth() + n = i + if b.flags&StripEscape != 0 { + n++ // strip Escape + } + b.startEscape(Escape) + + case '<', '&': + // possibly an html tag/entity + if b.flags&FilterHTML != 0 { + // begin of tag/entity + b.append(buf[n:i]) + b.updateWidth() + n = i + b.startEscape(ch) + } + } + + } else { + // inside escape + if ch == b.endChar { + // end of tag/entity + j := i + 1 + if ch == Escape && b.flags&StripEscape != 0 { + j = i // strip Escape + } + b.append(buf[n:j]) + n = i + 1 // ch consumed + b.endEscape() + } + } + } + + // append leftover text + b.append(buf[n:]) + n = len(buf) + return +} + +// NewWriter allocates and initializes a new tabwriter.Writer. +// The parameters are the same as for the Init function. +// +func NewWriter(output io.Writer, minwidth, tabwidth, padding int, padchar byte, flags uint) *Writer { + return new(Writer).Init(output, minwidth, tabwidth, padding, padchar, flags) +} diff --git a/vendor/github.com/mitchellh/go-wordwrap/LICENSE.md b/vendor/github.com/mitchellh/go-wordwrap/LICENSE.md new file mode 100644 index 0000000000..2298515904 --- /dev/null +++ b/vendor/github.com/mitchellh/go-wordwrap/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Mitchell Hashimoto + +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/mitchellh/go-wordwrap/README.md b/vendor/github.com/mitchellh/go-wordwrap/README.md new file mode 100644 index 0000000000..60ae311700 --- /dev/null +++ b/vendor/github.com/mitchellh/go-wordwrap/README.md @@ -0,0 +1,39 @@ +# go-wordwrap + +`go-wordwrap` (Golang package: `wordwrap`) is a package for Go that +automatically wraps words into multiple lines. The primary use case for this +is in formatting CLI output, but of course word wrapping is a generally useful +thing to do. + +## Installation and Usage + +Install using `go get github.com/mitchellh/go-wordwrap`. + +Full documentation is available at +http://godoc.org/github.com/mitchellh/go-wordwrap + +Below is an example of its usage ignoring errors: + +```go +wrapped := wordwrap.WrapString("foo bar baz", 3) +fmt.Println(wrapped) +``` + +Would output: + +``` +foo +bar +baz +``` + +## Word Wrap Algorithm + +This library doesn't use any clever algorithm for word wrapping. The wrapping +is actually very naive: whenever there is whitespace or an explicit linebreak. +The goal of this library is for word wrapping CLI output, so the input is +typically pretty well controlled human language. Because of this, the naive +approach typically works just fine. + +In the future, we'd like to make the algorithm more advanced. We would do +so without breaking the API. diff --git a/vendor/github.com/mitchellh/go-wordwrap/wordwrap.go b/vendor/github.com/mitchellh/go-wordwrap/wordwrap.go new file mode 100644 index 0000000000..f7bedda388 --- /dev/null +++ b/vendor/github.com/mitchellh/go-wordwrap/wordwrap.go @@ -0,0 +1,83 @@ +package wordwrap + +import ( + "bytes" + "unicode" +) + +const nbsp = 0xA0 + +// WrapString wraps the given string within lim width in characters. +// +// Wrapping is currently naive and only happens at white-space. A future +// version of the library will implement smarter wrapping. This means that +// pathological cases can dramatically reach past the limit, such as a very +// long word. +func WrapString(s string, lim uint) string { + // Initialize a buffer with a slightly larger size to account for breaks + init := make([]byte, 0, len(s)) + buf := bytes.NewBuffer(init) + + var current uint + var wordBuf, spaceBuf bytes.Buffer + var wordBufLen, spaceBufLen uint + + for _, char := range s { + if char == '\n' { + if wordBuf.Len() == 0 { + if current+spaceBufLen > lim { + current = 0 + } else { + current += spaceBufLen + spaceBuf.WriteTo(buf) + } + spaceBuf.Reset() + spaceBufLen = 0 + } else { + current += spaceBufLen + wordBufLen + spaceBuf.WriteTo(buf) + spaceBuf.Reset() + spaceBufLen = 0 + wordBuf.WriteTo(buf) + wordBuf.Reset() + wordBufLen = 0 + } + buf.WriteRune(char) + current = 0 + } else if unicode.IsSpace(char) && char != nbsp { + if spaceBuf.Len() == 0 || wordBuf.Len() > 0 { + current += spaceBufLen + wordBufLen + spaceBuf.WriteTo(buf) + spaceBuf.Reset() + spaceBufLen = 0 + wordBuf.WriteTo(buf) + wordBuf.Reset() + wordBufLen = 0 + } + + spaceBuf.WriteRune(char) + spaceBufLen++ + } else { + wordBuf.WriteRune(char) + wordBufLen++ + + if current+wordBufLen+spaceBufLen > lim && wordBufLen < lim { + buf.WriteRune('\n') + current = 0 + spaceBuf.Reset() + spaceBufLen = 0 + } + } + } + + if wordBuf.Len() == 0 { + if current+spaceBufLen <= lim { + spaceBuf.WriteTo(buf) + } + } else { + spaceBuf.WriteTo(buf) + wordBuf.WriteTo(buf) + } + + return buf.String() +} diff --git a/vendor/github.com/moby/spdystream/CONTRIBUTING.md b/vendor/github.com/moby/spdystream/CONTRIBUTING.md new file mode 100644 index 0000000000..d4eddcc539 --- /dev/null +++ b/vendor/github.com/moby/spdystream/CONTRIBUTING.md @@ -0,0 +1,13 @@ +# Contributing to SpdyStream + +Want to hack on spdystream? Awesome! Here are instructions to get you +started. + +SpdyStream is a part of the [Docker](https://docker.io) project, and follows +the same rules and principles. If you're already familiar with the way +Docker does things, you'll feel right at home. + +Otherwise, go read +[Docker's contributions guidelines](https://github.com/dotcloud/docker/blob/master/CONTRIBUTING.md). + +Happy hacking! diff --git a/vendor/github.com/moby/spdystream/LICENSE b/vendor/github.com/moby/spdystream/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/vendor/github.com/moby/spdystream/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/moby/spdystream/MAINTAINERS b/vendor/github.com/moby/spdystream/MAINTAINERS new file mode 100644 index 0000000000..26e5ec828a --- /dev/null +++ b/vendor/github.com/moby/spdystream/MAINTAINERS @@ -0,0 +1,40 @@ +# Spdystream maintainers file +# +# This file describes who runs the moby/spdystream project and how. +# This is a living document - if you see something out of date or missing, speak up! +# +# It is structured to be consumable by both humans and programs. +# To extract its contents programmatically, use any TOML-compliant parser. +# +# This file is compiled into the MAINTAINERS file in docker/opensource. +# +[Org] + [Org."Core maintainers"] + people = [ + "adisky", + "dims", + "dmcgowan", + ] + +[people] + +# A reference list of all people associated with the project. +# All other sections should refer to people by their canonical key +# in the people section. + + # ADD YOURSELF HERE IN ALPHABETICAL ORDER + + [people.adisky] + Name = "Aditi Sharma" + Email = "adi.sky17@gmail.com" + GitHub = "adisky" + + [people.dims] + Name = "Davanum Srinivas" + Email = "davanum@gmail.com" + GitHub = "dims" + + [people.dmcgowan] + Name = "Derek McGowan" + Email = "derek@mcg.dev" + GitHub = "dmcgowan" diff --git a/vendor/github.com/moby/spdystream/NOTICE b/vendor/github.com/moby/spdystream/NOTICE new file mode 100644 index 0000000000..b9b11c9ab7 --- /dev/null +++ b/vendor/github.com/moby/spdystream/NOTICE @@ -0,0 +1,5 @@ +SpdyStream +Copyright 2014-2021 Docker Inc. + +This product includes software developed at +Docker Inc. (https://www.docker.com/). diff --git a/vendor/github.com/moby/spdystream/README.md b/vendor/github.com/moby/spdystream/README.md new file mode 100644 index 0000000000..b84e983439 --- /dev/null +++ b/vendor/github.com/moby/spdystream/README.md @@ -0,0 +1,77 @@ +# SpdyStream + +A multiplexed stream library using spdy + +## Usage + +Client example (connecting to mirroring server without auth) + +```go +package main + +import ( + "fmt" + "github.com/moby/spdystream" + "net" + "net/http" +) + +func main() { + conn, err := net.Dial("tcp", "localhost:8080") + if err != nil { + panic(err) + } + spdyConn, err := spdystream.NewConnection(conn, false) + if err != nil { + panic(err) + } + go spdyConn.Serve(spdystream.NoOpStreamHandler) + stream, err := spdyConn.CreateStream(http.Header{}, nil, false) + if err != nil { + panic(err) + } + + stream.Wait() + + fmt.Fprint(stream, "Writing to stream") + + buf := make([]byte, 25) + stream.Read(buf) + fmt.Println(string(buf)) + + stream.Close() +} +``` + +Server example (mirroring server without auth) + +```go +package main + +import ( + "github.com/moby/spdystream" + "net" +) + +func main() { + listener, err := net.Listen("tcp", "localhost:8080") + if err != nil { + panic(err) + } + for { + conn, err := listener.Accept() + if err != nil { + panic(err) + } + spdyConn, err := spdystream.NewConnection(conn, true) + if err != nil { + panic(err) + } + go spdyConn.Serve(spdystream.MirrorStreamHandler) + } +} +``` + +## Copyright and license + +Copyright 2013-2021 Docker, inc. Released under the [Apache 2.0 license](LICENSE). diff --git a/vendor/github.com/moby/spdystream/connection.go b/vendor/github.com/moby/spdystream/connection.go new file mode 100644 index 0000000000..d906bb05ce --- /dev/null +++ b/vendor/github.com/moby/spdystream/connection.go @@ -0,0 +1,972 @@ +/* + Copyright 2014-2021 Docker Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package spdystream + +import ( + "errors" + "fmt" + "io" + "net" + "net/http" + "sync" + "time" + + "github.com/moby/spdystream/spdy" +) + +var ( + ErrInvalidStreamId = errors.New("Invalid stream id") + ErrTimeout = errors.New("Timeout occurred") + ErrReset = errors.New("Stream reset") + ErrWriteClosedStream = errors.New("Write on closed stream") +) + +const ( + FRAME_WORKERS = 5 + QUEUE_SIZE = 50 +) + +type StreamHandler func(stream *Stream) + +type AuthHandler func(header http.Header, slot uint8, parent uint32) bool + +type idleAwareFramer struct { + f *spdy.Framer + conn *Connection + writeLock sync.Mutex + resetChan chan struct{} + setTimeoutLock sync.Mutex + setTimeoutChan chan time.Duration + timeout time.Duration +} + +func newIdleAwareFramer(framer *spdy.Framer) *idleAwareFramer { + iaf := &idleAwareFramer{ + f: framer, + resetChan: make(chan struct{}, 2), + // setTimeoutChan needs to be buffered to avoid deadlocks when calling setIdleTimeout at about + // the same time the connection is being closed + setTimeoutChan: make(chan time.Duration, 1), + } + return iaf +} + +func (i *idleAwareFramer) monitor() { + var ( + timer *time.Timer + expired <-chan time.Time + resetChan = i.resetChan + setTimeoutChan = i.setTimeoutChan + ) +Loop: + for { + select { + case timeout := <-i.setTimeoutChan: + i.timeout = timeout + if timeout == 0 { + if timer != nil { + timer.Stop() + } + } else { + if timer == nil { + timer = time.NewTimer(timeout) + expired = timer.C + } else { + timer.Reset(timeout) + } + } + case <-resetChan: + if timer != nil && i.timeout > 0 { + timer.Reset(i.timeout) + } + case <-expired: + i.conn.streamCond.L.Lock() + streams := i.conn.streams + i.conn.streams = make(map[spdy.StreamId]*Stream) + i.conn.streamCond.Broadcast() + i.conn.streamCond.L.Unlock() + go func() { + for _, stream := range streams { + stream.resetStream() + } + i.conn.Close() + }() + case <-i.conn.closeChan: + if timer != nil { + timer.Stop() + } + + // Start a goroutine to drain resetChan. This is needed because we've seen + // some unit tests with large numbers of goroutines get into a situation + // where resetChan fills up, at least 1 call to Write() is still trying to + // send to resetChan, the connection gets closed, and this case statement + // attempts to grab the write lock that Write() already has, causing a + // deadlock. + // + // See https://github.com/moby/spdystream/issues/49 for more details. + go func() { + for range resetChan { + } + }() + + go func() { + for range setTimeoutChan { + } + }() + + i.writeLock.Lock() + close(resetChan) + i.resetChan = nil + i.writeLock.Unlock() + + i.setTimeoutLock.Lock() + close(i.setTimeoutChan) + i.setTimeoutChan = nil + i.setTimeoutLock.Unlock() + + break Loop + } + } + + // Drain resetChan + for range resetChan { + } +} + +func (i *idleAwareFramer) WriteFrame(frame spdy.Frame) error { + i.writeLock.Lock() + defer i.writeLock.Unlock() + if i.resetChan == nil { + return io.EOF + } + err := i.f.WriteFrame(frame) + if err != nil { + return err + } + + i.resetChan <- struct{}{} + + return nil +} + +func (i *idleAwareFramer) ReadFrame() (spdy.Frame, error) { + frame, err := i.f.ReadFrame() + if err != nil { + return nil, err + } + + // resetChan should never be closed since it is only closed + // when the connection has closed its closeChan. This closure + // only occurs after all Reads have finished + // TODO (dmcgowan): refactor relationship into connection + i.resetChan <- struct{}{} + + return frame, nil +} + +func (i *idleAwareFramer) setIdleTimeout(timeout time.Duration) { + i.setTimeoutLock.Lock() + defer i.setTimeoutLock.Unlock() + + if i.setTimeoutChan == nil { + return + } + + i.setTimeoutChan <- timeout +} + +type Connection struct { + conn net.Conn + framer *idleAwareFramer + + closeChan chan bool + goneAway bool + lastStreamChan chan<- *Stream + goAwayTimeout time.Duration + closeTimeout time.Duration + + streamLock *sync.RWMutex + streamCond *sync.Cond + streams map[spdy.StreamId]*Stream + + nextIdLock sync.Mutex + receiveIdLock sync.Mutex + nextStreamId spdy.StreamId + receivedStreamId spdy.StreamId + + pingIdLock sync.Mutex + pingId uint32 + pingChans map[uint32]chan error + + shutdownLock sync.Mutex + shutdownChan chan error + hasShutdown bool + + // for testing https://github.com/moby/spdystream/pull/56 + dataFrameHandler func(*spdy.DataFrame) error +} + +// NewConnection creates a new spdy connection from an existing +// network connection. +func NewConnection(conn net.Conn, server bool) (*Connection, error) { + framer, framerErr := spdy.NewFramer(conn, conn) + if framerErr != nil { + return nil, framerErr + } + idleAwareFramer := newIdleAwareFramer(framer) + var sid spdy.StreamId + var rid spdy.StreamId + var pid uint32 + if server { + sid = 2 + rid = 1 + pid = 2 + } else { + sid = 1 + rid = 2 + pid = 1 + } + + streamLock := new(sync.RWMutex) + streamCond := sync.NewCond(streamLock) + + session := &Connection{ + conn: conn, + framer: idleAwareFramer, + + closeChan: make(chan bool), + goAwayTimeout: time.Duration(0), + closeTimeout: time.Duration(0), + + streamLock: streamLock, + streamCond: streamCond, + streams: make(map[spdy.StreamId]*Stream), + nextStreamId: sid, + receivedStreamId: rid, + + pingId: pid, + pingChans: make(map[uint32]chan error), + + shutdownChan: make(chan error), + } + session.dataFrameHandler = session.handleDataFrame + idleAwareFramer.conn = session + go idleAwareFramer.monitor() + + return session, nil +} + +// Ping sends a ping frame across the connection and +// returns the response time +func (s *Connection) Ping() (time.Duration, error) { + pid := s.pingId + s.pingIdLock.Lock() + if s.pingId > 0x7ffffffe { + s.pingId = s.pingId - 0x7ffffffe + } else { + s.pingId = s.pingId + 2 + } + s.pingIdLock.Unlock() + pingChan := make(chan error) + s.pingChans[pid] = pingChan + defer delete(s.pingChans, pid) + + frame := &spdy.PingFrame{Id: pid} + startTime := time.Now() + writeErr := s.framer.WriteFrame(frame) + if writeErr != nil { + return time.Duration(0), writeErr + } + select { + case <-s.closeChan: + return time.Duration(0), errors.New("connection closed") + case err, ok := <-pingChan: + if ok && err != nil { + return time.Duration(0), err + } + break + } + return time.Since(startTime), nil +} + +// Serve handles frames sent from the server, including reply frames +// which are needed to fully initiate connections. Both clients and servers +// should call Serve in a separate goroutine before creating streams. +func (s *Connection) Serve(newHandler StreamHandler) { + // use a WaitGroup to wait for all frames to be drained after receiving + // go-away. + var wg sync.WaitGroup + + // Parition queues to ensure stream frames are handled + // by the same worker, ensuring order is maintained + frameQueues := make([]*PriorityFrameQueue, FRAME_WORKERS) + for i := 0; i < FRAME_WORKERS; i++ { + frameQueues[i] = NewPriorityFrameQueue(QUEUE_SIZE) + + // Ensure frame queue is drained when connection is closed + go func(frameQueue *PriorityFrameQueue) { + <-s.closeChan + frameQueue.Drain() + }(frameQueues[i]) + + wg.Add(1) + go func(frameQueue *PriorityFrameQueue) { + // let the WaitGroup know this worker is done + defer wg.Done() + + s.frameHandler(frameQueue, newHandler) + }(frameQueues[i]) + } + + var ( + partitionRoundRobin int + goAwayFrame *spdy.GoAwayFrame + ) +Loop: + for { + readFrame, err := s.framer.ReadFrame() + if err != nil { + if err != io.EOF { + debugMessage("frame read error: %s", err) + } else { + debugMessage("(%p) EOF received", s) + } + break + } + var priority uint8 + var partition int + switch frame := readFrame.(type) { + case *spdy.SynStreamFrame: + if s.checkStreamFrame(frame) { + priority = frame.Priority + partition = int(frame.StreamId % FRAME_WORKERS) + debugMessage("(%p) Add stream frame: %d ", s, frame.StreamId) + s.addStreamFrame(frame) + } else { + debugMessage("(%p) Rejected stream frame: %d ", s, frame.StreamId) + continue + } + case *spdy.SynReplyFrame: + priority = s.getStreamPriority(frame.StreamId) + partition = int(frame.StreamId % FRAME_WORKERS) + case *spdy.DataFrame: + priority = s.getStreamPriority(frame.StreamId) + partition = int(frame.StreamId % FRAME_WORKERS) + case *spdy.RstStreamFrame: + priority = s.getStreamPriority(frame.StreamId) + partition = int(frame.StreamId % FRAME_WORKERS) + case *spdy.HeadersFrame: + priority = s.getStreamPriority(frame.StreamId) + partition = int(frame.StreamId % FRAME_WORKERS) + case *spdy.PingFrame: + priority = 0 + partition = partitionRoundRobin + partitionRoundRobin = (partitionRoundRobin + 1) % FRAME_WORKERS + case *spdy.GoAwayFrame: + // hold on to the go away frame and exit the loop + goAwayFrame = frame + break Loop + default: + priority = 7 + partition = partitionRoundRobin + partitionRoundRobin = (partitionRoundRobin + 1) % FRAME_WORKERS + } + frameQueues[partition].Push(readFrame, priority) + } + close(s.closeChan) + + // wait for all frame handler workers to indicate they've drained their queues + // before handling the go away frame + wg.Wait() + + if goAwayFrame != nil { + s.handleGoAwayFrame(goAwayFrame) + } + + // now it's safe to close remote channels and empty s.streams + s.streamCond.L.Lock() + // notify streams that they're now closed, which will + // unblock any stream Read() calls + for _, stream := range s.streams { + stream.closeRemoteChannels() + } + s.streams = make(map[spdy.StreamId]*Stream) + s.streamCond.Broadcast() + s.streamCond.L.Unlock() +} + +func (s *Connection) frameHandler(frameQueue *PriorityFrameQueue, newHandler StreamHandler) { + for { + popFrame := frameQueue.Pop() + if popFrame == nil { + return + } + + var frameErr error + switch frame := popFrame.(type) { + case *spdy.SynStreamFrame: + frameErr = s.handleStreamFrame(frame, newHandler) + case *spdy.SynReplyFrame: + frameErr = s.handleReplyFrame(frame) + case *spdy.DataFrame: + frameErr = s.dataFrameHandler(frame) + case *spdy.RstStreamFrame: + frameErr = s.handleResetFrame(frame) + case *spdy.HeadersFrame: + frameErr = s.handleHeaderFrame(frame) + case *spdy.PingFrame: + frameErr = s.handlePingFrame(frame) + case *spdy.GoAwayFrame: + frameErr = s.handleGoAwayFrame(frame) + default: + frameErr = fmt.Errorf("unhandled frame type: %T", frame) + } + + if frameErr != nil { + debugMessage("frame handling error: %s", frameErr) + } + } +} + +func (s *Connection) getStreamPriority(streamId spdy.StreamId) uint8 { + stream, streamOk := s.getStream(streamId) + if !streamOk { + return 7 + } + return stream.priority +} + +func (s *Connection) addStreamFrame(frame *spdy.SynStreamFrame) { + var parent *Stream + if frame.AssociatedToStreamId != spdy.StreamId(0) { + parent, _ = s.getStream(frame.AssociatedToStreamId) + } + + stream := &Stream{ + streamId: frame.StreamId, + parent: parent, + conn: s, + startChan: make(chan error), + headers: frame.Headers, + finished: (frame.CFHeader.Flags & spdy.ControlFlagUnidirectional) != 0x00, + replyCond: sync.NewCond(new(sync.Mutex)), + dataChan: make(chan []byte), + headerChan: make(chan http.Header), + closeChan: make(chan bool), + priority: frame.Priority, + } + if frame.CFHeader.Flags&spdy.ControlFlagFin != 0x00 { + stream.closeRemoteChannels() + } + + s.addStream(stream) +} + +// checkStreamFrame checks to see if a stream frame is allowed. +// If the stream is invalid, then a reset frame with protocol error +// will be returned. +func (s *Connection) checkStreamFrame(frame *spdy.SynStreamFrame) bool { + s.receiveIdLock.Lock() + defer s.receiveIdLock.Unlock() + if s.goneAway { + return false + } + validationErr := s.validateStreamId(frame.StreamId) + if validationErr != nil { + go func() { + resetErr := s.sendResetFrame(spdy.ProtocolError, frame.StreamId) + if resetErr != nil { + debugMessage("reset error: %s", resetErr) + } + }() + return false + } + return true +} + +func (s *Connection) handleStreamFrame(frame *spdy.SynStreamFrame, newHandler StreamHandler) error { + stream, ok := s.getStream(frame.StreamId) + if !ok { + return fmt.Errorf("Missing stream: %d", frame.StreamId) + } + + newHandler(stream) + + return nil +} + +func (s *Connection) handleReplyFrame(frame *spdy.SynReplyFrame) error { + debugMessage("(%p) Reply frame received for %d", s, frame.StreamId) + stream, streamOk := s.getStream(frame.StreamId) + if !streamOk { + debugMessage("Reply frame gone away for %d", frame.StreamId) + // Stream has already gone away + return nil + } + if stream.replied { + // Stream has already received reply + return nil + } + stream.replied = true + + // TODO Check for error + if (frame.CFHeader.Flags & spdy.ControlFlagFin) != 0x00 { + s.remoteStreamFinish(stream) + } + + close(stream.startChan) + + return nil +} + +func (s *Connection) handleResetFrame(frame *spdy.RstStreamFrame) error { + stream, streamOk := s.getStream(frame.StreamId) + if !streamOk { + // Stream has already been removed + return nil + } + s.removeStream(stream) + stream.closeRemoteChannels() + + if !stream.replied { + stream.replied = true + stream.startChan <- ErrReset + close(stream.startChan) + } + + stream.finishLock.Lock() + stream.finished = true + stream.finishLock.Unlock() + + return nil +} + +func (s *Connection) handleHeaderFrame(frame *spdy.HeadersFrame) error { + stream, streamOk := s.getStream(frame.StreamId) + if !streamOk { + // Stream has already gone away + return nil + } + if !stream.replied { + // No reply received...Protocol error? + return nil + } + + // TODO limit headers while not blocking (use buffered chan or goroutine?) + select { + case <-stream.closeChan: + return nil + case stream.headerChan <- frame.Headers: + } + + if (frame.CFHeader.Flags & spdy.ControlFlagFin) != 0x00 { + s.remoteStreamFinish(stream) + } + + return nil +} + +func (s *Connection) handleDataFrame(frame *spdy.DataFrame) error { + debugMessage("(%p) Data frame received for %d", s, frame.StreamId) + stream, streamOk := s.getStream(frame.StreamId) + if !streamOk { + debugMessage("(%p) Data frame gone away for %d", s, frame.StreamId) + // Stream has already gone away + return nil + } + if !stream.replied { + debugMessage("(%p) Data frame not replied %d", s, frame.StreamId) + // No reply received...Protocol error? + return nil + } + + debugMessage("(%p) (%d) Data frame handling", stream, stream.streamId) + if len(frame.Data) > 0 { + stream.dataLock.RLock() + select { + case <-stream.closeChan: + debugMessage("(%p) (%d) Data frame not sent (stream shut down)", stream, stream.streamId) + case stream.dataChan <- frame.Data: + debugMessage("(%p) (%d) Data frame sent", stream, stream.streamId) + } + stream.dataLock.RUnlock() + } + if (frame.Flags & spdy.DataFlagFin) != 0x00 { + s.remoteStreamFinish(stream) + } + return nil +} + +func (s *Connection) handlePingFrame(frame *spdy.PingFrame) error { + if s.pingId&0x01 != frame.Id&0x01 { + return s.framer.WriteFrame(frame) + } + pingChan, pingOk := s.pingChans[frame.Id] + if pingOk { + close(pingChan) + } + return nil +} + +func (s *Connection) handleGoAwayFrame(frame *spdy.GoAwayFrame) error { + debugMessage("(%p) Go away received", s) + s.receiveIdLock.Lock() + if s.goneAway { + s.receiveIdLock.Unlock() + return nil + } + s.goneAway = true + s.receiveIdLock.Unlock() + + if s.lastStreamChan != nil { + stream, _ := s.getStream(frame.LastGoodStreamId) + go func() { + s.lastStreamChan <- stream + }() + } + + // Do not block frame handler waiting for closure + go s.shutdown(s.goAwayTimeout) + + return nil +} + +func (s *Connection) remoteStreamFinish(stream *Stream) { + stream.closeRemoteChannels() + + stream.finishLock.Lock() + if stream.finished { + // Stream is fully closed, cleanup + s.removeStream(stream) + } + stream.finishLock.Unlock() +} + +// CreateStream creates a new spdy stream using the parameters for +// creating the stream frame. The stream frame will be sent upon +// calling this function, however this function does not wait for +// the reply frame. If waiting for the reply is desired, use +// the stream Wait or WaitTimeout function on the stream returned +// by this function. +func (s *Connection) CreateStream(headers http.Header, parent *Stream, fin bool) (*Stream, error) { + // MUST synchronize stream creation (all the way to writing the frame) + // as stream IDs **MUST** increase monotonically. + s.nextIdLock.Lock() + defer s.nextIdLock.Unlock() + + streamId := s.getNextStreamId() + if streamId == 0 { + return nil, fmt.Errorf("Unable to get new stream id") + } + + stream := &Stream{ + streamId: streamId, + parent: parent, + conn: s, + startChan: make(chan error), + headers: headers, + dataChan: make(chan []byte), + headerChan: make(chan http.Header), + closeChan: make(chan bool), + } + + debugMessage("(%p) (%p) Create stream", s, stream) + + s.addStream(stream) + + return stream, s.sendStream(stream, fin) +} + +func (s *Connection) shutdown(closeTimeout time.Duration) { + // TODO Ensure this isn't called multiple times + s.shutdownLock.Lock() + if s.hasShutdown { + s.shutdownLock.Unlock() + return + } + s.hasShutdown = true + s.shutdownLock.Unlock() + + var timeout <-chan time.Time + if closeTimeout > time.Duration(0) { + timeout = time.After(closeTimeout) + } + streamsClosed := make(chan bool) + + go func() { + s.streamCond.L.Lock() + for len(s.streams) > 0 { + debugMessage("Streams opened: %d, %#v", len(s.streams), s.streams) + s.streamCond.Wait() + } + s.streamCond.L.Unlock() + close(streamsClosed) + }() + + var err error + select { + case <-streamsClosed: + // No active streams, close should be safe + err = s.conn.Close() + case <-timeout: + // Force ungraceful close + err = s.conn.Close() + // Wait for cleanup to clear active streams + <-streamsClosed + } + + if err != nil { + duration := 10 * time.Minute + time.AfterFunc(duration, func() { + select { + case err, ok := <-s.shutdownChan: + if ok { + debugMessage("Unhandled close error after %s: %s", duration, err) + } + default: + } + }) + s.shutdownChan <- err + } + close(s.shutdownChan) +} + +// Closes spdy connection by sending GoAway frame and initiating shutdown +func (s *Connection) Close() error { + s.receiveIdLock.Lock() + if s.goneAway { + s.receiveIdLock.Unlock() + return nil + } + s.goneAway = true + s.receiveIdLock.Unlock() + + var lastStreamId spdy.StreamId + if s.receivedStreamId > 2 { + lastStreamId = s.receivedStreamId - 2 + } + + goAwayFrame := &spdy.GoAwayFrame{ + LastGoodStreamId: lastStreamId, + Status: spdy.GoAwayOK, + } + + err := s.framer.WriteFrame(goAwayFrame) + go s.shutdown(s.closeTimeout) + if err != nil { + return err + } + + return nil +} + +// CloseWait closes the connection and waits for shutdown +// to finish. Note the underlying network Connection +// is not closed until the end of shutdown. +func (s *Connection) CloseWait() error { + closeErr := s.Close() + if closeErr != nil { + return closeErr + } + shutdownErr, ok := <-s.shutdownChan + if ok { + return shutdownErr + } + return nil +} + +// Wait waits for the connection to finish shutdown or for +// the wait timeout duration to expire. This needs to be +// called either after Close has been called or the GOAWAYFRAME +// has been received. If the wait timeout is 0, this function +// will block until shutdown finishes. If wait is never called +// and a shutdown error occurs, that error will be logged as an +// unhandled error. +func (s *Connection) Wait(waitTimeout time.Duration) error { + var timeout <-chan time.Time + if waitTimeout > time.Duration(0) { + timeout = time.After(waitTimeout) + } + + select { + case err, ok := <-s.shutdownChan: + if ok { + return err + } + case <-timeout: + return ErrTimeout + } + return nil +} + +// NotifyClose registers a channel to be called when the remote +// peer inidicates connection closure. The last stream to be +// received by the remote will be sent on the channel. The notify +// timeout will determine the duration between go away received +// and the connection being closed. +func (s *Connection) NotifyClose(c chan<- *Stream, timeout time.Duration) { + s.goAwayTimeout = timeout + s.lastStreamChan = c +} + +// SetCloseTimeout sets the amount of time close will wait for +// streams to finish before terminating the underlying network +// connection. Setting the timeout to 0 will cause close to +// wait forever, which is the default. +func (s *Connection) SetCloseTimeout(timeout time.Duration) { + s.closeTimeout = timeout +} + +// SetIdleTimeout sets the amount of time the connection may sit idle before +// it is forcefully terminated. +func (s *Connection) SetIdleTimeout(timeout time.Duration) { + s.framer.setIdleTimeout(timeout) +} + +func (s *Connection) sendHeaders(headers http.Header, stream *Stream, fin bool) error { + var flags spdy.ControlFlags + if fin { + flags = spdy.ControlFlagFin + } + + headerFrame := &spdy.HeadersFrame{ + StreamId: stream.streamId, + Headers: headers, + CFHeader: spdy.ControlFrameHeader{Flags: flags}, + } + + return s.framer.WriteFrame(headerFrame) +} + +func (s *Connection) sendReply(headers http.Header, stream *Stream, fin bool) error { + var flags spdy.ControlFlags + if fin { + flags = spdy.ControlFlagFin + } + + replyFrame := &spdy.SynReplyFrame{ + StreamId: stream.streamId, + Headers: headers, + CFHeader: spdy.ControlFrameHeader{Flags: flags}, + } + + return s.framer.WriteFrame(replyFrame) +} + +func (s *Connection) sendResetFrame(status spdy.RstStreamStatus, streamId spdy.StreamId) error { + resetFrame := &spdy.RstStreamFrame{ + StreamId: streamId, + Status: status, + } + + return s.framer.WriteFrame(resetFrame) +} + +func (s *Connection) sendReset(status spdy.RstStreamStatus, stream *Stream) error { + return s.sendResetFrame(status, stream.streamId) +} + +func (s *Connection) sendStream(stream *Stream, fin bool) error { + var flags spdy.ControlFlags + if fin { + flags = spdy.ControlFlagFin + stream.finished = true + } + + var parentId spdy.StreamId + if stream.parent != nil { + parentId = stream.parent.streamId + } + + streamFrame := &spdy.SynStreamFrame{ + StreamId: spdy.StreamId(stream.streamId), + AssociatedToStreamId: spdy.StreamId(parentId), + Headers: stream.headers, + CFHeader: spdy.ControlFrameHeader{Flags: flags}, + } + + return s.framer.WriteFrame(streamFrame) +} + +// getNextStreamId returns the next sequential id +// every call should produce a unique value or an error +func (s *Connection) getNextStreamId() spdy.StreamId { + sid := s.nextStreamId + if sid > 0x7fffffff { + return 0 + } + s.nextStreamId = s.nextStreamId + 2 + return sid +} + +// PeekNextStreamId returns the next sequential id and keeps the next id untouched +func (s *Connection) PeekNextStreamId() spdy.StreamId { + sid := s.nextStreamId + return sid +} + +func (s *Connection) validateStreamId(rid spdy.StreamId) error { + if rid > 0x7fffffff || rid < s.receivedStreamId { + return ErrInvalidStreamId + } + s.receivedStreamId = rid + 2 + return nil +} + +func (s *Connection) addStream(stream *Stream) { + s.streamCond.L.Lock() + s.streams[stream.streamId] = stream + debugMessage("(%p) (%p) Stream added, broadcasting: %d", s, stream, stream.streamId) + s.streamCond.Broadcast() + s.streamCond.L.Unlock() +} + +func (s *Connection) removeStream(stream *Stream) { + s.streamCond.L.Lock() + delete(s.streams, stream.streamId) + debugMessage("(%p) (%p) Stream removed, broadcasting: %d", s, stream, stream.streamId) + s.streamCond.Broadcast() + s.streamCond.L.Unlock() +} + +func (s *Connection) getStream(streamId spdy.StreamId) (stream *Stream, ok bool) { + s.streamLock.RLock() + stream, ok = s.streams[streamId] + s.streamLock.RUnlock() + return +} + +// FindStream looks up the given stream id and either waits for the +// stream to be found or returns nil if the stream id is no longer +// valid. +func (s *Connection) FindStream(streamId uint32) *Stream { + var stream *Stream + var ok bool + s.streamCond.L.Lock() + stream, ok = s.streams[spdy.StreamId(streamId)] + debugMessage("(%p) Found stream %d? %t", s, spdy.StreamId(streamId), ok) + for !ok && streamId >= uint32(s.receivedStreamId) { + s.streamCond.Wait() + stream, ok = s.streams[spdy.StreamId(streamId)] + } + s.streamCond.L.Unlock() + return stream +} + +func (s *Connection) CloseChan() <-chan bool { + return s.closeChan +} diff --git a/vendor/github.com/moby/spdystream/handlers.go b/vendor/github.com/moby/spdystream/handlers.go new file mode 100644 index 0000000000..d68f61f812 --- /dev/null +++ b/vendor/github.com/moby/spdystream/handlers.go @@ -0,0 +1,52 @@ +/* + Copyright 2014-2021 Docker Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package spdystream + +import ( + "io" + "net/http" +) + +// MirrorStreamHandler mirrors all streams. +func MirrorStreamHandler(stream *Stream) { + replyErr := stream.SendReply(http.Header{}, false) + if replyErr != nil { + return + } + + go func() { + io.Copy(stream, stream) + stream.Close() + }() + go func() { + for { + header, receiveErr := stream.ReceiveHeader() + if receiveErr != nil { + return + } + sendErr := stream.SendHeader(header, false) + if sendErr != nil { + return + } + } + }() +} + +// NoopStreamHandler does nothing when stream connects. +func NoOpStreamHandler(stream *Stream) { + stream.SendReply(http.Header{}, false) +} diff --git a/vendor/github.com/moby/spdystream/priority.go b/vendor/github.com/moby/spdystream/priority.go new file mode 100644 index 0000000000..d8eb3516ca --- /dev/null +++ b/vendor/github.com/moby/spdystream/priority.go @@ -0,0 +1,114 @@ +/* + Copyright 2014-2021 Docker Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package spdystream + +import ( + "container/heap" + "sync" + + "github.com/moby/spdystream/spdy" +) + +type prioritizedFrame struct { + frame spdy.Frame + priority uint8 + insertId uint64 +} + +type frameQueue []*prioritizedFrame + +func (fq frameQueue) Len() int { + return len(fq) +} + +func (fq frameQueue) Less(i, j int) bool { + if fq[i].priority == fq[j].priority { + return fq[i].insertId < fq[j].insertId + } + return fq[i].priority < fq[j].priority +} + +func (fq frameQueue) Swap(i, j int) { + fq[i], fq[j] = fq[j], fq[i] +} + +func (fq *frameQueue) Push(x interface{}) { + *fq = append(*fq, x.(*prioritizedFrame)) +} + +func (fq *frameQueue) Pop() interface{} { + old := *fq + n := len(old) + *fq = old[0 : n-1] + return old[n-1] +} + +type PriorityFrameQueue struct { + queue *frameQueue + c *sync.Cond + size int + nextInsertId uint64 + drain bool +} + +func NewPriorityFrameQueue(size int) *PriorityFrameQueue { + queue := make(frameQueue, 0, size) + heap.Init(&queue) + + return &PriorityFrameQueue{ + queue: &queue, + size: size, + c: sync.NewCond(&sync.Mutex{}), + } +} + +func (q *PriorityFrameQueue) Push(frame spdy.Frame, priority uint8) { + q.c.L.Lock() + defer q.c.L.Unlock() + for q.queue.Len() >= q.size { + q.c.Wait() + } + pFrame := &prioritizedFrame{ + frame: frame, + priority: priority, + insertId: q.nextInsertId, + } + q.nextInsertId = q.nextInsertId + 1 + heap.Push(q.queue, pFrame) + q.c.Signal() +} + +func (q *PriorityFrameQueue) Pop() spdy.Frame { + q.c.L.Lock() + defer q.c.L.Unlock() + for q.queue.Len() == 0 { + if q.drain { + return nil + } + q.c.Wait() + } + frame := heap.Pop(q.queue).(*prioritizedFrame).frame + q.c.Signal() + return frame +} + +func (q *PriorityFrameQueue) Drain() { + q.c.L.Lock() + defer q.c.L.Unlock() + q.drain = true + q.c.Broadcast() +} diff --git a/vendor/github.com/moby/spdystream/spdy/dictionary.go b/vendor/github.com/moby/spdystream/spdy/dictionary.go new file mode 100644 index 0000000000..392232f174 --- /dev/null +++ b/vendor/github.com/moby/spdystream/spdy/dictionary.go @@ -0,0 +1,203 @@ +/* + Copyright 2014-2021 Docker Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package spdy + +// headerDictionary is the dictionary sent to the zlib compressor/decompressor. +var headerDictionary = []byte{ + 0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, + 0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, + 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, + 0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, + 0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, + 0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, + 0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, + 0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, + 0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, + 0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, + 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, + 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, + 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, + 0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, + 0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, + 0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, + 0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, + 0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, + 0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, + 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, + 0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, + 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, + 0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, + 0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, + 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, + 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, + 0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, + 0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, + 0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, + 0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, + 0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, + 0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, + 0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, + 0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, + 0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, + 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, + 0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, + 0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, + 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, + 0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, + 0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, + 0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, + 0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, + 0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, + 0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, + 0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, + 0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, + 0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, + 0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, + 0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, + 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, + 0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, + 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, + 0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, + 0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, + 0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, + 0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, + 0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, + 0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, + 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, + 0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, + 0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, + 0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, + 0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, + 0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, + 0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, + 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, + 0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, + 0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, + 0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, + 0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, + 0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, + 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, + 0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, + 0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, + 0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, + 0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, + 0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, + 0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, + 0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, + 0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, + 0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, + 0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, + 0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, + 0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, + 0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, + 0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, + 0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, + 0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, + 0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, + 0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, + 0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, + 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, + 0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, + 0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, + 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, + 0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, + 0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, + 0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, + 0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, + 0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, + 0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, + 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, + 0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, + 0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, + 0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, + 0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, + 0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, + 0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, + 0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, + 0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, + 0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, + 0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, + 0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, + 0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, + 0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, + 0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, + 0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, + 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, + 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, + 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, + 0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, + 0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, + 0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, + 0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, + 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, + 0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, + 0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, + 0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, + 0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, + 0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, + 0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, + 0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, + 0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, + 0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, + 0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e, +} diff --git a/vendor/github.com/moby/spdystream/spdy/read.go b/vendor/github.com/moby/spdystream/spdy/read.go new file mode 100644 index 0000000000..75ea045b8e --- /dev/null +++ b/vendor/github.com/moby/spdystream/spdy/read.go @@ -0,0 +1,364 @@ +/* + Copyright 2014-2021 Docker Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package spdy + +import ( + "compress/zlib" + "encoding/binary" + "io" + "net/http" + "strings" +) + +func (frame *SynStreamFrame) read(h ControlFrameHeader, f *Framer) error { + return f.readSynStreamFrame(h, frame) +} + +func (frame *SynReplyFrame) read(h ControlFrameHeader, f *Framer) error { + return f.readSynReplyFrame(h, frame) +} + +func (frame *RstStreamFrame) read(h ControlFrameHeader, f *Framer) error { + frame.CFHeader = h + if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil { + return err + } + if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil { + return err + } + if frame.Status == 0 { + return &Error{InvalidControlFrame, frame.StreamId} + } + if frame.StreamId == 0 { + return &Error{ZeroStreamId, 0} + } + return nil +} + +func (frame *SettingsFrame) read(h ControlFrameHeader, f *Framer) error { + frame.CFHeader = h + var numSettings uint32 + if err := binary.Read(f.r, binary.BigEndian, &numSettings); err != nil { + return err + } + frame.FlagIdValues = make([]SettingsFlagIdValue, numSettings) + for i := uint32(0); i < numSettings; i++ { + if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Id); err != nil { + return err + } + frame.FlagIdValues[i].Flag = SettingsFlag((frame.FlagIdValues[i].Id & 0xff000000) >> 24) + frame.FlagIdValues[i].Id &= 0xffffff + if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Value); err != nil { + return err + } + } + return nil +} + +func (frame *PingFrame) read(h ControlFrameHeader, f *Framer) error { + frame.CFHeader = h + if err := binary.Read(f.r, binary.BigEndian, &frame.Id); err != nil { + return err + } + if frame.Id == 0 { + return &Error{ZeroStreamId, 0} + } + if frame.CFHeader.Flags != 0 { + return &Error{InvalidControlFrame, StreamId(frame.Id)} + } + return nil +} + +func (frame *GoAwayFrame) read(h ControlFrameHeader, f *Framer) error { + frame.CFHeader = h + if err := binary.Read(f.r, binary.BigEndian, &frame.LastGoodStreamId); err != nil { + return err + } + if frame.CFHeader.Flags != 0 { + return &Error{InvalidControlFrame, frame.LastGoodStreamId} + } + if frame.CFHeader.length != 8 { + return &Error{InvalidControlFrame, frame.LastGoodStreamId} + } + if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil { + return err + } + return nil +} + +func (frame *HeadersFrame) read(h ControlFrameHeader, f *Framer) error { + return f.readHeadersFrame(h, frame) +} + +func (frame *WindowUpdateFrame) read(h ControlFrameHeader, f *Framer) error { + frame.CFHeader = h + if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil { + return err + } + if frame.CFHeader.Flags != 0 { + return &Error{InvalidControlFrame, frame.StreamId} + } + if frame.CFHeader.length != 8 { + return &Error{InvalidControlFrame, frame.StreamId} + } + if err := binary.Read(f.r, binary.BigEndian, &frame.DeltaWindowSize); err != nil { + return err + } + return nil +} + +func newControlFrame(frameType ControlFrameType) (controlFrame, error) { + ctor, ok := cframeCtor[frameType] + if !ok { + return nil, &Error{Err: InvalidControlFrame} + } + return ctor(), nil +} + +var cframeCtor = map[ControlFrameType]func() controlFrame{ + TypeSynStream: func() controlFrame { return new(SynStreamFrame) }, + TypeSynReply: func() controlFrame { return new(SynReplyFrame) }, + TypeRstStream: func() controlFrame { return new(RstStreamFrame) }, + TypeSettings: func() controlFrame { return new(SettingsFrame) }, + TypePing: func() controlFrame { return new(PingFrame) }, + TypeGoAway: func() controlFrame { return new(GoAwayFrame) }, + TypeHeaders: func() controlFrame { return new(HeadersFrame) }, + TypeWindowUpdate: func() controlFrame { return new(WindowUpdateFrame) }, +} + +func (f *Framer) uncorkHeaderDecompressor(payloadSize int64) error { + if f.headerDecompressor != nil { + f.headerReader.N = payloadSize + return nil + } + f.headerReader = io.LimitedReader{R: f.r, N: payloadSize} + decompressor, err := zlib.NewReaderDict(&f.headerReader, []byte(headerDictionary)) + if err != nil { + return err + } + f.headerDecompressor = decompressor + return nil +} + +// ReadFrame reads SPDY encoded data and returns a decompressed Frame. +func (f *Framer) ReadFrame() (Frame, error) { + var firstWord uint32 + if err := binary.Read(f.r, binary.BigEndian, &firstWord); err != nil { + return nil, err + } + if firstWord&0x80000000 != 0 { + frameType := ControlFrameType(firstWord & 0xffff) + version := uint16(firstWord >> 16 & 0x7fff) + return f.parseControlFrame(version, frameType) + } + return f.parseDataFrame(StreamId(firstWord & 0x7fffffff)) +} + +func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) (Frame, error) { + var length uint32 + if err := binary.Read(f.r, binary.BigEndian, &length); err != nil { + return nil, err + } + flags := ControlFlags((length & 0xff000000) >> 24) + length &= 0xffffff + header := ControlFrameHeader{version, frameType, flags, length} + cframe, err := newControlFrame(frameType) + if err != nil { + return nil, err + } + if err = cframe.read(header, f); err != nil { + return nil, err + } + return cframe, nil +} + +func parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) { + var numHeaders uint32 + if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil { + return nil, err + } + var e error + h := make(http.Header, int(numHeaders)) + for i := 0; i < int(numHeaders); i++ { + var length uint32 + if err := binary.Read(r, binary.BigEndian, &length); err != nil { + return nil, err + } + nameBytes := make([]byte, length) + if _, err := io.ReadFull(r, nameBytes); err != nil { + return nil, err + } + name := string(nameBytes) + if name != strings.ToLower(name) { + e = &Error{UnlowercasedHeaderName, streamId} + name = strings.ToLower(name) + } + if h[name] != nil { + e = &Error{DuplicateHeaders, streamId} + } + if err := binary.Read(r, binary.BigEndian, &length); err != nil { + return nil, err + } + value := make([]byte, length) + if _, err := io.ReadFull(r, value); err != nil { + return nil, err + } + valueList := strings.Split(string(value), headerValueSeparator) + for _, v := range valueList { + h.Add(name, v) + } + } + if e != nil { + return h, e + } + return h, nil +} + +func (f *Framer) readSynStreamFrame(h ControlFrameHeader, frame *SynStreamFrame) error { + frame.CFHeader = h + var err error + if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil { + return err + } + if err = binary.Read(f.r, binary.BigEndian, &frame.AssociatedToStreamId); err != nil { + return err + } + if err = binary.Read(f.r, binary.BigEndian, &frame.Priority); err != nil { + return err + } + frame.Priority >>= 5 + if err = binary.Read(f.r, binary.BigEndian, &frame.Slot); err != nil { + return err + } + reader := f.r + if !f.headerCompressionDisabled { + err := f.uncorkHeaderDecompressor(int64(h.length - 10)) + if err != nil { + return err + } + reader = f.headerDecompressor + } + frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId) + if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) { + err = &Error{WrongCompressedPayloadSize, 0} + } + if err != nil { + return err + } + for h := range frame.Headers { + if invalidReqHeaders[h] { + return &Error{InvalidHeaderPresent, frame.StreamId} + } + } + if frame.StreamId == 0 { + return &Error{ZeroStreamId, 0} + } + return nil +} + +func (f *Framer) readSynReplyFrame(h ControlFrameHeader, frame *SynReplyFrame) error { + frame.CFHeader = h + var err error + if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil { + return err + } + reader := f.r + if !f.headerCompressionDisabled { + err := f.uncorkHeaderDecompressor(int64(h.length - 4)) + if err != nil { + return err + } + reader = f.headerDecompressor + } + frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId) + if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) { + err = &Error{WrongCompressedPayloadSize, 0} + } + if err != nil { + return err + } + for h := range frame.Headers { + if invalidRespHeaders[h] { + return &Error{InvalidHeaderPresent, frame.StreamId} + } + } + if frame.StreamId == 0 { + return &Error{ZeroStreamId, 0} + } + return nil +} + +func (f *Framer) readHeadersFrame(h ControlFrameHeader, frame *HeadersFrame) error { + frame.CFHeader = h + var err error + if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil { + return err + } + reader := f.r + if !f.headerCompressionDisabled { + err := f.uncorkHeaderDecompressor(int64(h.length - 4)) + if err != nil { + return err + } + reader = f.headerDecompressor + } + frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId) + if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) { + err = &Error{WrongCompressedPayloadSize, 0} + } + if err != nil { + return err + } + var invalidHeaders map[string]bool + if frame.StreamId%2 == 0 { + invalidHeaders = invalidReqHeaders + } else { + invalidHeaders = invalidRespHeaders + } + for h := range frame.Headers { + if invalidHeaders[h] { + return &Error{InvalidHeaderPresent, frame.StreamId} + } + } + if frame.StreamId == 0 { + return &Error{ZeroStreamId, 0} + } + return nil +} + +func (f *Framer) parseDataFrame(streamId StreamId) (*DataFrame, error) { + var length uint32 + if err := binary.Read(f.r, binary.BigEndian, &length); err != nil { + return nil, err + } + var frame DataFrame + frame.StreamId = streamId + frame.Flags = DataFlags(length >> 24) + length &= 0xffffff + frame.Data = make([]byte, length) + if _, err := io.ReadFull(f.r, frame.Data); err != nil { + return nil, err + } + if frame.StreamId == 0 { + return nil, &Error{ZeroStreamId, 0} + } + return &frame, nil +} diff --git a/vendor/github.com/moby/spdystream/spdy/types.go b/vendor/github.com/moby/spdystream/spdy/types.go new file mode 100644 index 0000000000..a254a43ab9 --- /dev/null +++ b/vendor/github.com/moby/spdystream/spdy/types.go @@ -0,0 +1,291 @@ +/* + Copyright 2014-2021 Docker Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package spdy implements the SPDY protocol (currently SPDY/3), described in +// http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3. +package spdy + +import ( + "bytes" + "compress/zlib" + "io" + "net/http" +) + +// Version is the protocol version number that this package implements. +const Version = 3 + +// ControlFrameType stores the type field in a control frame header. +type ControlFrameType uint16 + +const ( + TypeSynStream ControlFrameType = 0x0001 + TypeSynReply ControlFrameType = 0x0002 + TypeRstStream ControlFrameType = 0x0003 + TypeSettings ControlFrameType = 0x0004 + TypePing ControlFrameType = 0x0006 + TypeGoAway ControlFrameType = 0x0007 + TypeHeaders ControlFrameType = 0x0008 + TypeWindowUpdate ControlFrameType = 0x0009 +) + +// ControlFlags are the flags that can be set on a control frame. +type ControlFlags uint8 + +const ( + ControlFlagFin ControlFlags = 0x01 + ControlFlagUnidirectional ControlFlags = 0x02 + ControlFlagSettingsClearSettings ControlFlags = 0x01 +) + +// DataFlags are the flags that can be set on a data frame. +type DataFlags uint8 + +const ( + DataFlagFin DataFlags = 0x01 +) + +// MaxDataLength is the maximum number of bytes that can be stored in one frame. +const MaxDataLength = 1<<24 - 1 + +// headerValueSepator separates multiple header values. +const headerValueSeparator = "\x00" + +// Frame is a single SPDY frame in its unpacked in-memory representation. Use +// Framer to read and write it. +type Frame interface { + write(f *Framer) error +} + +// ControlFrameHeader contains all the fields in a control frame header, +// in its unpacked in-memory representation. +type ControlFrameHeader struct { + // Note, high bit is the "Control" bit. + version uint16 // spdy version number + frameType ControlFrameType + Flags ControlFlags + length uint32 // length of data field +} + +type controlFrame interface { + Frame + read(h ControlFrameHeader, f *Framer) error +} + +// StreamId represents a 31-bit value identifying the stream. +type StreamId uint32 + +// SynStreamFrame is the unpacked, in-memory representation of a SYN_STREAM +// frame. +type SynStreamFrame struct { + CFHeader ControlFrameHeader + StreamId StreamId + AssociatedToStreamId StreamId // stream id for a stream which this stream is associated to + Priority uint8 // priority of this frame (3-bit) + Slot uint8 // index in the server's credential vector of the client certificate + Headers http.Header +} + +// SynReplyFrame is the unpacked, in-memory representation of a SYN_REPLY frame. +type SynReplyFrame struct { + CFHeader ControlFrameHeader + StreamId StreamId + Headers http.Header +} + +// RstStreamStatus represents the status that led to a RST_STREAM. +type RstStreamStatus uint32 + +const ( + ProtocolError RstStreamStatus = iota + 1 + InvalidStream + RefusedStream + UnsupportedVersion + Cancel + InternalError + FlowControlError + StreamInUse + StreamAlreadyClosed + InvalidCredentials + FrameTooLarge +) + +// RstStreamFrame is the unpacked, in-memory representation of a RST_STREAM +// frame. +type RstStreamFrame struct { + CFHeader ControlFrameHeader + StreamId StreamId + Status RstStreamStatus +} + +// SettingsFlag represents a flag in a SETTINGS frame. +type SettingsFlag uint8 + +const ( + FlagSettingsPersistValue SettingsFlag = 0x1 + FlagSettingsPersisted SettingsFlag = 0x2 +) + +// SettingsFlag represents the id of an id/value pair in a SETTINGS frame. +type SettingsId uint32 + +const ( + SettingsUploadBandwidth SettingsId = iota + 1 + SettingsDownloadBandwidth + SettingsRoundTripTime + SettingsMaxConcurrentStreams + SettingsCurrentCwnd + SettingsDownloadRetransRate + SettingsInitialWindowSize + SettingsClientCretificateVectorSize +) + +// SettingsFlagIdValue is the unpacked, in-memory representation of the +// combined flag/id/value for a setting in a SETTINGS frame. +type SettingsFlagIdValue struct { + Flag SettingsFlag + Id SettingsId + Value uint32 +} + +// SettingsFrame is the unpacked, in-memory representation of a SPDY +// SETTINGS frame. +type SettingsFrame struct { + CFHeader ControlFrameHeader + FlagIdValues []SettingsFlagIdValue +} + +// PingFrame is the unpacked, in-memory representation of a PING frame. +type PingFrame struct { + CFHeader ControlFrameHeader + Id uint32 // unique id for this ping, from server is even, from client is odd. +} + +// GoAwayStatus represents the status in a GoAwayFrame. +type GoAwayStatus uint32 + +const ( + GoAwayOK GoAwayStatus = iota + GoAwayProtocolError + GoAwayInternalError +) + +// GoAwayFrame is the unpacked, in-memory representation of a GOAWAY frame. +type GoAwayFrame struct { + CFHeader ControlFrameHeader + LastGoodStreamId StreamId // last stream id which was accepted by sender + Status GoAwayStatus +} + +// HeadersFrame is the unpacked, in-memory representation of a HEADERS frame. +type HeadersFrame struct { + CFHeader ControlFrameHeader + StreamId StreamId + Headers http.Header +} + +// WindowUpdateFrame is the unpacked, in-memory representation of a +// WINDOW_UPDATE frame. +type WindowUpdateFrame struct { + CFHeader ControlFrameHeader + StreamId StreamId + DeltaWindowSize uint32 // additional number of bytes to existing window size +} + +// TODO: Implement credential frame and related methods. + +// DataFrame is the unpacked, in-memory representation of a DATA frame. +type DataFrame struct { + // Note, high bit is the "Control" bit. Should be 0 for data frames. + StreamId StreamId + Flags DataFlags + Data []byte // payload data of this frame +} + +// A SPDY specific error. +type ErrorCode string + +const ( + UnlowercasedHeaderName ErrorCode = "header was not lowercased" + DuplicateHeaders ErrorCode = "multiple headers with same name" + WrongCompressedPayloadSize ErrorCode = "compressed payload size was incorrect" + UnknownFrameType ErrorCode = "unknown frame type" + InvalidControlFrame ErrorCode = "invalid control frame" + InvalidDataFrame ErrorCode = "invalid data frame" + InvalidHeaderPresent ErrorCode = "frame contained invalid header" + ZeroStreamId ErrorCode = "stream id zero is disallowed" +) + +// Error contains both the type of error and additional values. StreamId is 0 +// if Error is not associated with a stream. +type Error struct { + Err ErrorCode + StreamId StreamId +} + +func (e *Error) Error() string { + return string(e.Err) +} + +var invalidReqHeaders = map[string]bool{ + "Connection": true, + "Host": true, + "Keep-Alive": true, + "Proxy-Connection": true, + "Transfer-Encoding": true, +} + +var invalidRespHeaders = map[string]bool{ + "Connection": true, + "Keep-Alive": true, + "Proxy-Connection": true, + "Transfer-Encoding": true, +} + +// Framer handles serializing/deserializing SPDY frames, including compressing/ +// decompressing payloads. +type Framer struct { + headerCompressionDisabled bool + w io.Writer + headerBuf *bytes.Buffer + headerCompressor *zlib.Writer + r io.Reader + headerReader io.LimitedReader + headerDecompressor io.ReadCloser +} + +// NewFramer allocates a new Framer for a given SPDY connection, represented by +// a io.Writer and io.Reader. Note that Framer will read and write individual fields +// from/to the Reader and Writer, so the caller should pass in an appropriately +// buffered implementation to optimize performance. +func NewFramer(w io.Writer, r io.Reader) (*Framer, error) { + compressBuf := new(bytes.Buffer) + compressor, err := zlib.NewWriterLevelDict(compressBuf, zlib.BestCompression, []byte(headerDictionary)) + if err != nil { + return nil, err + } + framer := &Framer{ + w: w, + headerBuf: compressBuf, + headerCompressor: compressor, + r: r, + } + return framer, nil +} diff --git a/vendor/github.com/moby/spdystream/spdy/write.go b/vendor/github.com/moby/spdystream/spdy/write.go new file mode 100644 index 0000000000..ab6d91f3b8 --- /dev/null +++ b/vendor/github.com/moby/spdystream/spdy/write.go @@ -0,0 +1,334 @@ +/* + Copyright 2014-2021 Docker Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package spdy + +import ( + "encoding/binary" + "io" + "net/http" + "strings" +) + +func (frame *SynStreamFrame) write(f *Framer) error { + return f.writeSynStreamFrame(frame) +} + +func (frame *SynReplyFrame) write(f *Framer) error { + return f.writeSynReplyFrame(frame) +} + +func (frame *RstStreamFrame) write(f *Framer) (err error) { + if frame.StreamId == 0 { + return &Error{ZeroStreamId, 0} + } + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypeRstStream + frame.CFHeader.Flags = 0 + frame.CFHeader.length = 8 + + // Serialize frame to Writer. + if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil { + return + } + if frame.Status == 0 { + return &Error{InvalidControlFrame, frame.StreamId} + } + if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil { + return + } + return +} + +func (frame *SettingsFrame) write(f *Framer) (err error) { + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypeSettings + frame.CFHeader.length = uint32(len(frame.FlagIdValues)*8 + 4) + + // Serialize frame to Writer. + if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, uint32(len(frame.FlagIdValues))); err != nil { + return + } + for _, flagIdValue := range frame.FlagIdValues { + flagId := uint32(flagIdValue.Flag)<<24 | uint32(flagIdValue.Id) + if err = binary.Write(f.w, binary.BigEndian, flagId); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, flagIdValue.Value); err != nil { + return + } + } + return +} + +func (frame *PingFrame) write(f *Framer) (err error) { + if frame.Id == 0 { + return &Error{ZeroStreamId, 0} + } + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypePing + frame.CFHeader.Flags = 0 + frame.CFHeader.length = 4 + + // Serialize frame to Writer. + if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, frame.Id); err != nil { + return + } + return +} + +func (frame *GoAwayFrame) write(f *Framer) (err error) { + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypeGoAway + frame.CFHeader.Flags = 0 + frame.CFHeader.length = 8 + + // Serialize frame to Writer. + if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, frame.LastGoodStreamId); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil { + return + } + return nil +} + +func (frame *HeadersFrame) write(f *Framer) error { + return f.writeHeadersFrame(frame) +} + +func (frame *WindowUpdateFrame) write(f *Framer) (err error) { + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypeWindowUpdate + frame.CFHeader.Flags = 0 + frame.CFHeader.length = 8 + + // Serialize frame to Writer. + if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, frame.DeltaWindowSize); err != nil { + return + } + return nil +} + +func (frame *DataFrame) write(f *Framer) error { + return f.writeDataFrame(frame) +} + +// WriteFrame writes a frame. +func (f *Framer) WriteFrame(frame Frame) error { + return frame.write(f) +} + +func writeControlFrameHeader(w io.Writer, h ControlFrameHeader) error { + if err := binary.Write(w, binary.BigEndian, 0x8000|h.version); err != nil { + return err + } + if err := binary.Write(w, binary.BigEndian, h.frameType); err != nil { + return err + } + flagsAndLength := uint32(h.Flags)<<24 | h.length + if err := binary.Write(w, binary.BigEndian, flagsAndLength); err != nil { + return err + } + return nil +} + +func writeHeaderValueBlock(w io.Writer, h http.Header) (n int, err error) { + n = 0 + if err = binary.Write(w, binary.BigEndian, uint32(len(h))); err != nil { + return + } + n += 2 + for name, values := range h { + if err = binary.Write(w, binary.BigEndian, uint32(len(name))); err != nil { + return + } + n += 2 + name = strings.ToLower(name) + if _, err = io.WriteString(w, name); err != nil { + return + } + n += len(name) + v := strings.Join(values, headerValueSeparator) + if err = binary.Write(w, binary.BigEndian, uint32(len(v))); err != nil { + return + } + n += 2 + if _, err = io.WriteString(w, v); err != nil { + return + } + n += len(v) + } + return +} + +func (f *Framer) writeSynStreamFrame(frame *SynStreamFrame) (err error) { + if frame.StreamId == 0 { + return &Error{ZeroStreamId, 0} + } + // Marshal the headers. + var writer io.Writer = f.headerBuf + if !f.headerCompressionDisabled { + writer = f.headerCompressor + } + if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil { + return + } + if !f.headerCompressionDisabled { + f.headerCompressor.Flush() + } + + // Set ControlFrameHeader. + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypeSynStream + frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 10) + + // Serialize frame to Writer. + if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { + return err + } + if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil { + return err + } + if err = binary.Write(f.w, binary.BigEndian, frame.AssociatedToStreamId); err != nil { + return err + } + if err = binary.Write(f.w, binary.BigEndian, frame.Priority<<5); err != nil { + return err + } + if err = binary.Write(f.w, binary.BigEndian, frame.Slot); err != nil { + return err + } + if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil { + return err + } + f.headerBuf.Reset() + return nil +} + +func (f *Framer) writeSynReplyFrame(frame *SynReplyFrame) (err error) { + if frame.StreamId == 0 { + return &Error{ZeroStreamId, 0} + } + // Marshal the headers. + var writer io.Writer = f.headerBuf + if !f.headerCompressionDisabled { + writer = f.headerCompressor + } + if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil { + return + } + if !f.headerCompressionDisabled { + f.headerCompressor.Flush() + } + + // Set ControlFrameHeader. + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypeSynReply + frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4) + + // Serialize frame to Writer. + if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil { + return + } + if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil { + return + } + f.headerBuf.Reset() + return +} + +func (f *Framer) writeHeadersFrame(frame *HeadersFrame) (err error) { + if frame.StreamId == 0 { + return &Error{ZeroStreamId, 0} + } + // Marshal the headers. + var writer io.Writer = f.headerBuf + if !f.headerCompressionDisabled { + writer = f.headerCompressor + } + if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil { + return + } + if !f.headerCompressionDisabled { + f.headerCompressor.Flush() + } + + // Set ControlFrameHeader. + frame.CFHeader.version = Version + frame.CFHeader.frameType = TypeHeaders + frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4) + + // Serialize frame to Writer. + if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { + return + } + if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil { + return + } + if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil { + return + } + f.headerBuf.Reset() + return +} + +func (f *Framer) writeDataFrame(frame *DataFrame) (err error) { + if frame.StreamId == 0 { + return &Error{ZeroStreamId, 0} + } + if frame.StreamId&0x80000000 != 0 || len(frame.Data) > MaxDataLength { + return &Error{InvalidDataFrame, frame.StreamId} + } + + // Serialize frame to Writer. + if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil { + return + } + flagsAndLength := uint32(frame.Flags)<<24 | uint32(len(frame.Data)) + if err = binary.Write(f.w, binary.BigEndian, flagsAndLength); err != nil { + return + } + if _, err = f.w.Write(frame.Data); err != nil { + return + } + return nil +} diff --git a/vendor/github.com/moby/spdystream/stream.go b/vendor/github.com/moby/spdystream/stream.go new file mode 100644 index 0000000000..404e3c02df --- /dev/null +++ b/vendor/github.com/moby/spdystream/stream.go @@ -0,0 +1,343 @@ +/* + Copyright 2014-2021 Docker Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package spdystream + +import ( + "errors" + "fmt" + "io" + "net" + "net/http" + "sync" + "time" + + "github.com/moby/spdystream/spdy" +) + +var ( + ErrUnreadPartialData = errors.New("unread partial data") +) + +type Stream struct { + streamId spdy.StreamId + parent *Stream + conn *Connection + startChan chan error + + dataLock sync.RWMutex + dataChan chan []byte + unread []byte + + priority uint8 + headers http.Header + headerChan chan http.Header + finishLock sync.Mutex + finished bool + replyCond *sync.Cond + replied bool + closeLock sync.Mutex + closeChan chan bool +} + +// WriteData writes data to stream, sending a dataframe per call +func (s *Stream) WriteData(data []byte, fin bool) error { + s.waitWriteReply() + var flags spdy.DataFlags + + if fin { + flags = spdy.DataFlagFin + s.finishLock.Lock() + if s.finished { + s.finishLock.Unlock() + return ErrWriteClosedStream + } + s.finished = true + s.finishLock.Unlock() + } + + dataFrame := &spdy.DataFrame{ + StreamId: s.streamId, + Flags: flags, + Data: data, + } + + debugMessage("(%p) (%d) Writing data frame", s, s.streamId) + return s.conn.framer.WriteFrame(dataFrame) +} + +// Write writes bytes to a stream, calling write data for each call. +func (s *Stream) Write(data []byte) (n int, err error) { + err = s.WriteData(data, false) + if err == nil { + n = len(data) + } + return +} + +// Read reads bytes from a stream, a single read will never get more +// than what is sent on a single data frame, but a multiple calls to +// read may get data from the same data frame. +func (s *Stream) Read(p []byte) (n int, err error) { + if s.unread == nil { + select { + case <-s.closeChan: + return 0, io.EOF + case read, ok := <-s.dataChan: + if !ok { + return 0, io.EOF + } + s.unread = read + } + } + n = copy(p, s.unread) + if n < len(s.unread) { + s.unread = s.unread[n:] + } else { + s.unread = nil + } + return +} + +// ReadData reads an entire data frame and returns the byte array +// from the data frame. If there is unread data from the result +// of a Read call, this function will return an ErrUnreadPartialData. +func (s *Stream) ReadData() ([]byte, error) { + debugMessage("(%p) Reading data from %d", s, s.streamId) + if s.unread != nil { + return nil, ErrUnreadPartialData + } + select { + case <-s.closeChan: + return nil, io.EOF + case read, ok := <-s.dataChan: + if !ok { + return nil, io.EOF + } + return read, nil + } +} + +func (s *Stream) waitWriteReply() { + if s.replyCond != nil { + s.replyCond.L.Lock() + for !s.replied { + s.replyCond.Wait() + } + s.replyCond.L.Unlock() + } +} + +// Wait waits for the stream to receive a reply. +func (s *Stream) Wait() error { + return s.WaitTimeout(time.Duration(0)) +} + +// WaitTimeout waits for the stream to receive a reply or for timeout. +// When the timeout is reached, ErrTimeout will be returned. +func (s *Stream) WaitTimeout(timeout time.Duration) error { + var timeoutChan <-chan time.Time + if timeout > time.Duration(0) { + timeoutChan = time.After(timeout) + } + + select { + case err := <-s.startChan: + if err != nil { + return err + } + break + case <-timeoutChan: + return ErrTimeout + } + return nil +} + +// Close closes the stream by sending an empty data frame with the +// finish flag set, indicating this side is finished with the stream. +func (s *Stream) Close() error { + select { + case <-s.closeChan: + // Stream is now fully closed + s.conn.removeStream(s) + default: + break + } + return s.WriteData([]byte{}, true) +} + +// Reset sends a reset frame, putting the stream into the fully closed state. +func (s *Stream) Reset() error { + s.conn.removeStream(s) + return s.resetStream() +} + +func (s *Stream) resetStream() error { + // Always call closeRemoteChannels, even if s.finished is already true. + // This makes it so that stream.Close() followed by stream.Reset() allows + // stream.Read() to unblock. + s.closeRemoteChannels() + + s.finishLock.Lock() + if s.finished { + s.finishLock.Unlock() + return nil + } + s.finished = true + s.finishLock.Unlock() + + resetFrame := &spdy.RstStreamFrame{ + StreamId: s.streamId, + Status: spdy.Cancel, + } + return s.conn.framer.WriteFrame(resetFrame) +} + +// CreateSubStream creates a stream using the current as the parent +func (s *Stream) CreateSubStream(headers http.Header, fin bool) (*Stream, error) { + return s.conn.CreateStream(headers, s, fin) +} + +// SetPriority sets the stream priority, does not affect the +// remote priority of this stream after Open has been called. +// Valid values are 0 through 7, 0 being the highest priority +// and 7 the lowest. +func (s *Stream) SetPriority(priority uint8) { + s.priority = priority +} + +// SendHeader sends a header frame across the stream +func (s *Stream) SendHeader(headers http.Header, fin bool) error { + return s.conn.sendHeaders(headers, s, fin) +} + +// SendReply sends a reply on a stream, only valid to be called once +// when handling a new stream +func (s *Stream) SendReply(headers http.Header, fin bool) error { + if s.replyCond == nil { + return errors.New("cannot reply on initiated stream") + } + s.replyCond.L.Lock() + defer s.replyCond.L.Unlock() + if s.replied { + return nil + } + + err := s.conn.sendReply(headers, s, fin) + if err != nil { + return err + } + + s.replied = true + s.replyCond.Broadcast() + return nil +} + +// Refuse sends a reset frame with the status refuse, only +// valid to be called once when handling a new stream. This +// may be used to indicate that a stream is not allowed +// when http status codes are not being used. +func (s *Stream) Refuse() error { + if s.replied { + return nil + } + s.replied = true + return s.conn.sendReset(spdy.RefusedStream, s) +} + +// Cancel sends a reset frame with the status canceled. This +// can be used at any time by the creator of the Stream to +// indicate the stream is no longer needed. +func (s *Stream) Cancel() error { + return s.conn.sendReset(spdy.Cancel, s) +} + +// ReceiveHeader receives a header sent on the other side +// of the stream. This function will block until a header +// is received or stream is closed. +func (s *Stream) ReceiveHeader() (http.Header, error) { + select { + case <-s.closeChan: + break + case header, ok := <-s.headerChan: + if !ok { + return nil, fmt.Errorf("header chan closed") + } + return header, nil + } + return nil, fmt.Errorf("stream closed") +} + +// Parent returns the parent stream +func (s *Stream) Parent() *Stream { + return s.parent +} + +// Headers returns the headers used to create the stream +func (s *Stream) Headers() http.Header { + return s.headers +} + +// String returns the string version of stream using the +// streamId to uniquely identify the stream +func (s *Stream) String() string { + return fmt.Sprintf("stream:%d", s.streamId) +} + +// Identifier returns a 32 bit identifier for the stream +func (s *Stream) Identifier() uint32 { + return uint32(s.streamId) +} + +// IsFinished returns whether the stream has finished +// sending data +func (s *Stream) IsFinished() bool { + return s.finished +} + +// Implement net.Conn interface + +func (s *Stream) LocalAddr() net.Addr { + return s.conn.conn.LocalAddr() +} + +func (s *Stream) RemoteAddr() net.Addr { + return s.conn.conn.RemoteAddr() +} + +// TODO set per stream values instead of connection-wide + +func (s *Stream) SetDeadline(t time.Time) error { + return s.conn.conn.SetDeadline(t) +} + +func (s *Stream) SetReadDeadline(t time.Time) error { + return s.conn.conn.SetReadDeadline(t) +} + +func (s *Stream) SetWriteDeadline(t time.Time) error { + return s.conn.conn.SetWriteDeadline(t) +} + +func (s *Stream) closeRemoteChannels() { + s.closeLock.Lock() + defer s.closeLock.Unlock() + select { + case <-s.closeChan: + default: + close(s.closeChan) + } +} diff --git a/vendor/github.com/moby/spdystream/utils.go b/vendor/github.com/moby/spdystream/utils.go new file mode 100644 index 0000000000..e9f7fffd60 --- /dev/null +++ b/vendor/github.com/moby/spdystream/utils.go @@ -0,0 +1,32 @@ +/* + Copyright 2014-2021 Docker Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package spdystream + +import ( + "log" + "os" +) + +var ( + DEBUG = os.Getenv("DEBUG") +) + +func debugMessage(fmt string, args ...interface{}) { + if DEBUG != "" { + log.Printf(fmt, args...) + } +} diff --git a/vendor/github.com/moby/term/.gitignore b/vendor/github.com/moby/term/.gitignore new file mode 100644 index 0000000000..b0747ff010 --- /dev/null +++ b/vendor/github.com/moby/term/.gitignore @@ -0,0 +1,8 @@ +# if you want to ignore files created by your editor/tools, consider using a +# global .gitignore or .git/info/exclude see https://help.github.com/articles/ignoring-files +.* +!.github +!.gitignore +profile.out +# support running go modules in vendor mode for local development +vendor/ diff --git a/vendor/github.com/moby/term/LICENSE b/vendor/github.com/moby/term/LICENSE new file mode 100644 index 0000000000..6d8d58fb67 --- /dev/null +++ b/vendor/github.com/moby/term/LICENSE @@ -0,0 +1,191 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2013-2018 Docker, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/moby/term/README.md b/vendor/github.com/moby/term/README.md new file mode 100644 index 0000000000..0ce92cc339 --- /dev/null +++ b/vendor/github.com/moby/term/README.md @@ -0,0 +1,36 @@ +# term - utilities for dealing with terminals + +![Test](https://github.com/moby/term/workflows/Test/badge.svg) [![GoDoc](https://godoc.org/github.com/moby/term?status.svg)](https://godoc.org/github.com/moby/term) [![Go Report Card](https://goreportcard.com/badge/github.com/moby/term)](https://goreportcard.com/report/github.com/moby/term) + +term provides structures and helper functions to work with terminal (state, sizes). + +#### Using term + +```go +package main + +import ( + "log" + "os" + + "github.com/moby/term" +) + +func main() { + fd := os.Stdin.Fd() + if term.IsTerminal(fd) { + ws, err := term.GetWinsize(fd) + if err != nil { + log.Fatalf("term.GetWinsize: %s", err) + } + log.Printf("%d:%d\n", ws.Height, ws.Width) + } +} +``` + +## Contributing + +Want to hack on term? [Docker's contributions guidelines](https://github.com/docker/docker/blob/master/CONTRIBUTING.md) apply. + +## Copyright and license +Code and documentation copyright 2015 Docker, inc. Code released under the Apache 2.0 license. Docs released under Creative commons. diff --git a/vendor/github.com/moby/term/ascii.go b/vendor/github.com/moby/term/ascii.go new file mode 100644 index 0000000000..55873c0556 --- /dev/null +++ b/vendor/github.com/moby/term/ascii.go @@ -0,0 +1,66 @@ +package term + +import ( + "fmt" + "strings" +) + +// ASCII list the possible supported ASCII key sequence +var ASCII = []string{ + "ctrl-@", + "ctrl-a", + "ctrl-b", + "ctrl-c", + "ctrl-d", + "ctrl-e", + "ctrl-f", + "ctrl-g", + "ctrl-h", + "ctrl-i", + "ctrl-j", + "ctrl-k", + "ctrl-l", + "ctrl-m", + "ctrl-n", + "ctrl-o", + "ctrl-p", + "ctrl-q", + "ctrl-r", + "ctrl-s", + "ctrl-t", + "ctrl-u", + "ctrl-v", + "ctrl-w", + "ctrl-x", + "ctrl-y", + "ctrl-z", + "ctrl-[", + "ctrl-\\", + "ctrl-]", + "ctrl-^", + "ctrl-_", +} + +// ToBytes converts a string representing a suite of key-sequence to the corresponding ASCII code. +func ToBytes(keys string) ([]byte, error) { + codes := []byte{} +next: + for _, key := range strings.Split(keys, ",") { + if len(key) != 1 { + for code, ctrl := range ASCII { + if ctrl == key { + codes = append(codes, byte(code)) + continue next + } + } + if key == "DEL" { + codes = append(codes, 127) + } else { + return nil, fmt.Errorf("Unknown character: '%s'", key) + } + } else { + codes = append(codes, key[0]) + } + } + return codes, nil +} diff --git a/vendor/github.com/moby/term/doc.go b/vendor/github.com/moby/term/doc.go new file mode 100644 index 0000000000..c9bc032443 --- /dev/null +++ b/vendor/github.com/moby/term/doc.go @@ -0,0 +1,3 @@ +// Package term provides structures and helper functions to work with +// terminal (state, sizes). +package term diff --git a/vendor/github.com/moby/term/proxy.go b/vendor/github.com/moby/term/proxy.go new file mode 100644 index 0000000000..c47756b89a --- /dev/null +++ b/vendor/github.com/moby/term/proxy.go @@ -0,0 +1,88 @@ +package term + +import ( + "io" +) + +// EscapeError is special error which returned by a TTY proxy reader's Read() +// method in case its detach escape sequence is read. +type EscapeError struct{} + +func (EscapeError) Error() string { + return "read escape sequence" +} + +// escapeProxy is used only for attaches with a TTY. It is used to proxy +// stdin keypresses from the underlying reader and look for the passed in +// escape key sequence to signal a detach. +type escapeProxy struct { + escapeKeys []byte + escapeKeyPos int + r io.Reader + buf []byte +} + +// NewEscapeProxy returns a new TTY proxy reader which wraps the given reader +// and detects when the specified escape keys are read, in which case the Read +// method will return an error of type EscapeError. +func NewEscapeProxy(r io.Reader, escapeKeys []byte) io.Reader { + return &escapeProxy{ + escapeKeys: escapeKeys, + r: r, + } +} + +func (r *escapeProxy) Read(buf []byte) (n int, err error) { + if len(r.escapeKeys) > 0 && r.escapeKeyPos == len(r.escapeKeys) { + return 0, EscapeError{} + } + + if len(r.buf) > 0 { + n = copy(buf, r.buf) + r.buf = r.buf[n:] + } + + nr, err := r.r.Read(buf[n:]) + n += nr + if len(r.escapeKeys) == 0 { + return n, err + } + + for i := 0; i < n; i++ { + if buf[i] == r.escapeKeys[r.escapeKeyPos] { + r.escapeKeyPos++ + + // Check if the full escape sequence is matched. + if r.escapeKeyPos == len(r.escapeKeys) { + n = i + 1 - r.escapeKeyPos + if n < 0 { + n = 0 + } + return n, EscapeError{} + } + continue + } + + // If we need to prepend a partial escape sequence from the previous + // read, make sure the new buffer size doesn't exceed len(buf). + // Otherwise, preserve any extra data in a buffer for the next read. + if i < r.escapeKeyPos { + preserve := make([]byte, 0, r.escapeKeyPos+n) + preserve = append(preserve, r.escapeKeys[:r.escapeKeyPos]...) + preserve = append(preserve, buf[:n]...) + n = copy(buf, preserve) + i += r.escapeKeyPos + r.buf = append(r.buf, preserve[n:]...) + } + r.escapeKeyPos = 0 + } + + // If we're in the middle of reading an escape sequence, make sure we don't + // let the caller read it. If later on we find that this is not the escape + // sequence, we'll prepend it back to buf. + n -= r.escapeKeyPos + if n < 0 { + n = 0 + } + return n, err +} diff --git a/vendor/github.com/moby/term/term.go b/vendor/github.com/moby/term/term.go new file mode 100644 index 0000000000..f9d8988ef8 --- /dev/null +++ b/vendor/github.com/moby/term/term.go @@ -0,0 +1,85 @@ +package term + +import "io" + +// State holds the platform-specific state / console mode for the terminal. +type State terminalState + +// Winsize represents the size of the terminal window. +type Winsize struct { + Height uint16 + Width uint16 + + // Only used on Unix + x uint16 + y uint16 +} + +// StdStreams returns the standard streams (stdin, stdout, stderr). +// +// On Windows, it attempts to turn on VT handling on all std handles if +// supported, or falls back to terminal emulation. On Unix, this returns +// the standard [os.Stdin], [os.Stdout] and [os.Stderr]. +func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { + return stdStreams() +} + +// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal. +func GetFdInfo(in interface{}) (fd uintptr, isTerminal bool) { + return getFdInfo(in) +} + +// GetWinsize returns the window size based on the specified file descriptor. +func GetWinsize(fd uintptr) (*Winsize, error) { + return getWinsize(fd) +} + +// SetWinsize tries to set the specified window size for the specified file +// descriptor. It is only implemented on Unix, and returns an error on Windows. +func SetWinsize(fd uintptr, ws *Winsize) error { + return setWinsize(fd, ws) +} + +// IsTerminal returns true if the given file descriptor is a terminal. +func IsTerminal(fd uintptr) bool { + return isTerminal(fd) +} + +// RestoreTerminal restores the terminal connected to the given file descriptor +// to a previous state. +func RestoreTerminal(fd uintptr, state *State) error { + return restoreTerminal(fd, state) +} + +// SaveState saves the state of the terminal connected to the given file descriptor. +func SaveState(fd uintptr) (*State, error) { + return saveState(fd) +} + +// DisableEcho applies the specified state to the terminal connected to the file +// descriptor, with echo disabled. +func DisableEcho(fd uintptr, state *State) error { + return disableEcho(fd, state) +} + +// SetRawTerminal puts the terminal connected to the given file descriptor into +// raw mode and returns the previous state. On UNIX, this is the equivalent of +// [MakeRaw], and puts both the input and output into raw mode. On Windows, it +// only puts the input into raw mode. +func SetRawTerminal(fd uintptr) (previousState *State, err error) { + return setRawTerminal(fd) +} + +// SetRawTerminalOutput puts the output of terminal connected to the given file +// descriptor into raw mode. On UNIX, this does nothing and returns nil for the +// state. On Windows, it disables LF -> CRLF translation. +func SetRawTerminalOutput(fd uintptr) (previousState *State, err error) { + return setRawTerminalOutput(fd) +} + +// MakeRaw puts the terminal (Windows Console) connected to the +// given file descriptor into raw mode and returns the previous state of +// the terminal so that it can be restored. +func MakeRaw(fd uintptr) (previousState *State, err error) { + return makeRaw(fd) +} diff --git a/vendor/github.com/moby/term/term_unix.go b/vendor/github.com/moby/term/term_unix.go new file mode 100644 index 0000000000..2ec7706a16 --- /dev/null +++ b/vendor/github.com/moby/term/term_unix.go @@ -0,0 +1,98 @@ +//go:build !windows +// +build !windows + +package term + +import ( + "errors" + "io" + "os" + + "golang.org/x/sys/unix" +) + +// ErrInvalidState is returned if the state of the terminal is invalid. +// +// Deprecated: ErrInvalidState is no longer used. +var ErrInvalidState = errors.New("Invalid terminal state") + +// terminalState holds the platform-specific state / console mode for the terminal. +type terminalState struct { + termios unix.Termios +} + +func stdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { + return os.Stdin, os.Stdout, os.Stderr +} + +func getFdInfo(in interface{}) (uintptr, bool) { + var inFd uintptr + var isTerminalIn bool + if file, ok := in.(*os.File); ok { + inFd = file.Fd() + isTerminalIn = isTerminal(inFd) + } + return inFd, isTerminalIn +} + +func getWinsize(fd uintptr) (*Winsize, error) { + uws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ) + ws := &Winsize{Height: uws.Row, Width: uws.Col, x: uws.Xpixel, y: uws.Ypixel} + return ws, err +} + +func setWinsize(fd uintptr, ws *Winsize) error { + return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, &unix.Winsize{ + Row: ws.Height, + Col: ws.Width, + Xpixel: ws.x, + Ypixel: ws.y, + }) +} + +func isTerminal(fd uintptr) bool { + _, err := tcget(fd) + return err == nil +} + +func restoreTerminal(fd uintptr, state *State) error { + if state == nil { + return errors.New("invalid terminal state") + } + return tcset(fd, &state.termios) +} + +func saveState(fd uintptr) (*State, error) { + termios, err := tcget(fd) + if err != nil { + return nil, err + } + return &State{termios: *termios}, nil +} + +func disableEcho(fd uintptr, state *State) error { + newState := state.termios + newState.Lflag &^= unix.ECHO + + return tcset(fd, &newState) +} + +func setRawTerminal(fd uintptr) (*State, error) { + return makeRaw(fd) +} + +func setRawTerminalOutput(fd uintptr) (*State, error) { + return nil, nil +} + +func tcget(fd uintptr) (*unix.Termios, error) { + p, err := unix.IoctlGetTermios(int(fd), getTermios) + if err != nil { + return nil, err + } + return p, nil +} + +func tcset(fd uintptr, p *unix.Termios) error { + return unix.IoctlSetTermios(int(fd), setTermios, p) +} diff --git a/vendor/github.com/moby/term/term_windows.go b/vendor/github.com/moby/term/term_windows.go new file mode 100644 index 0000000000..81ccff0428 --- /dev/null +++ b/vendor/github.com/moby/term/term_windows.go @@ -0,0 +1,176 @@ +package term + +import ( + "fmt" + "io" + "os" + "os/signal" + + windowsconsole "github.com/moby/term/windows" + "golang.org/x/sys/windows" +) + +// terminalState holds the platform-specific state / console mode for the terminal. +type terminalState struct { + mode uint32 +} + +// vtInputSupported is true if winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported by the console +var vtInputSupported bool + +func stdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { + // Turn on VT handling on all std handles, if possible. This might + // fail, in which case we will fall back to terminal emulation. + var ( + emulateStdin, emulateStdout, emulateStderr bool + + mode uint32 + ) + + fd := windows.Handle(os.Stdin.Fd()) + if err := windows.GetConsoleMode(fd, &mode); err == nil { + // Validate that winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported, but do not set it. + if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil { + emulateStdin = true + } else { + vtInputSupported = true + } + // Unconditionally set the console mode back even on failure because SetConsoleMode + // remembers invalid bits on input handles. + _ = windows.SetConsoleMode(fd, mode) + } + + fd = windows.Handle(os.Stdout.Fd()) + if err := windows.GetConsoleMode(fd, &mode); err == nil { + // Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it. + if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil { + emulateStdout = true + } else { + _ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING) + } + } + + fd = windows.Handle(os.Stderr.Fd()) + if err := windows.GetConsoleMode(fd, &mode); err == nil { + // Validate winterm.DISABLE_NEWLINE_AUTO_RETURN is supported, but do not set it. + if err = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING|windows.DISABLE_NEWLINE_AUTO_RETURN); err != nil { + emulateStderr = true + } else { + _ = windows.SetConsoleMode(fd, mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING) + } + } + + if emulateStdin { + h := uint32(windows.STD_INPUT_HANDLE) + stdIn = windowsconsole.NewAnsiReader(int(h)) + } else { + stdIn = os.Stdin + } + + if emulateStdout { + h := uint32(windows.STD_OUTPUT_HANDLE) + stdOut = windowsconsole.NewAnsiWriter(int(h)) + } else { + stdOut = os.Stdout + } + + if emulateStderr { + h := uint32(windows.STD_ERROR_HANDLE) + stdErr = windowsconsole.NewAnsiWriter(int(h)) + } else { + stdErr = os.Stderr + } + + return stdIn, stdOut, stdErr +} + +func getFdInfo(in interface{}) (uintptr, bool) { + return windowsconsole.GetHandleInfo(in) +} + +func getWinsize(fd uintptr) (*Winsize, error) { + var info windows.ConsoleScreenBufferInfo + if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { + return nil, err + } + + winsize := &Winsize{ + Width: uint16(info.Window.Right - info.Window.Left + 1), + Height: uint16(info.Window.Bottom - info.Window.Top + 1), + } + + return winsize, nil +} + +func setWinsize(fd uintptr, ws *Winsize) error { + return fmt.Errorf("not implemented on Windows") +} + +func isTerminal(fd uintptr) bool { + var mode uint32 + err := windows.GetConsoleMode(windows.Handle(fd), &mode) + return err == nil +} + +func restoreTerminal(fd uintptr, state *State) error { + return windows.SetConsoleMode(windows.Handle(fd), state.mode) +} + +func saveState(fd uintptr) (*State, error) { + var mode uint32 + + if err := windows.GetConsoleMode(windows.Handle(fd), &mode); err != nil { + return nil, err + } + + return &State{mode: mode}, nil +} + +func disableEcho(fd uintptr, state *State) error { + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx + mode := state.mode + mode &^= windows.ENABLE_ECHO_INPUT + mode |= windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT + err := windows.SetConsoleMode(windows.Handle(fd), mode) + if err != nil { + return err + } + + // Register an interrupt handler to catch and restore prior state + restoreAtInterrupt(fd, state) + return nil +} + +func setRawTerminal(fd uintptr) (*State, error) { + oldState, err := MakeRaw(fd) + if err != nil { + return nil, err + } + + // Register an interrupt handler to catch and restore prior state + restoreAtInterrupt(fd, oldState) + return oldState, err +} + +func setRawTerminalOutput(fd uintptr) (*State, error) { + oldState, err := saveState(fd) + if err != nil { + return nil, err + } + + // Ignore failures, since winterm.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this + // version of Windows. + _ = windows.SetConsoleMode(windows.Handle(fd), oldState.mode|windows.DISABLE_NEWLINE_AUTO_RETURN) + return oldState, err +} + +func restoreAtInterrupt(fd uintptr, state *State) { + sigchan := make(chan os.Signal, 1) + signal.Notify(sigchan, os.Interrupt) + + go func() { + _ = <-sigchan + _ = RestoreTerminal(fd, state) + os.Exit(0) + }() +} diff --git a/vendor/github.com/moby/term/termios_bsd.go b/vendor/github.com/moby/term/termios_bsd.go new file mode 100644 index 0000000000..45f77e03c7 --- /dev/null +++ b/vendor/github.com/moby/term/termios_bsd.go @@ -0,0 +1,13 @@ +//go:build darwin || freebsd || openbsd || netbsd +// +build darwin freebsd openbsd netbsd + +package term + +import ( + "golang.org/x/sys/unix" +) + +const ( + getTermios = unix.TIOCGETA + setTermios = unix.TIOCSETA +) diff --git a/vendor/github.com/moby/term/termios_nonbsd.go b/vendor/github.com/moby/term/termios_nonbsd.go new file mode 100644 index 0000000000..88b7b21563 --- /dev/null +++ b/vendor/github.com/moby/term/termios_nonbsd.go @@ -0,0 +1,13 @@ +//go:build !darwin && !freebsd && !netbsd && !openbsd && !windows +// +build !darwin,!freebsd,!netbsd,!openbsd,!windows + +package term + +import ( + "golang.org/x/sys/unix" +) + +const ( + getTermios = unix.TCGETS + setTermios = unix.TCSETS +) diff --git a/vendor/github.com/moby/term/termios_unix.go b/vendor/github.com/moby/term/termios_unix.go new file mode 100644 index 0000000000..60c823783c --- /dev/null +++ b/vendor/github.com/moby/term/termios_unix.go @@ -0,0 +1,35 @@ +//go:build !windows +// +build !windows + +package term + +import ( + "golang.org/x/sys/unix" +) + +// Termios is the Unix API for terminal I/O. +// +// Deprecated: use [unix.Termios]. +type Termios = unix.Termios + +func makeRaw(fd uintptr) (*State, error) { + termios, err := tcget(fd) + if err != nil { + return nil, err + } + + oldState := State{termios: *termios} + + termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON + termios.Oflag &^= unix.OPOST + termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN + termios.Cflag &^= unix.CSIZE | unix.PARENB + termios.Cflag |= unix.CS8 + termios.Cc[unix.VMIN] = 1 + termios.Cc[unix.VTIME] = 0 + + if err := tcset(fd, termios); err != nil { + return nil, err + } + return &oldState, nil +} diff --git a/vendor/github.com/moby/term/termios_windows.go b/vendor/github.com/moby/term/termios_windows.go new file mode 100644 index 0000000000..5be4e76011 --- /dev/null +++ b/vendor/github.com/moby/term/termios_windows.go @@ -0,0 +1,37 @@ +package term + +import "golang.org/x/sys/windows" + +func makeRaw(fd uintptr) (*State, error) { + state, err := SaveState(fd) + if err != nil { + return nil, err + } + + mode := state.mode + + // See + // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx + // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx + + // Disable these modes + mode &^= windows.ENABLE_ECHO_INPUT + mode &^= windows.ENABLE_LINE_INPUT + mode &^= windows.ENABLE_MOUSE_INPUT + mode &^= windows.ENABLE_WINDOW_INPUT + mode &^= windows.ENABLE_PROCESSED_INPUT + + // Enable these modes + mode |= windows.ENABLE_EXTENDED_FLAGS + mode |= windows.ENABLE_INSERT_MODE + mode |= windows.ENABLE_QUICK_EDIT_MODE + if vtInputSupported { + mode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT + } + + err = windows.SetConsoleMode(windows.Handle(fd), mode) + if err != nil { + return nil, err + } + return state, nil +} diff --git a/vendor/github.com/moby/term/windows/ansi_reader.go b/vendor/github.com/moby/term/windows/ansi_reader.go new file mode 100644 index 0000000000..fb34c547aa --- /dev/null +++ b/vendor/github.com/moby/term/windows/ansi_reader.go @@ -0,0 +1,252 @@ +//go:build windows +// +build windows + +package windowsconsole + +import ( + "bytes" + "errors" + "fmt" + "io" + "os" + "strings" + "unsafe" + + ansiterm "github.com/Azure/go-ansiterm" + "github.com/Azure/go-ansiterm/winterm" +) + +const ( + escapeSequence = ansiterm.KEY_ESC_CSI +) + +// ansiReader wraps a standard input file (e.g., os.Stdin) providing ANSI sequence translation. +type ansiReader struct { + file *os.File + fd uintptr + buffer []byte + cbBuffer int + command []byte +} + +// NewAnsiReader returns an io.ReadCloser that provides VT100 terminal emulation on top of a +// Windows console input handle. +func NewAnsiReader(nFile int) io.ReadCloser { + file, fd := winterm.GetStdFile(nFile) + return &ansiReader{ + file: file, + fd: fd, + command: make([]byte, 0, ansiterm.ANSI_MAX_CMD_LENGTH), + buffer: make([]byte, 0), + } +} + +// Close closes the wrapped file. +func (ar *ansiReader) Close() (err error) { + return ar.file.Close() +} + +// Fd returns the file descriptor of the wrapped file. +func (ar *ansiReader) Fd() uintptr { + return ar.fd +} + +// Read reads up to len(p) bytes of translated input events into p. +func (ar *ansiReader) Read(p []byte) (int, error) { + if len(p) == 0 { + return 0, nil + } + + // Previously read bytes exist, read as much as we can and return + if len(ar.buffer) > 0 { + originalLength := len(ar.buffer) + copiedLength := copy(p, ar.buffer) + + if copiedLength == originalLength { + ar.buffer = make([]byte, 0, len(p)) + } else { + ar.buffer = ar.buffer[copiedLength:] + } + + return copiedLength, nil + } + + // Read and translate key events + events, err := readInputEvents(ar, len(p)) + if err != nil { + return 0, err + } else if len(events) == 0 { + return 0, nil + } + + keyBytes := translateKeyEvents(events, []byte(escapeSequence)) + + // Save excess bytes and right-size keyBytes + if len(keyBytes) > len(p) { + ar.buffer = keyBytes[len(p):] + keyBytes = keyBytes[:len(p)] + } else if len(keyBytes) == 0 { + return 0, nil + } + + copiedLength := copy(p, keyBytes) + if copiedLength != len(keyBytes) { + return 0, errors.New("unexpected copy length encountered") + } + + return copiedLength, nil +} + +// readInputEvents polls until at least one event is available. +func readInputEvents(ar *ansiReader, maxBytes int) ([]winterm.INPUT_RECORD, error) { + // Determine the maximum number of records to retrieve + // -- Cast around the type system to obtain the size of a single INPUT_RECORD. + // unsafe.Sizeof requires an expression vs. a type-reference; the casting + // tricks the type system into believing it has such an expression. + recordSize := int(unsafe.Sizeof(*((*winterm.INPUT_RECORD)(unsafe.Pointer(&maxBytes))))) + countRecords := maxBytes / recordSize + if countRecords > ansiterm.MAX_INPUT_EVENTS { + countRecords = ansiterm.MAX_INPUT_EVENTS + } else if countRecords == 0 { + countRecords = 1 + } + + // Wait for and read input events + events := make([]winterm.INPUT_RECORD, countRecords) + nEvents := uint32(0) + eventsExist, err := winterm.WaitForSingleObject(ar.fd, winterm.WAIT_INFINITE) + if err != nil { + return nil, err + } + + if eventsExist { + err = winterm.ReadConsoleInput(ar.fd, events, &nEvents) + if err != nil { + return nil, err + } + } + + // Return a slice restricted to the number of returned records + return events[:nEvents], nil +} + +// KeyEvent Translation Helpers + +var arrowKeyMapPrefix = map[uint16]string{ + winterm.VK_UP: "%s%sA", + winterm.VK_DOWN: "%s%sB", + winterm.VK_RIGHT: "%s%sC", + winterm.VK_LEFT: "%s%sD", +} + +var keyMapPrefix = map[uint16]string{ + winterm.VK_UP: "\x1B[%sA", + winterm.VK_DOWN: "\x1B[%sB", + winterm.VK_RIGHT: "\x1B[%sC", + winterm.VK_LEFT: "\x1B[%sD", + winterm.VK_HOME: "\x1B[1%s~", // showkey shows ^[[1 + winterm.VK_END: "\x1B[4%s~", // showkey shows ^[[4 + winterm.VK_INSERT: "\x1B[2%s~", + winterm.VK_DELETE: "\x1B[3%s~", + winterm.VK_PRIOR: "\x1B[5%s~", + winterm.VK_NEXT: "\x1B[6%s~", + winterm.VK_F1: "", + winterm.VK_F2: "", + winterm.VK_F3: "\x1B[13%s~", + winterm.VK_F4: "\x1B[14%s~", + winterm.VK_F5: "\x1B[15%s~", + winterm.VK_F6: "\x1B[17%s~", + winterm.VK_F7: "\x1B[18%s~", + winterm.VK_F8: "\x1B[19%s~", + winterm.VK_F9: "\x1B[20%s~", + winterm.VK_F10: "\x1B[21%s~", + winterm.VK_F11: "\x1B[23%s~", + winterm.VK_F12: "\x1B[24%s~", +} + +// translateKeyEvents converts the input events into the appropriate ANSI string. +func translateKeyEvents(events []winterm.INPUT_RECORD, escapeSequence []byte) []byte { + var buffer bytes.Buffer + for _, event := range events { + if event.EventType == winterm.KEY_EVENT && event.KeyEvent.KeyDown != 0 { + buffer.WriteString(keyToString(&event.KeyEvent, escapeSequence)) + } + } + + return buffer.Bytes() +} + +// keyToString maps the given input event record to the corresponding string. +func keyToString(keyEvent *winterm.KEY_EVENT_RECORD, escapeSequence []byte) string { + if keyEvent.UnicodeChar == 0 { + return formatVirtualKey(keyEvent.VirtualKeyCode, keyEvent.ControlKeyState, escapeSequence) + } + + _, alt, control := getControlKeys(keyEvent.ControlKeyState) + if control { + // TODO(azlinux): Implement following control sequences + // -D Signals the end of input from the keyboard; also exits current shell. + // -H Deletes the first character to the left of the cursor. Also called the ERASE key. + // -Q Restarts printing after it has been stopped with -s. + // -S Suspends printing on the screen (does not stop the program). + // -U Deletes all characters on the current line. Also called the KILL key. + // -E Quits current command and creates a core + } + + // +Key generates ESC N Key + if !control && alt { + return ansiterm.KEY_ESC_N + strings.ToLower(string(rune(keyEvent.UnicodeChar))) + } + + return string(rune(keyEvent.UnicodeChar)) +} + +// formatVirtualKey converts a virtual key (e.g., up arrow) into the appropriate ANSI string. +func formatVirtualKey(key uint16, controlState uint32, escapeSequence []byte) string { + shift, alt, control := getControlKeys(controlState) + modifier := getControlKeysModifier(shift, alt, control) + + if format, ok := arrowKeyMapPrefix[key]; ok { + return fmt.Sprintf(format, escapeSequence, modifier) + } + + if format, ok := keyMapPrefix[key]; ok { + return fmt.Sprintf(format, modifier) + } + + return "" +} + +// getControlKeys extracts the shift, alt, and ctrl key states. +func getControlKeys(controlState uint32) (shift, alt, control bool) { + shift = 0 != (controlState & winterm.SHIFT_PRESSED) + alt = 0 != (controlState & (winterm.LEFT_ALT_PRESSED | winterm.RIGHT_ALT_PRESSED)) + control = 0 != (controlState & (winterm.LEFT_CTRL_PRESSED | winterm.RIGHT_CTRL_PRESSED)) + return shift, alt, control +} + +// getControlKeysModifier returns the ANSI modifier for the given combination of control keys. +func getControlKeysModifier(shift, alt, control bool) string { + if shift && alt && control { + return ansiterm.KEY_CONTROL_PARAM_8 + } + if alt && control { + return ansiterm.KEY_CONTROL_PARAM_7 + } + if shift && control { + return ansiterm.KEY_CONTROL_PARAM_6 + } + if control { + return ansiterm.KEY_CONTROL_PARAM_5 + } + if shift && alt { + return ansiterm.KEY_CONTROL_PARAM_4 + } + if alt { + return ansiterm.KEY_CONTROL_PARAM_3 + } + if shift { + return ansiterm.KEY_CONTROL_PARAM_2 + } + return "" +} diff --git a/vendor/github.com/moby/term/windows/ansi_writer.go b/vendor/github.com/moby/term/windows/ansi_writer.go new file mode 100644 index 0000000000..4243307fd3 --- /dev/null +++ b/vendor/github.com/moby/term/windows/ansi_writer.go @@ -0,0 +1,57 @@ +//go:build windows +// +build windows + +package windowsconsole + +import ( + "io" + "os" + + ansiterm "github.com/Azure/go-ansiterm" + "github.com/Azure/go-ansiterm/winterm" +) + +// ansiWriter wraps a standard output file (e.g., os.Stdout) providing ANSI sequence translation. +type ansiWriter struct { + file *os.File + fd uintptr + infoReset *winterm.CONSOLE_SCREEN_BUFFER_INFO + command []byte + escapeSequence []byte + inAnsiSequence bool + parser *ansiterm.AnsiParser +} + +// NewAnsiWriter returns an io.Writer that provides VT100 terminal emulation on top of a +// Windows console output handle. +func NewAnsiWriter(nFile int) io.Writer { + file, fd := winterm.GetStdFile(nFile) + info, err := winterm.GetConsoleScreenBufferInfo(fd) + if err != nil { + return nil + } + + parser := ansiterm.CreateParser("Ground", winterm.CreateWinEventHandler(fd, file)) + + return &ansiWriter{ + file: file, + fd: fd, + infoReset: info, + command: make([]byte, 0, ansiterm.ANSI_MAX_CMD_LENGTH), + escapeSequence: []byte(ansiterm.KEY_ESC_CSI), + parser: parser, + } +} + +func (aw *ansiWriter) Fd() uintptr { + return aw.fd +} + +// Write writes len(p) bytes from p to the underlying data stream. +func (aw *ansiWriter) Write(p []byte) (total int, err error) { + if len(p) == 0 { + return 0, nil + } + + return aw.parser.Parse(p) +} diff --git a/vendor/github.com/moby/term/windows/console.go b/vendor/github.com/moby/term/windows/console.go new file mode 100644 index 0000000000..21e57bd52f --- /dev/null +++ b/vendor/github.com/moby/term/windows/console.go @@ -0,0 +1,43 @@ +//go:build windows +// +build windows + +package windowsconsole + +import ( + "os" + + "golang.org/x/sys/windows" +) + +// GetHandleInfo returns file descriptor and bool indicating whether the file is a console. +func GetHandleInfo(in interface{}) (uintptr, bool) { + switch t := in.(type) { + case *ansiReader: + return t.Fd(), true + case *ansiWriter: + return t.Fd(), true + } + + var inFd uintptr + var isTerminal bool + + if file, ok := in.(*os.File); ok { + inFd = file.Fd() + isTerminal = isConsole(inFd) + } + return inFd, isTerminal +} + +// IsConsole returns true if the given file descriptor is a Windows Console. +// The code assumes that GetConsoleMode will return an error for file descriptors that are not a console. +// +// Deprecated: use [windows.GetConsoleMode] or [golang.org/x/term.IsTerminal]. +func IsConsole(fd uintptr) bool { + return isConsole(fd) +} + +func isConsole(fd uintptr) bool { + var mode uint32 + err := windows.GetConsoleMode(windows.Handle(fd), &mode) + return err == nil +} diff --git a/vendor/github.com/moby/term/windows/doc.go b/vendor/github.com/moby/term/windows/doc.go new file mode 100644 index 0000000000..54265fffaf --- /dev/null +++ b/vendor/github.com/moby/term/windows/doc.go @@ -0,0 +1,5 @@ +// These files implement ANSI-aware input and output streams for use by the Docker Windows client. +// When asked for the set of standard streams (e.g., stdin, stdout, stderr), the code will create +// and return pseudo-streams that convert ANSI sequences to / from Windows Console API calls. + +package windowsconsole diff --git a/vendor/github.com/mxk/go-flowrate/LICENSE b/vendor/github.com/mxk/go-flowrate/LICENSE new file mode 100644 index 0000000000..e9f9f628ba --- /dev/null +++ b/vendor/github.com/mxk/go-flowrate/LICENSE @@ -0,0 +1,29 @@ +Copyright (c) 2014 The Go-FlowRate 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 the go-flowrate project nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/mxk/go-flowrate/flowrate/flowrate.go b/vendor/github.com/mxk/go-flowrate/flowrate/flowrate.go new file mode 100644 index 0000000000..1b727721e1 --- /dev/null +++ b/vendor/github.com/mxk/go-flowrate/flowrate/flowrate.go @@ -0,0 +1,267 @@ +// +// Written by Maxim Khitrov (November 2012) +// + +// Package flowrate provides the tools for monitoring and limiting the flow rate +// of an arbitrary data stream. +package flowrate + +import ( + "math" + "sync" + "time" +) + +// Monitor monitors and limits the transfer rate of a data stream. +type Monitor struct { + mu sync.Mutex // Mutex guarding access to all internal fields + active bool // Flag indicating an active transfer + start time.Duration // Transfer start time (clock() value) + bytes int64 // Total number of bytes transferred + samples int64 // Total number of samples taken + + rSample float64 // Most recent transfer rate sample (bytes per second) + rEMA float64 // Exponential moving average of rSample + rPeak float64 // Peak transfer rate (max of all rSamples) + rWindow float64 // rEMA window (seconds) + + sBytes int64 // Number of bytes transferred since sLast + sLast time.Duration // Most recent sample time (stop time when inactive) + sRate time.Duration // Sampling rate + + tBytes int64 // Number of bytes expected in the current transfer + tLast time.Duration // Time of the most recent transfer of at least 1 byte +} + +// New creates a new flow control monitor. Instantaneous transfer rate is +// measured and updated for each sampleRate interval. windowSize determines the +// weight of each sample in the exponential moving average (EMA) calculation. +// The exact formulas are: +// +// sampleTime = currentTime - prevSampleTime +// sampleRate = byteCount / sampleTime +// weight = 1 - exp(-sampleTime/windowSize) +// newRate = weight*sampleRate + (1-weight)*oldRate +// +// The default values for sampleRate and windowSize (if <= 0) are 100ms and 1s, +// respectively. +func New(sampleRate, windowSize time.Duration) *Monitor { + if sampleRate = clockRound(sampleRate); sampleRate <= 0 { + sampleRate = 5 * clockRate + } + if windowSize <= 0 { + windowSize = 1 * time.Second + } + now := clock() + return &Monitor{ + active: true, + start: now, + rWindow: windowSize.Seconds(), + sLast: now, + sRate: sampleRate, + tLast: now, + } +} + +// Update records the transfer of n bytes and returns n. It should be called +// after each Read/Write operation, even if n is 0. +func (m *Monitor) Update(n int) int { + m.mu.Lock() + m.update(n) + m.mu.Unlock() + return n +} + +// IO is a convenience method intended to wrap io.Reader and io.Writer method +// execution. It calls m.Update(n) and then returns (n, err) unmodified. +func (m *Monitor) IO(n int, err error) (int, error) { + return m.Update(n), err +} + +// Done marks the transfer as finished and prevents any further updates or +// limiting. Instantaneous and current transfer rates drop to 0. Update, IO, and +// Limit methods become NOOPs. It returns the total number of bytes transferred. +func (m *Monitor) Done() int64 { + m.mu.Lock() + if now := m.update(0); m.sBytes > 0 { + m.reset(now) + } + m.active = false + m.tLast = 0 + n := m.bytes + m.mu.Unlock() + return n +} + +// timeRemLimit is the maximum Status.TimeRem value. +const timeRemLimit = 999*time.Hour + 59*time.Minute + 59*time.Second + +// Status represents the current Monitor status. All transfer rates are in bytes +// per second rounded to the nearest byte. +type Status struct { + Active bool // Flag indicating an active transfer + Start time.Time // Transfer start time + Duration time.Duration // Time period covered by the statistics + Idle time.Duration // Time since the last transfer of at least 1 byte + Bytes int64 // Total number of bytes transferred + Samples int64 // Total number of samples taken + InstRate int64 // Instantaneous transfer rate + CurRate int64 // Current transfer rate (EMA of InstRate) + AvgRate int64 // Average transfer rate (Bytes / Duration) + PeakRate int64 // Maximum instantaneous transfer rate + BytesRem int64 // Number of bytes remaining in the transfer + TimeRem time.Duration // Estimated time to completion + Progress Percent // Overall transfer progress +} + +// Status returns current transfer status information. The returned value +// becomes static after a call to Done. +func (m *Monitor) Status() Status { + m.mu.Lock() + now := m.update(0) + s := Status{ + Active: m.active, + Start: clockToTime(m.start), + Duration: m.sLast - m.start, + Idle: now - m.tLast, + Bytes: m.bytes, + Samples: m.samples, + PeakRate: round(m.rPeak), + BytesRem: m.tBytes - m.bytes, + Progress: percentOf(float64(m.bytes), float64(m.tBytes)), + } + if s.BytesRem < 0 { + s.BytesRem = 0 + } + if s.Duration > 0 { + rAvg := float64(s.Bytes) / s.Duration.Seconds() + s.AvgRate = round(rAvg) + if s.Active { + s.InstRate = round(m.rSample) + s.CurRate = round(m.rEMA) + if s.BytesRem > 0 { + if tRate := 0.8*m.rEMA + 0.2*rAvg; tRate > 0 { + ns := float64(s.BytesRem) / tRate * 1e9 + if ns > float64(timeRemLimit) { + ns = float64(timeRemLimit) + } + s.TimeRem = clockRound(time.Duration(ns)) + } + } + } + } + m.mu.Unlock() + return s +} + +// Limit restricts the instantaneous (per-sample) data flow to rate bytes per +// second. It returns the maximum number of bytes (0 <= n <= want) that may be +// transferred immediately without exceeding the limit. If block == true, the +// call blocks until n > 0. want is returned unmodified if want < 1, rate < 1, +// or the transfer is inactive (after a call to Done). +// +// At least one byte is always allowed to be transferred in any given sampling +// period. Thus, if the sampling rate is 100ms, the lowest achievable flow rate +// is 10 bytes per second. +// +// For usage examples, see the implementation of Reader and Writer in io.go. +func (m *Monitor) Limit(want int, rate int64, block bool) (n int) { + if want < 1 || rate < 1 { + return want + } + m.mu.Lock() + + // Determine the maximum number of bytes that can be sent in one sample + limit := round(float64(rate) * m.sRate.Seconds()) + if limit <= 0 { + limit = 1 + } + + // If block == true, wait until m.sBytes < limit + if now := m.update(0); block { + for m.sBytes >= limit && m.active { + now = m.waitNextSample(now) + } + } + + // Make limit <= want (unlimited if the transfer is no longer active) + if limit -= m.sBytes; limit > int64(want) || !m.active { + limit = int64(want) + } + m.mu.Unlock() + + if limit < 0 { + limit = 0 + } + return int(limit) +} + +// SetTransferSize specifies the total size of the data transfer, which allows +// the Monitor to calculate the overall progress and time to completion. +func (m *Monitor) SetTransferSize(bytes int64) { + if bytes < 0 { + bytes = 0 + } + m.mu.Lock() + m.tBytes = bytes + m.mu.Unlock() +} + +// update accumulates the transferred byte count for the current sample until +// clock() - m.sLast >= m.sRate. The monitor status is updated once the current +// sample is done. +func (m *Monitor) update(n int) (now time.Duration) { + if !m.active { + return + } + if now = clock(); n > 0 { + m.tLast = now + } + m.sBytes += int64(n) + if sTime := now - m.sLast; sTime >= m.sRate { + t := sTime.Seconds() + if m.rSample = float64(m.sBytes) / t; m.rSample > m.rPeak { + m.rPeak = m.rSample + } + + // Exponential moving average using a method similar to *nix load + // average calculation. Longer sampling periods carry greater weight. + if m.samples > 0 { + w := math.Exp(-t / m.rWindow) + m.rEMA = m.rSample + w*(m.rEMA-m.rSample) + } else { + m.rEMA = m.rSample + } + m.reset(now) + } + return +} + +// reset clears the current sample state in preparation for the next sample. +func (m *Monitor) reset(sampleTime time.Duration) { + m.bytes += m.sBytes + m.samples++ + m.sBytes = 0 + m.sLast = sampleTime +} + +// waitNextSample sleeps for the remainder of the current sample. The lock is +// released and reacquired during the actual sleep period, so it's possible for +// the transfer to be inactive when this method returns. +func (m *Monitor) waitNextSample(now time.Duration) time.Duration { + const minWait = 5 * time.Millisecond + current := m.sLast + + // sleep until the last sample time changes (ideally, just one iteration) + for m.sLast == current && m.active { + d := current + m.sRate - now + m.mu.Unlock() + if d < minWait { + d = minWait + } + time.Sleep(d) + m.mu.Lock() + now = m.update(0) + } + return now +} diff --git a/vendor/github.com/mxk/go-flowrate/flowrate/io.go b/vendor/github.com/mxk/go-flowrate/flowrate/io.go new file mode 100644 index 0000000000..fbe0909725 --- /dev/null +++ b/vendor/github.com/mxk/go-flowrate/flowrate/io.go @@ -0,0 +1,133 @@ +// +// Written by Maxim Khitrov (November 2012) +// + +package flowrate + +import ( + "errors" + "io" +) + +// ErrLimit is returned by the Writer when a non-blocking write is short due to +// the transfer rate limit. +var ErrLimit = errors.New("flowrate: flow rate limit exceeded") + +// Limiter is implemented by the Reader and Writer to provide a consistent +// interface for monitoring and controlling data transfer. +type Limiter interface { + Done() int64 + Status() Status + SetTransferSize(bytes int64) + SetLimit(new int64) (old int64) + SetBlocking(new bool) (old bool) +} + +// Reader implements io.ReadCloser with a restriction on the rate of data +// transfer. +type Reader struct { + io.Reader // Data source + *Monitor // Flow control monitor + + limit int64 // Rate limit in bytes per second (unlimited when <= 0) + block bool // What to do when no new bytes can be read due to the limit +} + +// NewReader restricts all Read operations on r to limit bytes per second. +func NewReader(r io.Reader, limit int64) *Reader { + return &Reader{r, New(0, 0), limit, true} +} + +// Read reads up to len(p) bytes into p without exceeding the current transfer +// rate limit. It returns (0, nil) immediately if r is non-blocking and no new +// bytes can be read at this time. +func (r *Reader) Read(p []byte) (n int, err error) { + p = p[:r.Limit(len(p), r.limit, r.block)] + if len(p) > 0 { + n, err = r.IO(r.Reader.Read(p)) + } + return +} + +// SetLimit changes the transfer rate limit to new bytes per second and returns +// the previous setting. +func (r *Reader) SetLimit(new int64) (old int64) { + old, r.limit = r.limit, new + return +} + +// SetBlocking changes the blocking behavior and returns the previous setting. A +// Read call on a non-blocking reader returns immediately if no additional bytes +// may be read at this time due to the rate limit. +func (r *Reader) SetBlocking(new bool) (old bool) { + old, r.block = r.block, new + return +} + +// Close closes the underlying reader if it implements the io.Closer interface. +func (r *Reader) Close() error { + defer r.Done() + if c, ok := r.Reader.(io.Closer); ok { + return c.Close() + } + return nil +} + +// Writer implements io.WriteCloser with a restriction on the rate of data +// transfer. +type Writer struct { + io.Writer // Data destination + *Monitor // Flow control monitor + + limit int64 // Rate limit in bytes per second (unlimited when <= 0) + block bool // What to do when no new bytes can be written due to the limit +} + +// NewWriter restricts all Write operations on w to limit bytes per second. The +// transfer rate and the default blocking behavior (true) can be changed +// directly on the returned *Writer. +func NewWriter(w io.Writer, limit int64) *Writer { + return &Writer{w, New(0, 0), limit, true} +} + +// Write writes len(p) bytes from p to the underlying data stream without +// exceeding the current transfer rate limit. It returns (n, ErrLimit) if w is +// non-blocking and no additional bytes can be written at this time. +func (w *Writer) Write(p []byte) (n int, err error) { + var c int + for len(p) > 0 && err == nil { + s := p[:w.Limit(len(p), w.limit, w.block)] + if len(s) > 0 { + c, err = w.IO(w.Writer.Write(s)) + } else { + return n, ErrLimit + } + p = p[c:] + n += c + } + return +} + +// SetLimit changes the transfer rate limit to new bytes per second and returns +// the previous setting. +func (w *Writer) SetLimit(new int64) (old int64) { + old, w.limit = w.limit, new + return +} + +// SetBlocking changes the blocking behavior and returns the previous setting. A +// Write call on a non-blocking writer returns as soon as no additional bytes +// may be written at this time due to the rate limit. +func (w *Writer) SetBlocking(new bool) (old bool) { + old, w.block = w.block, new + return +} + +// Close closes the underlying writer if it implements the io.Closer interface. +func (w *Writer) Close() error { + defer w.Done() + if c, ok := w.Writer.(io.Closer); ok { + return c.Close() + } + return nil +} diff --git a/vendor/github.com/mxk/go-flowrate/flowrate/util.go b/vendor/github.com/mxk/go-flowrate/flowrate/util.go new file mode 100644 index 0000000000..4caac583fc --- /dev/null +++ b/vendor/github.com/mxk/go-flowrate/flowrate/util.go @@ -0,0 +1,67 @@ +// +// Written by Maxim Khitrov (November 2012) +// + +package flowrate + +import ( + "math" + "strconv" + "time" +) + +// clockRate is the resolution and precision of clock(). +const clockRate = 20 * time.Millisecond + +// czero is the process start time rounded down to the nearest clockRate +// increment. +var czero = time.Duration(time.Now().UnixNano()) / clockRate * clockRate + +// clock returns a low resolution timestamp relative to the process start time. +func clock() time.Duration { + return time.Duration(time.Now().UnixNano())/clockRate*clockRate - czero +} + +// clockToTime converts a clock() timestamp to an absolute time.Time value. +func clockToTime(c time.Duration) time.Time { + return time.Unix(0, int64(czero+c)) +} + +// clockRound returns d rounded to the nearest clockRate increment. +func clockRound(d time.Duration) time.Duration { + return (d + clockRate>>1) / clockRate * clockRate +} + +// round returns x rounded to the nearest int64 (non-negative values only). +func round(x float64) int64 { + if _, frac := math.Modf(x); frac >= 0.5 { + return int64(math.Ceil(x)) + } + return int64(math.Floor(x)) +} + +// Percent represents a percentage in increments of 1/1000th of a percent. +type Percent uint32 + +// percentOf calculates what percent of the total is x. +func percentOf(x, total float64) Percent { + if x < 0 || total <= 0 { + return 0 + } else if p := round(x / total * 1e5); p <= math.MaxUint32 { + return Percent(p) + } + return Percent(math.MaxUint32) +} + +func (p Percent) Float() float64 { + return float64(p) * 1e-3 +} + +func (p Percent) String() string { + var buf [12]byte + b := strconv.AppendUint(buf[:0], uint64(p)/1000, 10) + n := len(b) + b = strconv.AppendUint(b, 1000+uint64(p)%1000, 10) + b[n] = '.' + return string(append(b, '%')) +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/action/generate_dockerfile.go b/vendor/github.com/operator-framework/operator-registry/alpha/action/generate_dockerfile.go new file mode 100644 index 0000000000..4d2a3ddfc7 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/action/generate_dockerfile.go @@ -0,0 +1,64 @@ +package action + +import ( + "fmt" + "io" + "text/template" + + "github.com/operator-framework/operator-registry/pkg/containertools" +) + +type GenerateDockerfile struct { + BaseImage string + IndexDir string + ExtraLabels map[string]string + Writer io.Writer +} + +func (i GenerateDockerfile) Run() error { + if err := i.validate(); err != nil { + return err + } + + t, err := template.New("dockerfile").Parse(dockerfileTmpl) + if err != nil { + // The template is hardcoded in the binary, so if + // there is a parse error, it was a programmer error. + panic(err) + } + return t.Execute(i.Writer, i) +} + +func (i GenerateDockerfile) validate() error { + if i.BaseImage == "" { + return fmt.Errorf("base image is unset") + } + if i.IndexDir == "" { + return fmt.Errorf("index directory is unset") + } + return nil +} + +const dockerfileTmpl = `# The base image is expected to contain +# /bin/opm (with a serve subcommand) and /bin/grpc_health_probe +FROM {{.BaseImage}} + +# Configure the entrypoint and command +ENTRYPOINT ["/bin/opm"] +CMD ["serve", "/configs", "--cache-dir=/tmp/cache"] + +# Copy declarative config root into image at /configs and pre-populate serve cache +ADD {{.IndexDir}} /configs +RUN ["/bin/opm", "serve", "/configs", "--cache-dir=/tmp/cache", "--cache-only"] + +# Set DC-specific label for the location of the DC root directory +# in the image +LABEL ` + containertools.ConfigsLocationLabel + `=/configs +{{- if .ExtraLabels }} + +# Set other custom labels +{{- range $key, $value := .ExtraLabels }} +LABEL "{{ $key }}"="{{ $value }}" +{{- end }} +{{- end }} +` diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/action/init.go b/vendor/github.com/operator-framework/operator-registry/alpha/action/init.go new file mode 100644 index 0000000000..242d8f818d --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/action/init.go @@ -0,0 +1,52 @@ +package action + +import ( + "fmt" + "io" + + "github.com/h2non/filetype" + + "github.com/operator-framework/operator-registry/alpha/declcfg" +) + +type Init struct { + Package string + DefaultChannel string + DescriptionReader io.Reader + IconReader io.Reader +} + +func (i Init) Run() (*declcfg.Package, error) { + pkg := &declcfg.Package{ + // TODO(joelanford): Use a constant for "olm.package" + Schema: "olm.package", + Name: i.Package, + DefaultChannel: i.DefaultChannel, + } + if i.DescriptionReader != nil { + descriptionData, err := io.ReadAll(i.DescriptionReader) + if err != nil { + return nil, fmt.Errorf("read description: %v", err) + } + pkg.Description = string(descriptionData) + } + + if i.IconReader != nil { + iconData, err := io.ReadAll(i.IconReader) + if err != nil { + return nil, fmt.Errorf("read icon: %v", err) + } + iconType, err := filetype.Match(iconData) + if err != nil { + return nil, fmt.Errorf("detect icon mediatype: %v", err) + } + if iconType.MIME.Type != "image" { + return nil, fmt.Errorf("detected invalid type %q: not an image", iconType.MIME.Value) + } + pkg.Icon = &declcfg.Icon{ + Data: iconData, + MediaType: iconType.MIME.Value, + } + } + return pkg, nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/action/list.go b/vendor/github.com/operator-framework/operator-registry/alpha/action/list.go new file mode 100644 index 0000000000..80c014d1d9 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/action/list.go @@ -0,0 +1,212 @@ +package action + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "sort" + "strings" + "text/tabwriter" + + "github.com/operator-framework/api/pkg/operators/v1alpha1" + + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/alpha/model" + "github.com/operator-framework/operator-registry/pkg/image" +) + +type ListPackages struct { + IndexReference string + Registry image.Registry +} + +func (l *ListPackages) Run(ctx context.Context) (*ListPackagesResult, error) { + m, err := indexRefToModel(ctx, l.IndexReference, l.Registry) + if err != nil { + return nil, err + } + + pkgs := []model.Package{} + for _, pkg := range m { + pkgs = append(pkgs, *pkg) + } + sort.Slice(pkgs, func(i, j int) bool { + return pkgs[i].Name < pkgs[j].Name + }) + return &ListPackagesResult{Packages: pkgs}, nil +} + +type ListPackagesResult struct { + Packages []model.Package +} + +func (r *ListPackagesResult) WriteColumns(w io.Writer) error { + tw := tabwriter.NewWriter(w, 0, 4, 2, ' ', 0) + if _, err := fmt.Fprintln(tw, "NAME\tDISPLAY NAME\tDEFAULT CHANNEL"); err != nil { + return err + } + for _, pkg := range r.Packages { + if _, err := fmt.Fprintf(tw, "%s\t%s\t%s\n", pkg.Name, getDisplayName(pkg), pkg.DefaultChannel.Name); err != nil { + return err + } + } + return tw.Flush() +} + +func getDisplayName(pkg model.Package) string { + if pkg.DefaultChannel == nil { + return "" + } + head, err := pkg.DefaultChannel.Head() + if err != nil || head == nil || head.CsvJSON == "" { + return "" + } + + csv := v1alpha1.ClusterServiceVersion{} + if err := json.Unmarshal([]byte(head.CsvJSON), &csv); err != nil { + return "" + } + return csv.Spec.DisplayName +} + +type ListChannels struct { + IndexReference string + PackageName string + Registry image.Registry +} + +func (l *ListChannels) Run(ctx context.Context) (*ListChannelsResult, error) { + m, err := indexRefToModel(ctx, l.IndexReference, l.Registry) + if err != nil { + return nil, err + } + + pkgs, err := getPackages(m, l.PackageName) + if err != nil { + return nil, err + } + + channels := []model.Channel{} + for _, pkg := range pkgs { + for _, ch := range pkg.Channels { + channels = append(channels, *ch) + } + } + + sort.Slice(channels, func(i, j int) bool { + if channels[i].Package.Name != channels[j].Package.Name { + return channels[i].Package.Name < channels[j].Package.Name + } + return channels[i].Name < channels[j].Name + }) + return &ListChannelsResult{Channels: channels}, nil +} + +type ListChannelsResult struct { + Channels []model.Channel +} + +func (r *ListChannelsResult) WriteColumns(w io.Writer) error { + tw := tabwriter.NewWriter(w, 0, 4, 2, ' ', 0) + if _, err := fmt.Fprintln(tw, "PACKAGE\tCHANNEL\tHEAD"); err != nil { + return err + } + for _, ch := range r.Channels { + headStr := "" + head, err := ch.Head() + if err != nil { + headStr = fmt.Sprintf("ERROR: %s", err) + } else { + headStr = head.Name + } + if _, err := fmt.Fprintf(tw, "%s\t%s\t%s\n", ch.Package.Name, ch.Name, headStr); err != nil { + return err + } + } + return tw.Flush() +} + +type ListBundles struct { + IndexReference string + PackageName string + Registry image.Registry +} + +func (l *ListBundles) Run(ctx context.Context) (*ListBundlesResult, error) { + m, err := indexRefToModel(ctx, l.IndexReference, l.Registry) + if err != nil { + return nil, err + } + + pkgs, err := getPackages(m, l.PackageName) + if err != nil { + return nil, err + } + + bundles := []model.Bundle{} + for _, pkg := range pkgs { + for _, ch := range pkg.Channels { + for _, b := range ch.Bundles { + bundles = append(bundles, *b) + } + } + } + + sort.Slice(bundles, func(i, j int) bool { + if bundles[i].Package.Name != bundles[j].Package.Name { + return bundles[i].Package.Name < bundles[j].Package.Name + } + if bundles[i].Channel.Name != bundles[j].Channel.Name { + return bundles[i].Channel.Name < bundles[j].Channel.Name + } + return bundles[i].Name < bundles[j].Name + }) + return &ListBundlesResult{Bundles: bundles}, nil +} + +type ListBundlesResult struct { + Bundles []model.Bundle +} + +func (r *ListBundlesResult) WriteColumns(w io.Writer) error { + tw := tabwriter.NewWriter(w, 0, 4, 2, ' ', 0) + if _, err := fmt.Fprintln(tw, "PACKAGE\tCHANNEL\tBUNDLE\tREPLACES\tSKIPS\tSKIP RANGE\tIMAGE"); err != nil { + return err + } + for _, b := range r.Bundles { + if _, err := fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", b.Package.Name, b.Channel.Name, b.Name, b.Replaces, strings.Join(b.Skips, ","), b.SkipRange, b.Image); err != nil { + return err + } + } + return tw.Flush() +} + +func indexRefToModel(ctx context.Context, ref string, reg image.Registry) (model.Model, error) { + render := Render{ + Refs: []string{ref}, + AllowedRefMask: RefDCImage | RefDCDir | RefSqliteImage | RefSqliteFile, + Registry: reg, + } + cfg, err := render.Run(ctx) + if err != nil { + if errors.Is(err, ErrNotAllowed) { + return nil, fmt.Errorf("cannot list non-index %q", ref) + } + return nil, err + } + + return declcfg.ConvertToModel(*cfg) +} + +func getPackages(m model.Model, packageName string) (model.Model, error) { + if packageName == "" { + return m, nil + } + pkg, ok := m[packageName] + if !ok { + return nil, fmt.Errorf("package %q not found", packageName) + } + return model.Model{packageName: pkg}, nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/action/migrate.go b/vendor/github.com/operator-framework/operator-registry/alpha/action/migrate.go new file mode 100644 index 0000000000..3a502300f1 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/action/migrate.go @@ -0,0 +1,47 @@ +package action + +import ( + "context" + "fmt" + "os" + + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/pkg/image" +) + +type Migrate struct { + CatalogRef string + OutputDir string + + WriteFunc declcfg.WriteFunc + FileExt string + Registry image.Registry +} + +func (m Migrate) Run(ctx context.Context) error { + entries, err := os.ReadDir(m.OutputDir) + if err != nil && !os.IsNotExist(err) { + return err + } + if len(entries) > 0 { + return fmt.Errorf("output dir %q must be empty", m.OutputDir) + } + + r := Render{ + Refs: []string{m.CatalogRef}, + Migrate: true, + + // Only allow catalogs to be migrated. + AllowedRefMask: RefSqliteImage | RefSqliteFile | RefDCImage | RefDCDir, + } + if m.Registry != nil { + r.Registry = m.Registry + } + + cfg, err := r.Run(ctx) + if err != nil { + return fmt.Errorf("render catalog image: %w", err) + } + + return declcfg.WriteFS(*cfg, m.OutputDir, m.WriteFunc, m.FileExt) +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/action/render.go b/vendor/github.com/operator-framework/operator-registry/alpha/action/render.go new file mode 100644 index 0000000000..be63aab539 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/action/render.go @@ -0,0 +1,538 @@ +package action + +import ( + "context" + "database/sql" + "encoding/json" + "errors" + "fmt" + "os" + "path/filepath" + "sort" + "strings" + "sync" + "text/template" + + "github.com/h2non/filetype" + "github.com/h2non/filetype/matchers" + "github.com/operator-framework/api/pkg/operators/v1alpha1" + "k8s.io/apimachinery/pkg/util/sets" + + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/alpha/property" + "github.com/operator-framework/operator-registry/pkg/containertools" + "github.com/operator-framework/operator-registry/pkg/image" + "github.com/operator-framework/operator-registry/pkg/image/containerdregistry" + "github.com/operator-framework/operator-registry/pkg/lib/bundle" + "github.com/operator-framework/operator-registry/pkg/lib/log" + "github.com/operator-framework/operator-registry/pkg/registry" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +var logDeprecationMessage sync.Once + +type RefType uint + +const ( + RefBundleImage RefType = 1 << iota + RefSqliteImage + RefSqliteFile + RefDCImage + RefDCDir + RefBundleDir + + RefAll = 0 +) + +func (r RefType) Allowed(refType RefType) bool { + return r == RefAll || r&refType == refType +} + +var ErrNotAllowed = errors.New("not allowed") + +type Render struct { + Refs []string + Registry image.Registry + AllowedRefMask RefType + Migrate bool + ImageRefTemplate *template.Template + + skipSqliteDeprecationLog bool +} + +func (r Render) Run(ctx context.Context) (*declcfg.DeclarativeConfig, error) { + if r.skipSqliteDeprecationLog { + // exhaust once with a no-op function. + logDeprecationMessage.Do(func() {}) + } + if r.Registry == nil { + reg, err := r.createRegistry() + if err != nil { + return nil, fmt.Errorf("create registry: %v", err) + } + defer reg.Destroy() + r.Registry = reg + } + + var cfgs []declcfg.DeclarativeConfig + for _, ref := range r.Refs { + cfg, err := r.renderReference(ctx, ref) + if err != nil { + return nil, fmt.Errorf("render reference %q: %w", ref, err) + } + moveBundleObjectsToEndOfPropertySlices(cfg) + + for _, b := range cfg.Bundles { + sort.Slice(b.RelatedImages, func(i, j int) bool { + return b.RelatedImages[i].Image < b.RelatedImages[j].Image + }) + } + + if r.Migrate { + if err := migrate(cfg); err != nil { + return nil, fmt.Errorf("migrate: %v", err) + } + } + + cfgs = append(cfgs, *cfg) + } + + return combineConfigs(cfgs), nil +} + +func (r Render) createRegistry() (*containerdregistry.Registry, error) { + cacheDir, err := os.MkdirTemp("", "render-registry-") + if err != nil { + return nil, fmt.Errorf("create tempdir: %v", err) + } + + reg, err := containerdregistry.NewRegistry( + containerdregistry.WithCacheDir(cacheDir), + + // The containerd registry impl is somewhat verbose, even on the happy path, + // so discard all logger logs. Any important failures will be returned from + // registry methods and eventually logged as fatal errors. + containerdregistry.WithLog(log.Null()), + ) + if err != nil { + return nil, err + } + return reg, nil +} + +func (r Render) renderReference(ctx context.Context, ref string) (*declcfg.DeclarativeConfig, error) { + stat, err := os.Stat(ref) + if err != nil { + return r.imageToDeclcfg(ctx, ref) + } + if stat.IsDir() { + dirEntries, err := os.ReadDir(ref) + if err != nil { + return nil, err + } + if isBundle(dirEntries) { + // Looks like a bundle directory + if !r.AllowedRefMask.Allowed(RefBundleDir) { + return nil, fmt.Errorf("cannot render bundle directory %q: %w", ref, ErrNotAllowed) + } + return r.renderBundleDirectory(ref) + } + + // Otherwise, assume it is a declarative config root directory. + if !r.AllowedRefMask.Allowed(RefDCDir) { + return nil, fmt.Errorf("cannot render declarative config directory: %w", ErrNotAllowed) + } + return declcfg.LoadFS(ctx, os.DirFS(ref)) + } + // The only supported file type is an sqlite DB file, + // since declarative configs will be in a directory. + if err := checkDBFile(ref); err != nil { + return nil, err + } + if !r.AllowedRefMask.Allowed(RefSqliteFile) { + return nil, fmt.Errorf("cannot render sqlite file: %w", ErrNotAllowed) + } + + db, err := sqlite.Open(ref) + if err != nil { + return nil, err + } + defer db.Close() + return sqliteToDeclcfg(ctx, db) +} + +func (r Render) imageToDeclcfg(ctx context.Context, imageRef string) (*declcfg.DeclarativeConfig, error) { + ref := image.SimpleReference(imageRef) + if err := r.Registry.Pull(ctx, ref); err != nil { + return nil, err + } + labels, err := r.Registry.Labels(ctx, ref) + if err != nil { + return nil, err + } + tmpDir, err := os.MkdirTemp("", "render-unpack-") + if err != nil { + return nil, err + } + defer os.RemoveAll(tmpDir) + if err := r.Registry.Unpack(ctx, ref, tmpDir); err != nil { + return nil, err + } + + var cfg *declcfg.DeclarativeConfig + if dbFile, ok := labels[containertools.DbLocationLabel]; ok { + if !r.AllowedRefMask.Allowed(RefSqliteImage) { + return nil, fmt.Errorf("cannot render sqlite image: %w", ErrNotAllowed) + } + db, err := sqlite.Open(filepath.Join(tmpDir, dbFile)) + if err != nil { + return nil, err + } + defer db.Close() + cfg, err = sqliteToDeclcfg(ctx, db) + if err != nil { + return nil, err + } + } else if configsDir, ok := labels[containertools.ConfigsLocationLabel]; ok { + if !r.AllowedRefMask.Allowed(RefDCImage) { + return nil, fmt.Errorf("cannot render declarative config image: %w", ErrNotAllowed) + } + cfg, err = declcfg.LoadFS(ctx, os.DirFS(filepath.Join(tmpDir, configsDir))) + if err != nil { + return nil, err + } + } else if _, ok := labels[bundle.PackageLabel]; ok { + if !r.AllowedRefMask.Allowed(RefBundleImage) { + return nil, fmt.Errorf("cannot render bundle image: %w", ErrNotAllowed) + } + img, err := registry.NewImageInput(ref, tmpDir) + if err != nil { + return nil, err + } + + bundle, err := bundleToDeclcfg(img.Bundle) + if err != nil { + return nil, err + } + cfg = &declcfg.DeclarativeConfig{Bundles: []declcfg.Bundle{*bundle}} + } else { + labelKeys := sets.StringKeySet(labels) + labelVals := []string{} + for _, k := range labelKeys.List() { + labelVals = append(labelVals, fmt.Sprintf(" %s=%s", k, labels[k])) + } + if len(labelVals) > 0 { + return nil, fmt.Errorf("render %q: image type could not be determined, found labels\n%s", ref, strings.Join(labelVals, "\n")) + } else { + return nil, fmt.Errorf("render %q: image type could not be determined: image has no labels", ref) + } + } + return cfg, nil +} + +// checkDBFile returns an error if ref is not an sqlite3 database. +func checkDBFile(ref string) error { + typ, err := filetype.MatchFile(ref) + if err != nil { + return err + } + if typ != matchers.TypeSqlite { + return fmt.Errorf("ref %q has unsupported file type: %s", ref, typ) + } + return nil +} + +func sqliteToDeclcfg(ctx context.Context, db *sql.DB) (*declcfg.DeclarativeConfig, error) { + logDeprecationMessage.Do(func() { + sqlite.LogSqliteDeprecation() + }) + + migrator, err := sqlite.NewSQLLiteMigrator(db) + if err != nil { + return nil, err + } + if migrator == nil { + return nil, fmt.Errorf("failed to load migrator") + } + + if err := migrator.Migrate(ctx); err != nil { + return nil, err + } + + q := sqlite.NewSQLLiteQuerierFromDb(db) + m, err := sqlite.ToModel(ctx, q) + if err != nil { + return nil, err + } + + cfg := declcfg.ConvertFromModel(m) + + if err := populateDBRelatedImages(ctx, &cfg, db); err != nil { + return nil, err + } + + return &cfg, nil +} + +func populateDBRelatedImages(ctx context.Context, cfg *declcfg.DeclarativeConfig, db *sql.DB) error { + rows, err := db.QueryContext(ctx, "SELECT image, operatorbundle_name FROM related_image") + if err != nil { + return err + } + defer rows.Close() + + images := map[string]sets.String{} + for rows.Next() { + var ( + img sql.NullString + bundleName sql.NullString + ) + if err := rows.Scan(&img, &bundleName); err != nil { + return err + } + if !img.Valid || !bundleName.Valid { + continue + } + m, ok := images[bundleName.String] + if !ok { + m = sets.NewString() + } + m.Insert(img.String) + images[bundleName.String] = m + } + + for i, b := range cfg.Bundles { + ris, ok := images[b.Name] + if !ok { + continue + } + for _, ri := range b.RelatedImages { + if ris.Has(ri.Image) { + ris.Delete(ri.Image) + } + } + for ri := range ris { + cfg.Bundles[i].RelatedImages = append(cfg.Bundles[i].RelatedImages, declcfg.RelatedImage{Image: ri}) + } + } + return nil +} + +func bundleToDeclcfg(bundle *registry.Bundle) (*declcfg.Bundle, error) { + objs, props, err := registry.ObjectsAndPropertiesFromBundle(bundle) + if err != nil { + return nil, fmt.Errorf("get properties for bundle %q: %v", bundle.Name, err) + } + relatedImages, err := getRelatedImages(bundle) + if err != nil { + return nil, fmt.Errorf("get related images for bundle %q: %v", bundle.Name, err) + } + + var csvJson []byte + for _, obj := range bundle.Objects { + if obj.GetKind() == "ClusterServiceVersion" { + csvJson, err = json.Marshal(obj) + if err != nil { + return nil, fmt.Errorf("marshal CSV JSON for bundle %q: %v", bundle.Name, err) + } + } + } + + return &declcfg.Bundle{ + Schema: "olm.bundle", + Name: bundle.Name, + Package: bundle.Package, + Image: bundle.BundleImage, + Properties: props, + RelatedImages: relatedImages, + Objects: objs, + CsvJSON: string(csvJson), + }, nil +} + +func getRelatedImages(b *registry.Bundle) ([]declcfg.RelatedImage, error) { + csv, err := b.ClusterServiceVersion() + if err != nil { + return nil, err + } + + var objmap map[string]*json.RawMessage + if err = json.Unmarshal(csv.Spec, &objmap); err != nil { + return nil, err + } + + var relatedImages []declcfg.RelatedImage + rawValue, ok := objmap["relatedImages"] + if ok && rawValue != nil { + if err = json.Unmarshal(*rawValue, &relatedImages); err != nil { + return nil, err + } + } + + // Keep track of the images we've already found, so that we don't add + // them multiple times. + allImages := sets.NewString() + for _, ri := range relatedImages { + allImages = allImages.Insert(ri.Image) + } + + if b.BundleImage != "" && !allImages.Has(b.BundleImage) { + relatedImages = append(relatedImages, declcfg.RelatedImage{ + Image: b.BundleImage, + }) + } + + opImages, err := csv.GetOperatorImages() + if err != nil { + return nil, err + } + for img := range opImages { + if !allImages.Has(img) { + relatedImages = append(relatedImages, declcfg.RelatedImage{ + Image: img, + }) + } + allImages = allImages.Insert(img) + } + + return relatedImages, nil +} + +func moveBundleObjectsToEndOfPropertySlices(cfg *declcfg.DeclarativeConfig) { + for bi, b := range cfg.Bundles { + var ( + others []property.Property + objs []property.Property + ) + for _, p := range b.Properties { + switch p.Type { + case property.TypeBundleObject, property.TypeCSVMetadata: + objs = append(objs, p) + default: + others = append(others, p) + } + } + cfg.Bundles[bi].Properties = append(others, objs...) + } +} + +func migrate(cfg *declcfg.DeclarativeConfig) error { + migrations := []func(*declcfg.DeclarativeConfig) error{ + convertObjectsToCSVMetadata, + } + + for _, m := range migrations { + if err := m(cfg); err != nil { + return err + } + } + return nil +} + +func convertObjectsToCSVMetadata(cfg *declcfg.DeclarativeConfig) error { +BundleLoop: + for bi, b := range cfg.Bundles { + if b.Image == "" || b.CsvJSON == "" { + continue + } + + var csv v1alpha1.ClusterServiceVersion + if err := json.Unmarshal([]byte(b.CsvJSON), &csv); err != nil { + return err + } + + props := b.Properties[:0] + for _, p := range b.Properties { + switch p.Type { + case property.TypeBundleObject: + // Get rid of the bundle objects + case property.TypeCSVMetadata: + // If this bundle already has a CSV metadata + // property, we won't mutate the bundle at all. + continue BundleLoop + default: + // Keep all of the other properties + props = append(props, p) + } + } + cfg.Bundles[bi].Properties = append(props, property.MustBuildCSVMetadata(csv)) + } + return nil +} + +func combineConfigs(cfgs []declcfg.DeclarativeConfig) *declcfg.DeclarativeConfig { + out := &declcfg.DeclarativeConfig{} + for _, in := range cfgs { + out.Merge(&in) + } + return out +} + +func isBundle(entries []os.DirEntry) bool { + foundManifests := false + foundMetadata := false + for _, e := range entries { + if e.IsDir() { + switch e.Name() { + case "manifests": + foundManifests = true + case "metadata": + foundMetadata = true + } + } + if foundMetadata && foundManifests { + return true + } + } + return false +} + +type imageReferenceTemplateData struct { + Package string + Name string + Version string +} + +func (r *Render) renderBundleDirectory(ref string) (*declcfg.DeclarativeConfig, error) { + img, err := registry.NewImageInput(image.SimpleReference(""), ref) + if err != nil { + return nil, err + } + if err := r.templateBundleImageRef(img.Bundle); err != nil { + return nil, fmt.Errorf("failed templating image reference from bundle for %q: %v", ref, err) + } + fbcBundle, err := bundleToDeclcfg(img.Bundle) + if err != nil { + return nil, err + } + return &declcfg.DeclarativeConfig{Bundles: []declcfg.Bundle{*fbcBundle}}, nil +} + +func (r *Render) templateBundleImageRef(bundle *registry.Bundle) error { + if r.ImageRefTemplate == nil { + return nil + } + + var pkgProp property.Package + for _, p := range bundle.Properties { + if p.Type != property.TypePackage { + continue + } + if err := json.Unmarshal(p.Value, &pkgProp); err != nil { + return err + } + break + } + + var buf strings.Builder + tmplInput := imageReferenceTemplateData{ + Package: bundle.Package, + Name: bundle.Name, + Version: pkgProp.Version, + } + if err := r.ImageRefTemplate.Execute(&buf, tmplInput); err != nil { + return err + } + bundle.BundleImage = buf.String() + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/declcfg.go b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/declcfg.go new file mode 100644 index 0000000000..3474814be5 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/declcfg.go @@ -0,0 +1,209 @@ +package declcfg + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + + prettyunmarshaler "github.com/operator-framework/operator-registry/pkg/prettyunmarshaler" + + "golang.org/x/text/cases" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/sets" + + "github.com/operator-framework/operator-registry/alpha/property" +) + +const ( + SchemaPackage = "olm.package" + SchemaChannel = "olm.channel" + SchemaBundle = "olm.bundle" + SchemaDeprecation = "olm.deprecations" +) + +type DeclarativeConfig struct { + Packages []Package + Channels []Channel + Bundles []Bundle + Deprecations []Deprecation + Others []Meta +} + +type Package struct { + Schema string `json:"schema"` + Name string `json:"name"` + DefaultChannel string `json:"defaultChannel"` + Icon *Icon `json:"icon,omitempty"` + Description string `json:"description,omitempty"` + Properties []property.Property `json:"properties,omitempty" hash:"set"` +} + +type Icon struct { + Data []byte `json:"base64data"` + MediaType string `json:"mediatype"` +} + +type Channel struct { + Schema string `json:"schema"` + Name string `json:"name"` + Package string `json:"package"` + Entries []ChannelEntry `json:"entries"` + Properties []property.Property `json:"properties,omitempty" hash:"set"` +} + +type ChannelEntry struct { + Name string `json:"name"` + Replaces string `json:"replaces,omitempty"` + Skips []string `json:"skips,omitempty"` + SkipRange string `json:"skipRange,omitempty"` +} + +// Bundle specifies all metadata and data of a bundle object. +// Top-level fields are the source of truth, i.e. not CSV values. +// +// Notes: +// - Any field slice type field or type containing a slice somewhere +// where two types/fields are equal if their contents are equal regardless +// of order must have a `hash:"set"` field tag for bundle comparison. +// - Any fields that have a `json:"-"` tag must be included in the equality +// evaluation in bundlesEqual(). +type Bundle struct { + Schema string `json:"schema"` + Name string `json:"name"` + Package string `json:"package"` + Image string `json:"image"` + Properties []property.Property `json:"properties,omitempty" hash:"set"` + RelatedImages []RelatedImage `json:"relatedImages,omitempty" hash:"set"` + + // These fields are present so that we can continue serving + // the GRPC API the way packageserver expects us to in a + // backwards-compatible way. These are populated from + // any `olm.bundle.object` properties. + // + // These fields will never be persisted in the bundle blob as + // first class fields. + CsvJSON string `json:"-"` + Objects []string `json:"-"` +} + +type RelatedImage struct { + Name string `json:"name"` + Image string `json:"image"` +} + +type Deprecation struct { + Schema string `json:"schema"` + Package string `json:"package"` + Entries []DeprecationEntry `json:"entries"` +} + +type DeprecationEntry struct { + Reference PackageScopedReference `json:"reference"` + Message string `json:"message"` +} + +type PackageScopedReference struct { + Schema string `json:"schema"` + Name string `json:"name,omitempty"` +} + +type Meta struct { + Schema string + Package string + Name string + + Blob json.RawMessage +} + +func (m Meta) MarshalJSON() ([]byte, error) { + return m.Blob, nil +} + +func (m *Meta) UnmarshalJSON(blob []byte) error { + blobMap := map[string]interface{}{} + if err := json.Unmarshal(blob, &blobMap); err != nil { + // TODO: unfortunately, there are libraries between here and the original caller + // that eat our error type and return a generic error, such that we lose the + // ability to errors.As to get this error on the other side. For now, just return + // a string error that includes the pretty printed message. + return errors.New(prettyunmarshaler.NewJSONUnmarshalError(blob, err).Pretty()) + } + + // TODO: this function ensures we do not break backwards compatibility with + // the documented examples of FBC templates, which use upper camel case + // for JSON field names. We need to decide if we want to continue supporting + // case insensitive JSON field names, or if we want to enforce a specific + // case-sensitive key value for each field. + if err := extractUniqueMetaKeys(blobMap, m); err != nil { + return err + } + + buf := bytes.Buffer{} + enc := json.NewEncoder(&buf) + enc.SetEscapeHTML(false) + if err := enc.Encode(blobMap); err != nil { + return err + } + m.Blob = buf.Bytes() + return nil +} + +// extractUniqueMetaKeys enables a case-insensitive key lookup for the schema, package, and name +// fields of the Meta struct. If the blobMap contains duplicate keys (that is, keys have the same folded value), +// an error is returned. +func extractUniqueMetaKeys(blobMap map[string]any, m *Meta) error { + keySets := map[string]sets.Set[string]{} + folder := cases.Fold() + for key := range blobMap { + foldKey := folder.String(key) + if _, ok := keySets[foldKey]; !ok { + keySets[foldKey] = sets.New[string]() + } + keySets[foldKey].Insert(key) + } + + dupErrs := []error{} + for foldedKey, keys := range keySets { + if len(keys) != 1 { + dupErrs = append(dupErrs, fmt.Errorf("duplicate keys for key %q: %v", foldedKey, sets.List(keys))) + } + } + if len(dupErrs) > 0 { + return utilerrors.NewAggregate(dupErrs) + } + + metaMap := map[string]*string{ + folder.String("schema"): &m.Schema, + folder.String("package"): &m.Package, + folder.String("name"): &m.Name, + } + + for foldedKey, ptr := range metaMap { + // if the folded key doesn't exist in the key set derived from the blobMap, that means + // the key doesn't exist in the blobMap, so we can skip it + if _, ok := keySets[foldedKey]; !ok { + continue + } + + // reset key to the unfolded key, which we know is the one that appears in the blobMap + key := keySets[foldedKey].UnsortedList()[0] + if _, ok := blobMap[key]; !ok { + continue + } + v, ok := blobMap[key].(string) + if !ok { + return fmt.Errorf("expected value for key %q to be a string, got %t: %v", key, blobMap[key], blobMap[key]) + } + *ptr = v + } + return nil +} + +func (destination *DeclarativeConfig) Merge(src *DeclarativeConfig) { + destination.Packages = append(destination.Packages, src.Packages...) + destination.Channels = append(destination.Channels, src.Channels...) + destination.Bundles = append(destination.Bundles, src.Bundles...) + destination.Others = append(destination.Others, src.Others...) + destination.Deprecations = append(destination.Deprecations, src.Deprecations...) +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/declcfg_to_model.go b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/declcfg_to_model.go new file mode 100644 index 0000000000..2657efb16f --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/declcfg_to_model.go @@ -0,0 +1,257 @@ +package declcfg + +import ( + "fmt" + + "github.com/blang/semver/v4" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apimachinery/pkg/util/validation" + + "github.com/operator-framework/operator-registry/alpha/model" + "github.com/operator-framework/operator-registry/alpha/property" +) + +func ConvertToModel(cfg DeclarativeConfig) (model.Model, error) { + mpkgs := model.Model{} + defaultChannels := map[string]string{} + for _, p := range cfg.Packages { + if p.Name == "" { + return nil, fmt.Errorf("config contains package with no name") + } + + if _, ok := mpkgs[p.Name]; ok { + return nil, fmt.Errorf("duplicate package %q", p.Name) + } + + if errs := validation.IsDNS1123Label(p.Name); len(errs) > 0 { + return nil, fmt.Errorf("invalid package name %q: %v", p.Name, errs) + } + + mpkg := &model.Package{ + Name: p.Name, + Description: p.Description, + Channels: map[string]*model.Channel{}, + } + if p.Icon != nil { + mpkg.Icon = &model.Icon{ + Data: p.Icon.Data, + MediaType: p.Icon.MediaType, + } + } + defaultChannels[p.Name] = p.DefaultChannel + mpkgs[p.Name] = mpkg + } + + channelDefinedEntries := map[string]sets.Set[string]{} + for _, c := range cfg.Channels { + mpkg, ok := mpkgs[c.Package] + if !ok { + return nil, fmt.Errorf("unknown package %q for channel %q", c.Package, c.Name) + } + + if c.Name == "" { + return nil, fmt.Errorf("package %q contains channel with no name", c.Package) + } + + if _, ok := mpkg.Channels[c.Name]; ok { + return nil, fmt.Errorf("package %q has duplicate channel %q", c.Package, c.Name) + } + + mch := &model.Channel{ + Package: mpkg, + Name: c.Name, + Bundles: map[string]*model.Bundle{}, + // NOTICE: The field Properties of the type Channel is for internal use only. + // DO NOT use it for any public-facing functionalities. + // This API is in alpha stage and it is subject to change. + Properties: c.Properties, + } + + cde := sets.Set[string]{} + for _, entry := range c.Entries { + if _, ok := mch.Bundles[entry.Name]; ok { + return nil, fmt.Errorf("invalid package %q, channel %q: duplicate entry %q", c.Package, c.Name, entry.Name) + } + cde = cde.Insert(entry.Name) + mch.Bundles[entry.Name] = &model.Bundle{ + Package: mpkg, + Channel: mch, + Name: entry.Name, + Replaces: entry.Replaces, + Skips: entry.Skips, + SkipRange: entry.SkipRange, + } + } + channelDefinedEntries[c.Package] = cde + + mpkg.Channels[c.Name] = mch + + defaultChannelName := defaultChannels[c.Package] + if defaultChannelName == c.Name { + mpkg.DefaultChannel = mch + } + } + + // packageBundles tracks the set of bundle names for each package + // and is used to detect duplicate bundles. + packageBundles := map[string]sets.Set[string]{} + + for _, b := range cfg.Bundles { + if b.Package == "" { + return nil, fmt.Errorf("package name must be set for bundle %q", b.Name) + } + mpkg, ok := mpkgs[b.Package] + if !ok { + return nil, fmt.Errorf("unknown package %q for bundle %q", b.Package, b.Name) + } + + bundles, ok := packageBundles[b.Package] + if !ok { + bundles = sets.Set[string]{} + } + if bundles.Has(b.Name) { + return nil, fmt.Errorf("package %q has duplicate bundle %q", b.Package, b.Name) + } + bundles.Insert(b.Name) + packageBundles[b.Package] = bundles + + props, err := property.Parse(b.Properties) + if err != nil { + return nil, fmt.Errorf("parse properties for bundle %q: %v", b.Name, err) + } + + if len(props.Packages) != 1 { + return nil, fmt.Errorf("package %q bundle %q must have exactly 1 %q property, found %d", b.Package, b.Name, property.TypePackage, len(props.Packages)) + } + + if b.Package != props.Packages[0].PackageName { + return nil, fmt.Errorf("package %q does not match %q property %q", b.Package, property.TypePackage, props.Packages[0].PackageName) + } + + // Parse version from the package property. + rawVersion := props.Packages[0].Version + ver, err := semver.Parse(rawVersion) + if err != nil { + return nil, fmt.Errorf("error parsing bundle %q version %q: %v", b.Name, rawVersion, err) + } + + channelDefinedEntries[b.Package] = channelDefinedEntries[b.Package].Delete(b.Name) + found := false + for _, mch := range mpkg.Channels { + if mb, ok := mch.Bundles[b.Name]; ok { + found = true + mb.Image = b.Image + mb.Properties = b.Properties + mb.RelatedImages = relatedImagesToModelRelatedImages(b.RelatedImages) + mb.CsvJSON = b.CsvJSON + mb.Objects = b.Objects + mb.PropertiesP = props + mb.Version = ver + } + } + if !found { + return nil, fmt.Errorf("package %q, bundle %q not found in any channel entries", b.Package, b.Name) + } + } + + for pkg, entries := range channelDefinedEntries { + if entries.Len() > 0 { + return nil, fmt.Errorf("no olm.bundle blobs found in package %q for olm.channel entries %s", pkg, sets.List[string](entries)) + } + } + + for _, mpkg := range mpkgs { + defaultChannelName := defaultChannels[mpkg.Name] + if defaultChannelName != "" && mpkg.DefaultChannel == nil { + dch := &model.Channel{ + Package: mpkg, + Name: defaultChannelName, + Bundles: map[string]*model.Bundle{}, + } + mpkg.DefaultChannel = dch + mpkg.Channels[dch.Name] = dch + } + } + + // deprecationsByPackage tracks the set of package names + // and is used to detect duplicate packages. + deprecationsByPackage := sets.New[string]() + + for i, deprecation := range cfg.Deprecations { + + // no need to validate schema, since it could not be unmarshaled if missing/invalid + + if deprecation.Package == "" { + return nil, fmt.Errorf("package name must be set for deprecation item %v", i) + } + + // must refer to package in this catalog + mpkg, ok := mpkgs[deprecation.Package] + if !ok { + return nil, fmt.Errorf("cannot apply deprecations to an unknown package %q", deprecation.Package) + } + + // must be unique per package + if deprecationsByPackage.Has(deprecation.Package) { + return nil, fmt.Errorf("expected a maximum of one deprecation per package: %q", deprecation.Package) + } + deprecationsByPackage.Insert(deprecation.Package) + + references := sets.New[PackageScopedReference]() + + for j, entry := range deprecation.Entries { + if entry.Reference.Schema == "" { + return nil, fmt.Errorf("schema must be set for deprecation entry [%v] for package %q", deprecation.Package, j) + } + + if references.Has(entry.Reference) { + return nil, fmt.Errorf("duplicate deprecation entry %#v for package %q", entry.Reference, deprecation.Package) + } + references.Insert(entry.Reference) + + switch entry.Reference.Schema { + case SchemaBundle: + if !packageBundles[deprecation.Package].Has(entry.Reference.Name) { + return nil, fmt.Errorf("cannot deprecate bundle %q for package %q: bundle not found", entry.Reference.Name, deprecation.Package) + } + for _, mch := range mpkg.Channels { + if mb, ok := mch.Bundles[entry.Reference.Name]; ok { + mb.Deprecation = &model.Deprecation{Message: entry.Message} + } + } + case SchemaChannel: + ch, ok := mpkg.Channels[entry.Reference.Name] + if !ok { + return nil, fmt.Errorf("cannot deprecate channel %q for package %q: channel not found", entry.Reference.Name, deprecation.Package) + } + ch.Deprecation = &model.Deprecation{Message: entry.Message} + + case SchemaPackage: + if entry.Reference.Name != "" { + return nil, fmt.Errorf("package name must be empty for deprecated package %q (specified %q)", deprecation.Package, entry.Reference.Name) + } + mpkg.Deprecation = &model.Deprecation{Message: entry.Message} + + default: + return nil, fmt.Errorf("cannot deprecate object %#v referenced by entry %v for package %q: object schema unknown", entry.Reference, j, deprecation.Package) + } + } + } + + if err := mpkgs.Validate(); err != nil { + return nil, err + } + mpkgs.Normalize() + return mpkgs, nil +} + +func relatedImagesToModelRelatedImages(in []RelatedImage) []model.RelatedImage { + var out []model.RelatedImage + for _, p := range in { + out = append(out, model.RelatedImage{ + Name: p.Name, + Image: p.Image, + }) + } + return out +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/load.go b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/load.go new file mode 100644 index 0000000000..8717299a6a --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/load.go @@ -0,0 +1,317 @@ +package declcfg + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "io/fs" + "runtime" + "sync" + + "github.com/joelanford/ignore" + "golang.org/x/sync/errgroup" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/yaml" + + "github.com/operator-framework/api/pkg/operators" + + "github.com/operator-framework/operator-registry/alpha/property" +) + +const ( + indexIgnoreFilename = ".indexignore" +) + +type WalkMetasFSFunc func(path string, meta *Meta, err error) error + +// WalkMetasFS walks the filesystem rooted at root and calls walkFn for each individual meta object found in the root. +// By default, WalkMetasFS is not thread-safe because it invokes walkFn concurrently. In order to make it thread-safe, +// use the WithConcurrency(1) to avoid concurrent invocations of walkFn. +func WalkMetasFS(ctx context.Context, root fs.FS, walkFn WalkMetasFSFunc, opts ...LoadOption) error { + if root == nil { + return fmt.Errorf("no declarative config filesystem provided") + } + + options := LoadOptions{ + concurrency: runtime.NumCPU(), + } + for _, opt := range opts { + opt(&options) + } + + pathChan := make(chan string, options.concurrency) + + // Create an errgroup to manage goroutines. The context is closed when any + // goroutine returns an error. Goroutines should check the context + // to see if they should return early (in the case of another goroutine + // returning an error). + eg, ctx := errgroup.WithContext(ctx) + + // Walk the FS and send paths to a channel for parsing. + eg.Go(func() error { + return sendPaths(ctx, root, pathChan) + }) + + // Parse paths concurrently. The waitgroup ensures that all paths are parsed + // before the cfgChan is closed. + for i := 0; i < options.concurrency; i++ { + eg.Go(func() error { + return parseMetaPaths(ctx, root, pathChan, walkFn, options) + }) + } + return eg.Wait() +} + +type WalkMetasReaderFunc func(meta *Meta, err error) error + +func WalkMetasReader(r io.Reader, walkFn WalkMetasReaderFunc) error { + dec := yaml.NewYAMLOrJSONDecoder(r, 4096) + for { + var in Meta + if err := dec.Decode(&in); err != nil { + if errors.Is(err, io.EOF) { + break + } + return walkFn(nil, err) + } + + if err := walkFn(&in, nil); err != nil { + return err + } + } + return nil +} + +type WalkFunc func(path string, cfg *DeclarativeConfig, err error) error + +// WalkFS walks root using a gitignore-style filename matcher to skip files +// that match patterns found in .indexignore files found throughout the filesystem. +// It calls walkFn for each declarative config file it finds. If WalkFS encounters +// an error loading or parsing any file, the error will be immediately returned. +func WalkFS(root fs.FS, walkFn WalkFunc) error { + return walkFiles(root, func(root fs.FS, path string, err error) error { + if err != nil { + return walkFn(path, nil, err) + } + + cfg, err := LoadFile(root, path) + if err != nil { + return walkFn(path, cfg, err) + } + + return walkFn(path, cfg, nil) + }) +} + +func walkFiles(root fs.FS, fn func(root fs.FS, path string, err error) error) error { + if root == nil { + return fmt.Errorf("no declarative config filesystem provided") + } + + matcher, err := ignore.NewMatcher(root, indexIgnoreFilename) + if err != nil { + return err + } + + return fs.WalkDir(root, ".", func(path string, info fs.DirEntry, err error) error { + if err != nil { + return fn(root, path, err) + } + // avoid validating a directory, an .indexignore file, or any file that matches + // an ignore pattern outlined in a .indexignore file. + if info.IsDir() || info.Name() == indexIgnoreFilename || matcher.Match(path, false) { + return nil + } + + return fn(root, path, nil) + }) +} + +type LoadOptions struct { + concurrency int +} + +type LoadOption func(*LoadOptions) + +func WithConcurrency(concurrency int) LoadOption { + return func(opts *LoadOptions) { + opts.concurrency = concurrency + } +} + +// LoadFS loads a declarative config from the provided root FS. LoadFS walks the +// filesystem from root and uses a gitignore-style filename matcher to skip files +// that match patterns found in .indexignore files found throughout the filesystem. +// If LoadFS encounters an error loading or parsing any file, the error will be +// immediately returned. +func LoadFS(ctx context.Context, root fs.FS, opts ...LoadOption) (*DeclarativeConfig, error) { + builder := fbcBuilder{} + if err := WalkMetasFS(ctx, root, func(path string, meta *Meta, err error) error { + if err != nil { + return err + } + return builder.addMeta(meta) + }, opts...); err != nil { + return nil, err + } + return &builder.cfg, nil +} + +func sendPaths(ctx context.Context, root fs.FS, pathChan chan<- string) error { + defer close(pathChan) + return walkFiles(root, func(_ fs.FS, path string, err error) error { + if err != nil { + return err + } + select { + case pathChan <- path: + case <-ctx.Done(): // don't block on sending to pathChan + return ctx.Err() + } + return nil + }) +} + +func parseMetaPaths(ctx context.Context, root fs.FS, pathChan <-chan string, walkFn WalkMetasFSFunc, options LoadOptions) error { + for { + select { + case <-ctx.Done(): // don't block on receiving from pathChan + return ctx.Err() + case path, ok := <-pathChan: + if !ok { + return nil + } + file, err := root.Open(path) + if err != nil { + return err + } + if err := WalkMetasReader(file, func(meta *Meta, err error) error { + return walkFn(path, meta, err) + }); err != nil { + return err + } + } + } +} + +func readBundleObjects(b *Bundle) error { + var obj property.BundleObject + for i, props := range b.Properties { + if props.Type != property.TypeBundleObject { + continue + } + if err := json.Unmarshal(props.Value, &obj); err != nil { + return fmt.Errorf("package %q, bundle %q: parse property at index %d as bundle object: %v", b.Package, b.Name, i, err) + } + objJson, err := yaml.ToJSON(obj.Data) + if err != nil { + return fmt.Errorf("package %q, bundle %q: convert bundle object property at index %d to JSON: %v", b.Package, b.Name, i, err) + } + b.Objects = append(b.Objects, string(objJson)) + } + b.CsvJSON = extractCSV(b.Objects) + return nil +} + +func extractCSV(objs []string) string { + for _, obj := range objs { + u := unstructured.Unstructured{} + if err := yaml.Unmarshal([]byte(obj), &u); err != nil { + continue + } + if u.GetKind() == operators.ClusterServiceVersionKind { + return obj + } + } + return "" +} + +// LoadReader reads yaml or json from the passed in io.Reader and unmarshals it into a DeclarativeConfig struct. +func LoadReader(r io.Reader) (*DeclarativeConfig, error) { + builder := fbcBuilder{} + if err := WalkMetasReader(r, func(meta *Meta, err error) error { + if err != nil { + return err + } + return builder.addMeta(meta) + }); err != nil { + return nil, err + } + return &builder.cfg, nil +} + +// LoadFile will unmarshall declarative config components from a single filename provided in 'path' +// located at a filesystem hierarchy 'root' +func LoadFile(root fs.FS, path string) (*DeclarativeConfig, error) { + file, err := root.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + + cfg, err := LoadReader(file) + if err != nil { + return nil, err + } + + return cfg, nil +} + +type fbcBuilder struct { + cfg DeclarativeConfig + + packagesMu sync.Mutex + channelsMu sync.Mutex + bundlesMu sync.Mutex + deprecationsMu sync.Mutex + othersMu sync.Mutex +} + +func (c *fbcBuilder) addMeta(in *Meta) error { + switch in.Schema { + case SchemaPackage: + var p Package + if err := json.Unmarshal(in.Blob, &p); err != nil { + return fmt.Errorf("parse package: %v", err) + } + c.packagesMu.Lock() + c.cfg.Packages = append(c.cfg.Packages, p) + c.packagesMu.Unlock() + case SchemaChannel: + var ch Channel + if err := json.Unmarshal(in.Blob, &ch); err != nil { + return fmt.Errorf("parse channel: %v", err) + } + c.channelsMu.Lock() + c.cfg.Channels = append(c.cfg.Channels, ch) + c.channelsMu.Unlock() + case SchemaBundle: + var b Bundle + if err := json.Unmarshal(in.Blob, &b); err != nil { + return fmt.Errorf("parse bundle: %v", err) + } + if err := readBundleObjects(&b); err != nil { + return fmt.Errorf("read bundle objects: %v", err) + } + c.bundlesMu.Lock() + c.cfg.Bundles = append(c.cfg.Bundles, b) + c.bundlesMu.Unlock() + case SchemaDeprecation: + var d Deprecation + if err := json.Unmarshal(in.Blob, &d); err != nil { + return fmt.Errorf("parse deprecation: %w", err) + } + c.deprecationsMu.Lock() + c.cfg.Deprecations = append(c.cfg.Deprecations, d) + c.deprecationsMu.Unlock() + case "": + return fmt.Errorf("object '%s' is missing root schema field", string(in.Blob)) + default: + c.othersMu.Lock() + c.cfg.Others = append(c.cfg.Others, *in) + c.othersMu.Unlock() + } + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/model_to_declcfg.go b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/model_to_declcfg.go new file mode 100644 index 0000000000..14424d9f0f --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/model_to_declcfg.go @@ -0,0 +1,131 @@ +package declcfg + +import ( + "sort" + + "github.com/operator-framework/operator-registry/alpha/model" + "github.com/operator-framework/operator-registry/alpha/property" +) + +func ConvertFromModel(mpkgs model.Model) DeclarativeConfig { + cfg := DeclarativeConfig{} + for _, mpkg := range mpkgs { + channels, bundles := traverseModelChannels(*mpkg) + + var i *Icon + if mpkg.Icon != nil { + i = &Icon{ + Data: mpkg.Icon.Data, + MediaType: mpkg.Icon.MediaType, + } + } + defaultChannel := "" + if mpkg.DefaultChannel != nil { + defaultChannel = mpkg.DefaultChannel.Name + } + cfg.Packages = append(cfg.Packages, Package{ + Schema: SchemaPackage, + Name: mpkg.Name, + DefaultChannel: defaultChannel, + Icon: i, + Description: mpkg.Description, + }) + cfg.Channels = append(cfg.Channels, channels...) + cfg.Bundles = append(cfg.Bundles, bundles...) + } + + sort.Slice(cfg.Packages, func(i, j int) bool { + return cfg.Packages[i].Name < cfg.Packages[j].Name + }) + sort.Slice(cfg.Channels, func(i, j int) bool { + if cfg.Channels[i].Package != cfg.Channels[j].Package { + return cfg.Channels[i].Package < cfg.Channels[j].Package + } + return cfg.Channels[i].Name < cfg.Channels[j].Name + }) + sort.Slice(cfg.Bundles, func(i, j int) bool { + if cfg.Bundles[i].Package != cfg.Bundles[j].Package { + return cfg.Bundles[i].Package < cfg.Bundles[j].Package + } + return cfg.Bundles[i].Name < cfg.Bundles[j].Name + }) + + return cfg +} + +func traverseModelChannels(mpkg model.Package) ([]Channel, []Bundle) { + channels := []Channel{} + bundleMap := map[string]*Bundle{} + + for _, ch := range mpkg.Channels { + // initialize channel + c := Channel{ + Schema: SchemaChannel, + Name: ch.Name, + Package: ch.Package.Name, + Entries: []ChannelEntry{}, + // NOTICE: The field Properties of the type Channel is for internal use only. + // DO NOT use it for any public-facing functionalities. + // This API is in alpha stage and it is subject to change. + Properties: ch.Properties, + } + + for _, chb := range ch.Bundles { + // populate channel entry + c.Entries = append(c.Entries, ChannelEntry{ + Name: chb.Name, + Replaces: chb.Replaces, + Skips: chb.Skips, + SkipRange: chb.SkipRange, + }) + + // create or update bundle + b, ok := bundleMap[chb.Name] + if !ok { + b = &Bundle{ + Schema: SchemaBundle, + Name: chb.Name, + Package: chb.Package.Name, + Image: chb.Image, + RelatedImages: ModelRelatedImagesToRelatedImages(chb.RelatedImages), + CsvJSON: chb.CsvJSON, + Objects: chb.Objects, + } + bundleMap[b.Name] = b + } + b.Properties = append(b.Properties, chb.Properties...) + } + + // sort channel entries by name + sort.Slice(c.Entries, func(i, j int) bool { + return c.Entries[i].Name < c.Entries[j].Name + }) + channels = append(channels, c) + } + + var bundles []Bundle + for _, b := range bundleMap { + b.Properties = property.Deduplicate(b.Properties) + + sort.Slice(b.Properties, func(i, j int) bool { + if b.Properties[i].Type != b.Properties[j].Type { + return b.Properties[i].Type < b.Properties[j].Type + } + return string(b.Properties[i].Value) < string(b.Properties[j].Value) + }) + + bundles = append(bundles, *b) + } + return channels, bundles +} + +func ModelRelatedImagesToRelatedImages(relatedImages []model.RelatedImage) []RelatedImage { + var out []RelatedImage + for _, ri := range relatedImages { + out = append(out, RelatedImage{ + Name: ri.Name, + Image: ri.Image, + }) + } + return out +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/write.go b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/write.go new file mode 100644 index 0000000000..9856c2e1ee --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/write.go @@ -0,0 +1,542 @@ +package declcfg + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "os" + "path/filepath" + "sort" + "strings" + + "github.com/blang/semver/v4" + "k8s.io/apimachinery/pkg/util/sets" + "sigs.k8s.io/yaml" + + "github.com/operator-framework/operator-registry/alpha/property" +) + +type MermaidWriter struct { + MinEdgeName string + SpecifiedPackageName string +} + +type MermaidOption func(*MermaidWriter) + +func NewMermaidWriter(opts ...MermaidOption) *MermaidWriter { + const ( + minEdgeName = "" + specifiedPackageName = "" + ) + m := &MermaidWriter{ + MinEdgeName: minEdgeName, + SpecifiedPackageName: specifiedPackageName, + } + + for _, opt := range opts { + opt(m) + } + return m +} + +func WithMinEdgeName(minEdgeName string) MermaidOption { + return func(o *MermaidWriter) { + o.MinEdgeName = minEdgeName + } +} + +func WithSpecifiedPackageName(specifiedPackageName string) MermaidOption { + return func(o *MermaidWriter) { + o.SpecifiedPackageName = specifiedPackageName + } +} + +// writes out the channel edges of the declarative config graph in a mermaid format capable of being pasted into +// mermaid renderers like github, mermaid.live, etc. +// output is sorted lexicographically by package name, and then by channel name +// if provided, minEdgeName will be used as the lower bound for edges in the output graph +// +// Example output: +// graph LR +// +// %% package "neuvector-certified-operator-rhmp" +// subgraph "neuvector-certified-operator-rhmp" +// %% channel "beta" +// subgraph neuvector-certified-operator-rhmp-beta["beta"] +// neuvector-certified-operator-rhmp-beta-neuvector-operator.v1.2.8["neuvector-operator.v1.2.8"] +// neuvector-certified-operator-rhmp-beta-neuvector-operator.v1.2.9["neuvector-operator.v1.2.9"] +// neuvector-certified-operator-rhmp-beta-neuvector-operator.v1.3.0["neuvector-operator.v1.3.0"] +// neuvector-certified-operator-rhmp-beta-neuvector-operator.v1.3.0["neuvector-operator.v1.3.0"]-- replaces --> neuvector-certified-operator-rhmp-beta-neuvector-operator.v1.2.8["neuvector-operator.v1.2.8"] +// neuvector-certified-operator-rhmp-beta-neuvector-operator.v1.3.0["neuvector-operator.v1.3.0"]-- skips --> neuvector-certified-operator-rhmp-beta-neuvector-operator.v1.2.9["neuvector-operator.v1.2.9"] +// end +// end +// +// end +func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) error { + pkgs := map[string]*strings.Builder{} + + sort.Slice(cfg.Channels, func(i, j int) bool { + return cfg.Channels[i].Name < cfg.Channels[j].Name + }) + + versionMap, err := getBundleVersions(&cfg) + if err != nil { + return err + } + + // establish a 'floor' version, either specified by user or entirely open + minVersion := semver.Version{Major: 0, Minor: 0, Patch: 0} + + if writer.MinEdgeName != "" { + if _, ok := versionMap[writer.MinEdgeName]; !ok { + return fmt.Errorf("unknown minimum edge name: %q", writer.MinEdgeName) + } + minVersion = versionMap[writer.MinEdgeName] + } + + // build increasing-version-ordered bundle names, so we can meaningfully iterate over a range + orderedBundles := []string{} + for n := range versionMap { + orderedBundles = append(orderedBundles, n) + } + sort.Slice(orderedBundles, func(i, j int) bool { + return versionMap[orderedBundles[i]].LT(versionMap[orderedBundles[j]]) + }) + + minEdgePackage := writer.getMinEdgePackage(&cfg) + + depByPackage := sets.Set[string]{} + depByChannel := sets.Set[string]{} + depByBundle := sets.Set[string]{} + + for _, d := range cfg.Deprecations { + for _, e := range d.Entries { + switch e.Reference.Schema { + case SchemaPackage: + depByPackage.Insert(d.Package) + case SchemaChannel: + depByChannel.Insert(e.Reference.Name) + case SchemaBundle: + depByBundle.Insert(e.Reference.Name) + } + } + } + + var deprecatedPackage string + deprecatedChannels := []string{} + + for _, c := range cfg.Channels { + filteredChannel := writer.filterChannel(&c, versionMap, minVersion, minEdgePackage) + if filteredChannel != nil { + pkgBuilder, ok := pkgs[c.Package] + if !ok { + pkgBuilder = &strings.Builder{} + pkgs[c.Package] = pkgBuilder + } + + channelID := fmt.Sprintf("%s-%s", filteredChannel.Package, filteredChannel.Name) + pkgBuilder.WriteString(fmt.Sprintf(" %%%% channel %q\n", filteredChannel.Name)) + pkgBuilder.WriteString(fmt.Sprintf(" subgraph %s[%q]\n", channelID, filteredChannel.Name)) + + if depByPackage.Has(filteredChannel.Package) { + deprecatedPackage = filteredChannel.Package + } + + if depByChannel.Has(filteredChannel.Name) { + deprecatedChannels = append(deprecatedChannels, channelID) + } + + for _, ce := range filteredChannel.Entries { + if versionMap[ce.Name].GE(minVersion) { + bundleDeprecation := "" + if depByBundle.Has(ce.Name) { + bundleDeprecation = ":::deprecated" + } + + entryId := fmt.Sprintf("%s-%s", channelID, ce.Name) + pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]%s\n", entryId, ce.Name, bundleDeprecation)) + + if len(ce.Replaces) > 0 { + replacesId := fmt.Sprintf("%s-%s", channelID, ce.Replaces) + pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- %s --> %s[%q]\n", replacesId, ce.Replaces, "replace", entryId, ce.Name)) + } + if len(ce.Skips) > 0 { + for _, s := range ce.Skips { + skipsId := fmt.Sprintf("%s-%s", channelID, s) + pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- %s --> %s[%q]\n", skipsId, s, "skip", entryId, ce.Name)) + } + } + if len(ce.SkipRange) > 0 { + skipRange, err := semver.ParseRange(ce.SkipRange) + if err == nil { + for _, edgeName := range filteredChannel.Entries { + if skipRange(versionMap[edgeName.Name]) { + skipRangeId := fmt.Sprintf("%s-%s", channelID, edgeName.Name) + pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- \"%s(%s)\" --> %s[%q]\n", skipRangeId, edgeName.Name, "skipRange", ce.SkipRange, entryId, ce.Name)) + } + } + } else { + fmt.Fprintf(os.Stderr, "warning: ignoring invalid SkipRange for package/edge %q/%q: %v\n", c.Package, ce.Name, err) + } + } + } + } + pkgBuilder.WriteString(" end\n") + } + } + + out.Write([]byte("graph LR\n")) + out.Write([]byte(fmt.Sprintf(" classDef deprecated fill:#E8960F\n"))) + pkgNames := []string{} + for pname := range pkgs { + pkgNames = append(pkgNames, pname) + } + sort.Slice(pkgNames, func(i, j int) bool { + return pkgNames[i] < pkgNames[j] + }) + for _, pkgName := range pkgNames { + out.Write([]byte(fmt.Sprintf(" %%%% package %q\n", pkgName))) + out.Write([]byte(fmt.Sprintf(" subgraph %q\n", pkgName))) + out.Write([]byte(pkgs[pkgName].String())) + out.Write([]byte(" end\n")) + } + + if deprecatedPackage != "" { + out.Write([]byte(fmt.Sprintf("style %s fill:#989695\n", deprecatedPackage))) + } + + if len(deprecatedChannels) > 0 { + for _, deprecatedChannel := range deprecatedChannels { + out.Write([]byte(fmt.Sprintf("style %s fill:#DCD0FF\n", deprecatedChannel))) + } + } + + return nil +} + +// filters the channel edges to include only those which are greater-than-or-equal to the edge named by startVersion +// returns a nil channel if all edges are filtered out +func (writer *MermaidWriter) filterChannel(c *Channel, versionMap map[string]semver.Version, minVersion semver.Version, minEdgePackage string) *Channel { + // short-circuit if no active filters + if writer.MinEdgeName == "" && writer.SpecifiedPackageName == "" { + return c + } + + // short-circuit if channel's package doesn't match filter + if writer.SpecifiedPackageName != "" && c.Package != writer.SpecifiedPackageName { + return nil + } + + // short-circuit if channel package is mismatch from filter + if minEdgePackage != "" && c.Package != minEdgePackage { + return nil + } + + out := &Channel{Name: c.Name, Package: c.Package, Properties: c.Properties, Entries: []ChannelEntry{}} + for _, ce := range c.Entries { + filteredCe := ChannelEntry{Name: ce.Name} + if writer.MinEdgeName == "" { + // no minimum-edge specified + filteredCe.SkipRange = ce.SkipRange + filteredCe.Replaces = ce.Replaces + filteredCe.Skips = append(filteredCe.Skips, ce.Skips...) + + // accumulate IFF there are any relevant skips/skipRange/replaces remaining or there never were any to begin with + // for the case where all skip/skipRange/replaces are retained, this is effectively the original edge with validated linkages + if len(filteredCe.Replaces) > 0 || len(filteredCe.Skips) > 0 || len(filteredCe.SkipRange) > 0 { + out.Entries = append(out.Entries, filteredCe) + } else { + if len(ce.Replaces) == 0 && len(ce.SkipRange) == 0 && len(ce.Skips) == 0 { + out.Entries = append(out.Entries, filteredCe) + } + } + } else { + if ce.Name == writer.MinEdgeName { + // edge is the 'floor', meaning that since all references are "backward references", and we don't want any references from this edge + // accumulate w/o references + out.Entries = append(out.Entries, filteredCe) + } else { + // edge needs to be filtered to determine if it is below the floor (bad) or on/above (good) + if len(ce.Replaces) > 0 && versionMap[ce.Replaces].GTE(minVersion) { + filteredCe.Replaces = ce.Replaces + } + if len(ce.Skips) > 0 { + filteredSkips := []string{} + for _, s := range ce.Skips { + if versionMap[s].GTE(minVersion) { + filteredSkips = append(filteredSkips, s) + } + } + if len(filteredSkips) > 0 { + filteredCe.Skips = filteredSkips + } + } + if len(ce.SkipRange) > 0 { + skipRange, err := semver.ParseRange(ce.SkipRange) + // if skipRange can't be parsed, just don't filter based on it + if err == nil && skipRange(minVersion) { + // specified range includes our floor + filteredCe.SkipRange = ce.SkipRange + } + } + // accumulate IFF there are any relevant skips/skipRange/replaces remaining, or there never were any to begin with (NOP) + // but the edge name satisfies the minimum-edge constraint + // for the case where all skip/skipRange/replaces are retained, this is effectively `ce` but with validated linkages + if len(filteredCe.Replaces) > 0 || len(filteredCe.Skips) > 0 || len(filteredCe.SkipRange) > 0 { + out.Entries = append(out.Entries, filteredCe) + } else { + if len(ce.Replaces) == 0 && len(ce.SkipRange) == 0 && len(ce.Skips) == 0 && versionMap[filteredCe.Name].GTE(minVersion) { + out.Entries = append(out.Entries, filteredCe) + } + } + } + } + } + + if len(out.Entries) > 0 { + return out + } else { + return nil + } +} + +func parseVersionProperty(b *Bundle) (*semver.Version, error) { + props, err := property.Parse(b.Properties) + if err != nil { + return nil, fmt.Errorf("parse properties for bundle %q: %v", b.Name, err) + } + if len(props.Packages) != 1 { + return nil, fmt.Errorf("bundle %q has multiple %q properties, expected exactly 1", b.Name, property.TypePackage) + } + v, err := semver.Parse(props.Packages[0].Version) + if err != nil { + return nil, fmt.Errorf("bundle %q has invalid version %q: %v", b.Name, props.Packages[0].Version, err) + } + + return &v, nil +} + +func getBundleVersions(cfg *DeclarativeConfig) (map[string]semver.Version, error) { + entries := make(map[string]semver.Version) + for index := range cfg.Bundles { + if _, ok := entries[cfg.Bundles[index].Name]; !ok { + ver, err := parseVersionProperty(&cfg.Bundles[index]) + if err != nil { + return entries, err + } + entries[cfg.Bundles[index].Name] = *ver + } + } + + return entries, nil +} + +func (writer *MermaidWriter) getMinEdgePackage(cfg *DeclarativeConfig) string { + if writer.MinEdgeName == "" { + return "" + } + + for _, c := range cfg.Channels { + for _, ce := range c.Entries { + if writer.MinEdgeName == ce.Name { + return c.Package + } + } + } + + return "" +} + +func WriteJSON(cfg DeclarativeConfig, w io.Writer) error { + enc := json.NewEncoder(w) + enc.SetIndent("", " ") + enc.SetEscapeHTML(false) + return writeToEncoder(cfg, enc) +} + +func WriteYAML(cfg DeclarativeConfig, w io.Writer) error { + enc := newYAMLEncoder(w) + enc.SetEscapeHTML(false) + return writeToEncoder(cfg, enc) +} + +type yamlEncoder struct { + w io.Writer + escapeHTML bool +} + +func newYAMLEncoder(w io.Writer) *yamlEncoder { + return &yamlEncoder{w, true} +} + +func (e *yamlEncoder) SetEscapeHTML(on bool) { + e.escapeHTML = on +} + +func (e *yamlEncoder) Encode(v interface{}) error { + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + enc.SetEscapeHTML(e.escapeHTML) + if err := enc.Encode(v); err != nil { + return err + } + yamlData, err := yaml.JSONToYAML(buf.Bytes()) + if err != nil { + return err + } + yamlData = append([]byte("---\n"), yamlData...) + _, err = e.w.Write(yamlData) + return err +} + +type encoder interface { + Encode(interface{}) error +} + +func writeToEncoder(cfg DeclarativeConfig, enc encoder) error { + pkgNames := sets.NewString() + + packagesByName := map[string][]Package{} + for _, p := range cfg.Packages { + pkgName := p.Name + pkgNames.Insert(pkgName) + packagesByName[pkgName] = append(packagesByName[pkgName], p) + } + channelsByPackage := map[string][]Channel{} + for _, c := range cfg.Channels { + pkgName := c.Package + pkgNames.Insert(pkgName) + channelsByPackage[pkgName] = append(channelsByPackage[pkgName], c) + } + bundlesByPackage := map[string][]Bundle{} + for _, b := range cfg.Bundles { + pkgName := b.Package + pkgNames.Insert(pkgName) + bundlesByPackage[pkgName] = append(bundlesByPackage[pkgName], b) + } + othersByPackage := map[string][]Meta{} + for _, o := range cfg.Others { + pkgName := o.Package + pkgNames.Insert(pkgName) + othersByPackage[pkgName] = append(othersByPackage[pkgName], o) + } + deprecationsByPackage := map[string][]Deprecation{} + for _, d := range cfg.Deprecations { + pkgName := d.Package + pkgNames.Insert(pkgName) + deprecationsByPackage[pkgName] = append(deprecationsByPackage[pkgName], d) + } + + for _, pName := range pkgNames.List() { + if len(pName) == 0 { + continue + } + pkgs := packagesByName[pName] + for _, p := range pkgs { + if err := enc.Encode(p); err != nil { + return err + } + } + + channels := channelsByPackage[pName] + sort.Slice(channels, func(i, j int) bool { + return channels[i].Name < channels[j].Name + }) + for _, c := range channels { + if err := enc.Encode(c); err != nil { + return err + } + } + + bundles := bundlesByPackage[pName] + sort.Slice(bundles, func(i, j int) bool { + return bundles[i].Name < bundles[j].Name + }) + for _, b := range bundles { + if err := enc.Encode(b); err != nil { + return err + } + } + + others := othersByPackage[pName] + sort.SliceStable(others, func(i, j int) bool { + return others[i].Schema < others[j].Schema + }) + for _, o := range others { + if err := enc.Encode(o); err != nil { + return err + } + } + + // + // Normally we would order the deprecations, but it really doesn't make sense since + // - there will be 0 or 1 of them for any given package + // - they have no other useful field for ordering + // + // validation is typically via conversion to a model.Model and invoking model.Package.Validate() + // It's possible that a user of the object could create a slice containing more then 1 + // Deprecation object for a package, and it would bypass validation if this + // function gets called without conversion. + // + deprecations := deprecationsByPackage[pName] + for _, d := range deprecations { + if err := enc.Encode(d); err != nil { + return err + } + } + } + + for _, o := range othersByPackage[""] { + if err := enc.Encode(o); err != nil { + return err + } + } + + return nil +} + +type WriteFunc func(config DeclarativeConfig, w io.Writer) error + +func WriteFS(cfg DeclarativeConfig, rootDir string, writeFunc WriteFunc, fileExt string) error { + channelsByPackage := map[string][]Channel{} + for _, c := range cfg.Channels { + channelsByPackage[c.Package] = append(channelsByPackage[c.Package], c) + } + bundlesByPackage := map[string][]Bundle{} + for _, b := range cfg.Bundles { + bundlesByPackage[b.Package] = append(bundlesByPackage[b.Package], b) + } + + if err := os.MkdirAll(rootDir, 0777); err != nil { + return err + } + + for _, p := range cfg.Packages { + fcfg := DeclarativeConfig{ + Packages: []Package{p}, + Channels: channelsByPackage[p.Name], + Bundles: bundlesByPackage[p.Name], + } + pkgDir := filepath.Join(rootDir, p.Name) + if err := os.MkdirAll(pkgDir, 0777); err != nil { + return err + } + filename := filepath.Join(pkgDir, fmt.Sprintf("catalog%s", fileExt)) + if err := writeFile(fcfg, filename, writeFunc); err != nil { + return err + } + } + return nil +} + +func writeFile(cfg DeclarativeConfig, filename string, writeFunc WriteFunc) error { + buf := &bytes.Buffer{} + if err := writeFunc(cfg, buf); err != nil { + return fmt.Errorf("write to buffer for %q: %v", filename, err) + } + if err := os.WriteFile(filename, buf.Bytes(), 0666); err != nil { + return fmt.Errorf("write file %q: %v", filename, err) + } + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/template/basic/basic.go b/vendor/github.com/operator-framework/operator-registry/alpha/template/basic/basic.go new file mode 100644 index 0000000000..18566fbcf2 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/template/basic/basic.go @@ -0,0 +1,50 @@ +package basic + +import ( + "context" + "fmt" + "io" + + "github.com/operator-framework/operator-registry/alpha/action" + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/pkg/image" +) + +type Template struct { + Registry image.Registry +} + +func (t Template) Render(ctx context.Context, reader io.Reader) (*declcfg.DeclarativeConfig, error) { + cfg, err := declcfg.LoadReader(reader) + if err != nil { + return cfg, err + } + + outb := cfg.Bundles[:0] // allocate based on max size of input, but empty slice + // populate registry, incl any flags from CLI, and enforce only rendering bundle images + r := action.Render{ + Registry: t.Registry, + AllowedRefMask: action.RefBundleImage, + } + + for _, b := range cfg.Bundles { + if !isBundleTemplate(&b) { + return nil, fmt.Errorf("unexpected fields present in basic template bundle") + } + r.Refs = []string{b.Image} + contributor, err := r.Run(ctx) + if err != nil { + return nil, err + } + outb = append(outb, contributor.Bundles...) + } + + cfg.Bundles = outb + return cfg, nil +} + +// isBundleTemplate identifies a Bundle template source as having a Schema and Image defined +// but no Properties, RelatedImages or Package defined +func isBundleTemplate(b *declcfg.Bundle) bool { + return b.Schema != "" && b.Image != "" && b.Package == "" && len(b.Properties) == 0 && len(b.RelatedImages) == 0 +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/builder.go b/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/builder.go new file mode 100644 index 0000000000..e22b5e49c7 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/builder.go @@ -0,0 +1,363 @@ +package composite + +import ( + "bytes" + "context" + "fmt" + "io" + "os" + "os/exec" + "path" + "path/filepath" + "strings" + + "sigs.k8s.io/yaml" + + "github.com/operator-framework/operator-registry/alpha/declcfg" + basictemplate "github.com/operator-framework/operator-registry/alpha/template/basic" + semvertemplate "github.com/operator-framework/operator-registry/alpha/template/semver" + "github.com/operator-framework/operator-registry/pkg/image" + "github.com/operator-framework/operator-registry/pkg/lib/config" +) + +const ( + BasicBuilderSchema = "olm.builder.basic" + SemverBuilderSchema = "olm.builder.semver" + RawBuilderSchema = "olm.builder.raw" + CustomBuilderSchema = "olm.builder.custom" +) + +type BuilderConfig struct { + WorkingDir string + OutputType string + ContributionPath string +} + +type Builder interface { + Build(ctx context.Context, reg image.Registry, dir string, td TemplateDefinition) error + Validate(ctx context.Context, dir string) error +} + +type BasicBuilder struct { + builderCfg BuilderConfig +} + +var _ Builder = &BasicBuilder{} + +func NewBasicBuilder(builderCfg BuilderConfig) *BasicBuilder { + return &BasicBuilder{ + builderCfg: builderCfg, + } +} + +func (bb *BasicBuilder) Build(ctx context.Context, reg image.Registry, dir string, td TemplateDefinition) error { + if td.Schema != BasicBuilderSchema { + return fmt.Errorf("schema %q does not match the basic template builder schema %q", td.Schema, BasicBuilderSchema) + } + // Parse out the basic template configuration + basicConfig := &BasicConfig{} + err := yaml.UnmarshalStrict(td.Config, basicConfig) + if err != nil { + return fmt.Errorf("unmarshalling basic template config: %w", err) + } + + // validate the basic config fields + valid := true + validationErrs := []string{} + if basicConfig.Input == "" { + valid = false + validationErrs = append(validationErrs, "basic template config must have a non-empty input (templateDefinition.config.input)") + } + + if basicConfig.Output == "" { + valid = false + validationErrs = append(validationErrs, "basic template config must have a non-empty output (templateDefinition.config.output)") + } + + if !valid { + return fmt.Errorf("basic template configuration is invalid: %s", strings.Join(validationErrs, ",")) + } + + b := basictemplate.Template{Registry: reg} + reader, err := os.Open(basicConfig.Input) + if err != nil { + if os.IsNotExist(err) && bb.builderCfg.ContributionPath != "" { + reader, err = os.Open(path.Join(bb.builderCfg.ContributionPath, basicConfig.Input)) + if err != nil { + return fmt.Errorf("error reading basic template: %v (tried contribution-local path: %q)", err, bb.builderCfg.ContributionPath) + } + } else { + return fmt.Errorf("error reading basic template: %v", err) + } + } + defer reader.Close() + + dcfg, err := b.Render(ctx, reader) + if err != nil { + return fmt.Errorf("error rendering basic template: %v", err) + } + + destPath := path.Join(bb.builderCfg.WorkingDir, dir, basicConfig.Output) + + return build(dcfg, destPath, bb.builderCfg.OutputType) +} + +func (bb *BasicBuilder) Validate(ctx context.Context, dir string) error { + return validate(ctx, bb.builderCfg, dir) +} + +type SemverBuilder struct { + builderCfg BuilderConfig +} + +var _ Builder = &SemverBuilder{} + +func NewSemverBuilder(builderCfg BuilderConfig) *SemverBuilder { + return &SemverBuilder{ + builderCfg: builderCfg, + } +} + +func (sb *SemverBuilder) Build(ctx context.Context, reg image.Registry, dir string, td TemplateDefinition) error { + if td.Schema != SemverBuilderSchema { + return fmt.Errorf("schema %q does not match the semver template builder schema %q", td.Schema, SemverBuilderSchema) + } + // Parse out the semver template configuration + semverConfig := &SemverConfig{} + err := yaml.UnmarshalStrict(td.Config, semverConfig) + if err != nil { + return fmt.Errorf("unmarshalling semver template config: %w", err) + } + + // validate the semver config fields + valid := true + validationErrs := []string{} + if semverConfig.Input == "" { + valid = false + validationErrs = append(validationErrs, "semver template config must have a non-empty input (templateDefinition.config.input)") + } + + if semverConfig.Output == "" { + valid = false + validationErrs = append(validationErrs, "semver template config must have a non-empty output (templateDefinition.config.output)") + } + + if !valid { + return fmt.Errorf("semver template configuration is invalid: %s", strings.Join(validationErrs, ",")) + } + + reader, err := os.Open(semverConfig.Input) + if err != nil { + if os.IsNotExist(err) && sb.builderCfg.ContributionPath != "" { + reader, err = os.Open(path.Join(sb.builderCfg.ContributionPath, semverConfig.Input)) + if err != nil { + return fmt.Errorf("error reading semver template: %v (tried contribution-local path: %q)", err, sb.builderCfg.ContributionPath) + } + } else { + return fmt.Errorf("error reading semver template: %v", err) + } + } + defer reader.Close() + + s := semvertemplate.Template{Registry: reg, Data: reader} + + dcfg, err := s.Render(ctx) + if err != nil { + return fmt.Errorf("error rendering semver template: %v", err) + } + + destPath := path.Join(sb.builderCfg.WorkingDir, dir, semverConfig.Output) + + return build(dcfg, destPath, sb.builderCfg.OutputType) +} + +func (sb *SemverBuilder) Validate(ctx context.Context, dir string) error { + return validate(ctx, sb.builderCfg, dir) +} + +type RawBuilder struct { + builderCfg BuilderConfig +} + +var _ Builder = &RawBuilder{} + +func NewRawBuilder(builderCfg BuilderConfig) *RawBuilder { + return &RawBuilder{ + builderCfg: builderCfg, + } +} + +func (rb *RawBuilder) Build(ctx context.Context, _ image.Registry, dir string, td TemplateDefinition) error { + if td.Schema != RawBuilderSchema { + return fmt.Errorf("schema %q does not match the raw template builder schema %q", td.Schema, RawBuilderSchema) + } + // Parse out the raw template configuration + rawConfig := &RawConfig{} + err := yaml.UnmarshalStrict(td.Config, rawConfig) + if err != nil { + return fmt.Errorf("unmarshalling raw template config: %w", err) + } + + // validate the raw config fields + valid := true + validationErrs := []string{} + if rawConfig.Input == "" { + valid = false + validationErrs = append(validationErrs, "raw template config must have a non-empty input (templateDefinition.config.input)") + } + + if rawConfig.Output == "" { + valid = false + validationErrs = append(validationErrs, "raw template config must have a non-empty output (templateDefinition.config.output)") + } + + if !valid { + return fmt.Errorf("raw template configuration is invalid: %s", strings.Join(validationErrs, ",")) + } + + reader, err := os.Open(rawConfig.Input) + if err != nil { + if os.IsNotExist(err) && rb.builderCfg.ContributionPath != "" { + reader, err = os.Open(path.Join(rb.builderCfg.ContributionPath, rawConfig.Input)) + if err != nil { + return fmt.Errorf("error reading raw input file: %v (tried contribution-local path: %q)", err, rb.builderCfg.ContributionPath) + } + } else { + return fmt.Errorf("error reading raw input file: %v", err) + } + } + defer reader.Close() + + dcfg, err := declcfg.LoadReader(reader) + if err != nil { + return fmt.Errorf("error parsing raw input file: %s, %v", rawConfig.Input, err) + } + + destPath := path.Join(rb.builderCfg.WorkingDir, dir, rawConfig.Output) + + return build(dcfg, destPath, rb.builderCfg.OutputType) +} + +func (rb *RawBuilder) Validate(ctx context.Context, dir string) error { + return validate(ctx, rb.builderCfg, dir) +} + +type CustomBuilder struct { + builderCfg BuilderConfig +} + +var _ Builder = &CustomBuilder{} + +func NewCustomBuilder(builderCfg BuilderConfig) *CustomBuilder { + return &CustomBuilder{ + builderCfg: builderCfg, + } +} + +func (cb *CustomBuilder) Build(ctx context.Context, reg image.Registry, dir string, td TemplateDefinition) error { + if td.Schema != CustomBuilderSchema { + return fmt.Errorf("schema %q does not match the custom template builder schema %q", td.Schema, CustomBuilderSchema) + } + // Parse out the raw template configuration + customConfig := &CustomConfig{} + err := yaml.UnmarshalStrict(td.Config, customConfig) + if err != nil { + return fmt.Errorf("unmarshalling custom template config: %w", err) + } + + // validate the custom config fields + valid := true + validationErrs := []string{} + if customConfig.Command == "" { + valid = false + validationErrs = append(validationErrs, "custom template config must have a non-empty command (templateDefinition.config.command)") + } + + if customConfig.Output == "" { + valid = false + validationErrs = append(validationErrs, "custom template config must have a non-empty output (templateDefinition.config.output)") + } + + if !valid { + return fmt.Errorf("custom template configuration is invalid: %s", strings.Join(validationErrs, ",")) + } + // build the command to execute + cmd := exec.Command(customConfig.Command, customConfig.Args...) + + // custom template should output a valid FBC to STDOUT so we can + // build the FBC just like all the other templates. + v, err := cmd.Output() + if err != nil { + return fmt.Errorf("running command %q: %v: %v", cmd.String(), err, v) + } + + reader := bytes.NewReader(v) + + dcfg, err := declcfg.LoadReader(reader) + cmdString := []string{customConfig.Command} + cmdString = append(cmdString, customConfig.Args...) + if err != nil { + return fmt.Errorf("error parsing custom command output: %s, %v", strings.Join(cmdString, "'"), err) + } + + destPath := path.Join(cb.builderCfg.WorkingDir, dir, customConfig.Output) + + // custom template should output a valid FBC to STDOUT so we can + // build the FBC just like all the other templates. + return build(dcfg, destPath, cb.builderCfg.OutputType) +} + +func (cb *CustomBuilder) Validate(ctx context.Context, dir string) error { + return validate(ctx, cb.builderCfg, dir) +} + +func writeDeclCfg(dcfg declcfg.DeclarativeConfig, w io.Writer, output string) error { + switch output { + case "yaml": + return declcfg.WriteYAML(dcfg, w) + case "json": + return declcfg.WriteJSON(dcfg, w) + default: + return fmt.Errorf("invalid --output value %q, expected (json|yaml)", output) + } +} + +func validate(ctx context.Context, builderCfg BuilderConfig, dir string) error { + + path := path.Join(builderCfg.WorkingDir, dir) + s, err := os.Stat(path) + if err != nil { + return fmt.Errorf("directory not found. validation path needs to be composed of BuilderConfig.WorkingDir+Component[].Destination.Path: %q: %v", path, err) + } + if !s.IsDir() { + return fmt.Errorf("%q is not a directory", path) + } + + if err := config.Validate(ctx, os.DirFS(path)); err != nil { + return fmt.Errorf("validation failure in path %q: %v", path, err) + } + return nil +} + +func build(dcfg *declcfg.DeclarativeConfig, outPath string, outType string) error { + // create the destination for output, if it does not exist + outDir := filepath.Dir(outPath) + err := os.MkdirAll(outDir, 0o777) + if err != nil { + return fmt.Errorf("creating output directory %q: %v", outPath, err) + } + + // write the dcfg + file, err := os.Create(outPath) + if err != nil { + return fmt.Errorf("creating output file %q: %v", outPath, err) + } + defer file.Close() + + err = writeDeclCfg(*dcfg, file, outType) + if err != nil { + return fmt.Errorf("writing to output file %q: %v", outPath, err) + } + + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/composite.go b/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/composite.go new file mode 100644 index 0000000000..e88daa7b2f --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/composite.go @@ -0,0 +1,261 @@ +package composite + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/url" + "os" + "path/filepath" + + "github.com/operator-framework/operator-registry/pkg/image" + "k8s.io/apimachinery/pkg/util/yaml" +) + +func WithCatalogFile(catalogFile io.Reader) TemplateOption { + return func(t *Template) { + t.catalogFile = catalogFile + } +} + +func WithContributionFile(contribFile io.Reader, contribPath string) TemplateOption { + return func(t *Template) { + t.contributionFile = contribFile + t.contributionPath = contribPath + } +} + +func WithOutputType(outputType string) TemplateOption { + return func(t *Template) { + t.outputType = outputType + } +} + +func WithRegistry(reg image.Registry) TemplateOption { + return func(t *Template) { + t.registry = reg + } +} + +func WithValidate(validate bool) TemplateOption { + return func(t *Template) { + t.validate = validate + } +} + +func NewTemplate(opts ...TemplateOption) *Template { + temp := &Template{ + // Default registered builders when creating a new Template + registeredBuilders: map[string]builderFunc{ + BasicBuilderSchema: func(bc BuilderConfig) Builder { return NewBasicBuilder(bc) }, + SemverBuilderSchema: func(bc BuilderConfig) Builder { return NewSemverBuilder(bc) }, + RawBuilderSchema: func(bc BuilderConfig) Builder { return NewRawBuilder(bc) }, + CustomBuilderSchema: func(bc BuilderConfig) Builder { return NewCustomBuilder(bc) }, + }, + } + + for _, opt := range opts { + opt(temp) + } + + return temp +} + +// FetchCatalogConfig will fetch the catalog configuration file from the given path. +// The path can be a local file path OR a URL that returns the raw contents of the catalog +// configuration file. +// The filepath can be structured relative or as an absolute path +func FetchCatalogConfig(path string, httpGetter HttpGetter) (io.ReadCloser, error) { + var tempCatalog io.ReadCloser + catalogURI, err := url.ParseRequestURI(path) + // Evalute local catalog config + // URI parse will fail on relative filepaths + // Check if path is an absolute filepath + if err != nil || filepath.IsAbs(path) { + tempCatalog, err = os.Open(path) + if err != nil { + return nil, fmt.Errorf("opening catalog config file %q: %v", path, err) + } + } else { + // Evalute remote catalog config + // If URI is valid, execute fetch + tempResp, err := httpGetter.Get(catalogURI.String()) + if err != nil { + return nil, fmt.Errorf("fetching remote catalog config file %q: %v", path, err) + } + tempCatalog = tempResp.Body + } + + return tempCatalog, nil +} + +func (t *Template) Parse() (*Specs, error) { + var s Specs + + catalogSpec, err := t.parseCatalogsSpec() + if err != nil { + return nil, err + } + s.CatalogSpec = catalogSpec + + contributionSpec, err := t.parseContributionSpec() + if err != nil { + return nil, err + } + s.ContributionSpec = contributionSpec + + return &s, nil +} + +func (t *Template) Render(ctx context.Context, validate bool) error { + specs, err := t.Parse() + if err != nil { + return err + } + + catalogBuilderMap, err := t.newCatalogBuilderMap(specs.CatalogSpec.Catalogs, t.outputType) + if err != nil { + return err + } + + // TODO(everettraven): should we return aggregated errors? + for _, component := range specs.ContributionSpec.Components { + if builderMap, ok := (*catalogBuilderMap)[component.Name]; ok { + if builder, ok := builderMap[component.Strategy.Template.Schema]; ok { + // run the builder corresponding to the schema + err := builder.Build(ctx, t.registry, component.Destination.Path, component.Strategy.Template) + if err != nil { + return fmt.Errorf("building component %q: %w", component.Name, err) + } + + if validate { + // run the validation for the builder + err = builder.Validate(ctx, component.Destination.Path) + if err != nil { + return fmt.Errorf("validating component %q: %w", component.Name, err) + } + } + } else { + return fmt.Errorf("building component %q: no builder found for template schema %q", component.Name, component.Strategy.Template.Schema) + } + } else { + allowedComponents := []string{} + for k := range *catalogBuilderMap { + allowedComponents = append(allowedComponents, k) + } + return fmt.Errorf("building component %q: component does not exist in the catalog configuration. Available components are: %s", component.Name, allowedComponents) + } + } + return nil +} + +func (t *Template) builderForSchema(schema string, builderCfg BuilderConfig) (Builder, error) { + builderFunc, ok := t.registeredBuilders[schema] + if !ok { + return nil, fmt.Errorf("unknown schema %q", schema) + } + + return builderFunc(builderCfg), nil +} + +func (t *Template) parseCatalogsSpec() (*CatalogConfig, error) { + + // get catalog configurations + catalogConfig := &CatalogConfig{} + catalogDoc := json.RawMessage{} + catalogDecoder := yaml.NewYAMLOrJSONDecoder(t.catalogFile, 4096) + err := catalogDecoder.Decode(&catalogDoc) + if err != nil { + return nil, fmt.Errorf("decoding catalog config: %v", err) + } + err = json.Unmarshal(catalogDoc, catalogConfig) + if err != nil { + return nil, fmt.Errorf("unmarshalling catalog config: %v", err) + } + + if catalogConfig.Schema != CatalogSchema { + return nil, fmt.Errorf("catalog configuration file has unknown schema, should be %q", CatalogSchema) + } + + return catalogConfig, nil +} + +func (t *Template) parseContributionSpec() (*CompositeConfig, error) { + + // parse data to composite config + compositeConfig := &CompositeConfig{} + compositeDoc := json.RawMessage{} + compositeDecoder := yaml.NewYAMLOrJSONDecoder(t.contributionFile, 4096) + err := compositeDecoder.Decode(&compositeDoc) + if err != nil { + return nil, fmt.Errorf("decoding composite config: %v", err) + } + err = json.Unmarshal(compositeDoc, compositeConfig) + if err != nil { + return nil, fmt.Errorf("unmarshalling composite config: %v", err) + } + + if compositeConfig.Schema != CompositeSchema { + return nil, fmt.Errorf("composite configuration file has unknown schema, should be %q", CompositeSchema) + } + + return compositeConfig, nil +} + +func (t *Template) newCatalogBuilderMap(catalogs []Catalog, outputType string) (*CatalogBuilderMap, error) { + + catalogBuilderMap := make(CatalogBuilderMap) + + // setup the builders for each catalog + setupFailed := false + setupErrors := map[string][]string{} + for _, catalog := range catalogs { + errs := []string{} + // if catalog.Destination.BaseImage == "" { + // errs = append(errs, "destination.baseImage must not be an empty string") + // } + + if catalog.Destination.WorkingDir == "" { + errs = append(errs, "destination.workingDir must not be an empty string") + } + + // check for validation errors and skip builder creation if there are any errors + if len(errs) > 0 { + setupFailed = true + setupErrors[catalog.Name] = errs + continue + } + + if _, ok := catalogBuilderMap[catalog.Name]; !ok { + builderMap := make(BuilderMap) + for _, schema := range catalog.Builders { + builder, err := t.builderForSchema(schema, BuilderConfig{ + WorkingDir: catalog.Destination.WorkingDir, + OutputType: outputType, + ContributionPath: t.contributionPath, + }) + if err != nil { + return nil, fmt.Errorf("getting builder %q for catalog %q: %v", schema, catalog.Name, err) + } + builderMap[schema] = builder + } + catalogBuilderMap[catalog.Name] = builderMap + } + } + + // if there were errors validating the catalog configuration then exit + if setupFailed { + //build the error message + var errMsg string + for cat, errs := range setupErrors { + errMsg += fmt.Sprintf("\nCatalog %v:\n", cat) + for _, err := range errs { + errMsg += fmt.Sprintf(" - %v\n", err) + } + } + return nil, fmt.Errorf("catalog configuration file field validation failed: %s", errMsg) + } + + return &catalogBuilderMap, nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/config.go b/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/config.go new file mode 100644 index 0000000000..21d4ac5ee0 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/config.go @@ -0,0 +1,42 @@ +package composite + +const ( + CompositeSchema = "olm.composite" + CatalogSchema = "olm.composite.catalogs" +) + +type CompositeConfig struct { + Schema string + Components []Component +} + +type Component struct { + Name string + Destination ComponentDestination + Strategy BuildStrategy +} + +type ComponentDestination struct { + Path string +} + +type BuildStrategy struct { + Name string + Template TemplateDefinition +} + +type CatalogConfig struct { + Schema string + Catalogs []Catalog +} + +type Catalog struct { + Name string + Destination CatalogDestination + Builders []string +} + +type CatalogDestination struct { + // BaseImage string + WorkingDir string +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/types.go b/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/types.go new file mode 100644 index 0000000000..32116bea19 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/types.go @@ -0,0 +1,62 @@ +package composite + +import ( + "encoding/json" + "io" + "net/http" + + "github.com/operator-framework/operator-registry/pkg/image" +) + +type TemplateDefinition struct { + Schema string + Config json.RawMessage +} + +type BasicConfig struct { + Input string + Output string +} + +type SemverConfig struct { + Input string + Output string +} + +type RawConfig struct { + Input string + Output string +} + +type CustomConfig struct { + Command string + Args []string + Output string +} + +type BuilderMap map[string]Builder + +type CatalogBuilderMap map[string]BuilderMap + +type builderFunc func(BuilderConfig) Builder + +type Template struct { + catalogFile io.Reader + contributionFile io.Reader + contributionPath string + validate bool + outputType string + registry image.Registry + registeredBuilders map[string]builderFunc +} + +type TemplateOption func(t *Template) + +type Specs struct { + CatalogSpec *CatalogConfig + ContributionSpec *CompositeConfig +} + +type HttpGetter interface { + Get(url string) (*http.Response, error) +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/README.md b/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/README.md new file mode 100644 index 0000000000..ace33746ab --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/README.md @@ -0,0 +1,286 @@ +## Semver Template: + +Since a `catalog template` is identified as an input schema which may be processed to generate a valid FBC, we can define a `semver template` as a schema which uses channel conventions to facilitate the auto-generation of channels along `semver` delimiters. + +[**DISCLAIMER:** since version build metadata [MUST be ignored when determining version precedence](https://semver.org) when using semver, rendering the template will result in an error if two bundles differ only by the build metadata.] + +### Schema Goals +The `semver template` must have: +- terse grammar to minimize creation/maintenance effort +- deterministic output +- simple channel promotion for maturing bundles +- demonstration of a common type of channel maturity model +- minor-version (Y-stream), major-version (X-stream) versioning optionality + +The resulting FBC must clearly indicate how generated channels relate to template entities + +### Schema Anatomy +For convenience and simplicity, this template currently supports hard-coded channel names `Candidate`, `Fast`, and `Stable`, in order of increasing channel stability. We leverage this relationship to calculate the default channel for the package. + +`GenerateMajorChannels` and `GenerateMinorChannels` dictate whether this template will generate X-stream or Y-stream channels (attributes can be set independently). If omitted, only minor (Y-stream) channels will be generated. + +Under each channel are a list of bundle image references which contribute to that channel. + +With the following (hypothetical) example we define a mock bundle which has 11 versions, represented across each of the channel types: +```yaml +Schema: olm.semver +GenerateMajorChannels: true +GenerateMinorChannels: true +Candidate: + Bundles: + - Image: quay.io/foo/olm:testoperator.v0.1.0 + - Image: quay.io/foo/olm:testoperator.v0.1.1 + - Image: quay.io/foo/olm:testoperator.v0.1.2 + - Image: quay.io/foo/olm:testoperator.v0.1.3 + - Image: quay.io/foo/olm:testoperator.v0.2.0 + - Image: quay.io/foo/olm:testoperator.v0.2.1 + - Image: quay.io/foo/olm:testoperator.v0.2.2 + - Image: quay.io/foo/olm:testoperator.v0.3.0 + - Image: quay.io/foo/olm:testoperator.v1.0.0 + - Image: quay.io/foo/olm:testoperator.v1.0.1 + - Image: quay.io/foo/olm:testoperator.v1.1.0 +Fast: + Bundles: + - Image: quay.io/foo/olm:testoperator.v0.2.1 + - Image: quay.io/foo/olm:testoperator.v0.2.2 + - Image: quay.io/foo/olm:testoperator.v0.3.0 + - Image: quay.io/foo/olm:testoperator.v1.0.1 + - Image: quay.io/foo/olm:testoperator.v1.1.0 +Stable: + Bundles: + - Image: quay.io/foo/olm:testoperator.v1.0.1 +``` +In this example, `Candidate` has the entire version range of bundles, `Fast` has a mix of older and more-recent versions, and `Stable` channel only has a single published entry. + +### CLI Tool Usage +``` +% ./bin/opm alpha render-template semver -h +Generate a file-based catalog from a single 'semver template' file +When FILE is '-' or not provided, the template is read from standard input + +Usage: + opm alpha render-template semver [FILE] [flags] + +Flags: + -h, --help help for semver + -o, --output string Output format (json|yaml|mermaid) (default "json") + +Global Flags: + --skip-tls-verify skip TLS certificate verification for container image registries while pulling bundles + --use-http use plain HTTP for container image registries while pulling bundles +``` + +Example command usage: +``` +# Example with file argument passed in +opm alpha render-template semver infile.semver.template.yaml + +# Example with no file argument passed in +opm alpha render-template semver -o yaml < infile.semver.template.yaml > outfile.yaml + +# Example with "-" as the file argument passed in +cat infile.semver.template.yaml | opm alpha render-template semver -o mermaid - +``` +Note that if the command is called without a file argument and nothing passed in on standard input, +the command will hang indefinitely. Either a file argument or file information passed +in on standard input is required by the command. + +With the template attribute `GenerateMajorChannels: true` resulting major channels from the command are (filtering out `olm.bundle` content): +```yaml +--- +defaultChannel: stable-v1 +name: testoperator +schema: olm.package +--- +entries: + - name: testoperator.v0.1.0 + - name: testoperator.v0.1.1 + - name: testoperator.v0.1.2 + - name: testoperator.v0.1.3 + skips: + - testoperator.v0.1.0 + - testoperator.v0.1.1 + - testoperator.v0.1.2 + - name: testoperator.v0.2.0 + - name: testoperator.v0.2.1 + - name: testoperator.v0.2.2 + replaces: testoperator.v0.1.3 + skips: + - testoperator.v0.1.0 + - testoperator.v0.1.1 + - testoperator.v0.1.2 + - testoperator.v0.2.0 + - testoperator.v0.2.1 + - name: testoperator.v0.3.0 + replaces: testoperator.v0.2.2 + skips: + - testoperator.v0.1.0 + - testoperator.v0.1.1 + - testoperator.v0.1.2 + - testoperator.v0.1.3 + - testoperator.v0.2.0 + - testoperator.v0.2.1 +name: candidate-v0 +package: testoperator +schema: olm.channel +--- +entries: + - name: testoperator.v1.0.0 + - name: testoperator.v1.0.1 + skips: + - testoperator.v1.0.0 + - name: testoperator.v1.1.0 + replaces: testoperator.v1.0.1 + skips: + - testoperator.v1.0.0 +name: candidate-v1 +package: testoperator +schema: olm.channel +--- +entries: + - name: testoperator.v0.2.1 + - name: testoperator.v0.2.2 + skips: + - testoperator.v0.2.1 + - name: testoperator.v0.3.0 + replaces: testoperator.v0.2.2 + skips: + - testoperator.v0.2.1 +name: fast-v0 +package: testoperator +schema: olm.channel +--- +entries: + - name: testoperator.v1.0.1 + - name: testoperator.v1.1.0 + replaces: testoperator.v1.0.1 +name: fast-v1 +package: testoperator +schema: olm.channel +--- +entries: + - name: testoperator.v1.0.1 +name: stable-v1 +package: testoperator +schema: olm.channel +``` + +We generated a channel for each template channel entity corresponding to each of the 0.\#.\#, 1.\#.\# major version ranges with skips to the head of the highest semver in a channel. We also generated a replaces edge to traverse across minor version transitions within each major channel. Finally, we generated an `olm.package` object, setting as default the most-stable channel head we created. This process will prefer `Stable` channel over `Fast`, over `Candidate` and then a higher bundle version over a lower version. +(Please note that the naming of the generated channels indicates the digits of significance for that channel. For example, `fast-v1` is a decomposed channel of the `fast` type which contains only major versions of contributing bundles matching `v1`.) + +For contrast, with the template attribute `GenerateMinorChannels: true` and running the command again (again skipping rendered bundle image output) we get a bunch more channels: +```yaml +--- +defaultChannel: stable-v1.0 +name: testoperator +schema: olm.package +--- +entries: + - name: testoperator.v0.1.0 + - name: testoperator.v0.1.1 + - name: testoperator.v0.1.2 + - name: testoperator.v0.1.3 + skips: + - testoperator.v0.1.0 + - testoperator.v0.1.1 + - testoperator.v0.1.2 +name: candidate-v0.1 +package: testoperator +schema: olm.channel +--- +entries: + - name: testoperator.v0.2.0 + - name: testoperator.v0.2.1 + - name: testoperator.v0.2.2 + replaces: testoperator.v0.1.3 + skips: + - testoperator.v0.1.0 + - testoperator.v0.1.1 + - testoperator.v0.1.2 + - testoperator.v0.2.0 + - testoperator.v0.2.1 +name: candidate-v0.2 +package: testoperator +schema: olm.channel +--- +entries: + - name: testoperator.v0.3.0 + replaces: testoperator.v0.2.2 + skips: + - testoperator.v0.1.0 + - testoperator.v0.1.1 + - testoperator.v0.1.2 + - testoperator.v0.1.3 + - testoperator.v0.2.0 + - testoperator.v0.2.1 +name: candidate-v0.3 +package: testoperator +schema: olm.channel +--- +entries: + - name: testoperator.v1.0.0 + - name: testoperator.v1.0.1 + skips: + - testoperator.v1.0.0 +name: candidate-v1.0 +package: testoperator +schema: olm.channel +--- +entries: + - name: testoperator.v1.1.0 + replaces: testoperator.v1.0.1 + skips: + - testoperator.v1.0.0 +name: candidate-v1.1 +package: testoperator +schema: olm.channel +--- +entries: + - name: testoperator.v0.2.1 + - name: testoperator.v0.2.2 + skips: + - testoperator.v0.2.1 +name: fast-v0.2 +package: testoperator +schema: olm.channel +--- +entries: + - name: testoperator.v0.3.0 + replaces: testoperator.v0.2.2 + skips: + - testoperator.v0.2.1 +name: fast-v0.3 +package: testoperator +schema: olm.channel +--- +entries: + - name: testoperator.v1.0.1 +name: fast-v1.0 +package: testoperator +schema: olm.channel +--- +entries: + - name: testoperator.v1.1.0 + replaces: testoperator.v1.0.1 +name: fast-v1.1 +package: testoperator +schema: olm.channel +--- +entries: + - name: testoperator.v1.0.1 +name: stable-v1.0 +package: testoperator +schema: olm.channel +``` +Here, a channel is generated for each template channel which differs by minor version, each channel has a `replaces` edge from the highest version entry in the predecessor channel, and the highest version entry in each channel also has a skips list composed of all lower version entries within the same minor (Y). Please note that at no time do we transgress across major-version boundaries with the channels, to be consistent with [the semver convention](https://semver.org/) for major versions, where the purpose is to make incompatible API changes. + + +### DEMOS + +#### Major Channel Generation +![`GenerateMajorChannels`](./major-version-demo.gif) + +#### Minor Channel Generation +![`GenerateMinorChannels`](./minor-version-demo.gif) + + diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/major-version-demo.gif b/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/major-version-demo.gif new file mode 100644 index 0000000000000000000000000000000000000000..21d46519c6899e1bd1affd7eda468f624744898c GIT binary patch literal 1041736 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%0ABvd+;$|81- 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]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
  • w=(tQIzB%BjHBZ>f*QQepC= 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

    uIFyYn4gVcp8i%fY+S{d4ps@(4$#=5=e?;p6 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 z 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 z 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

    }HspCMr81=V5ySz;73o}#Q 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%0DdL@RpHjBd1}9}Ve9OM23juC%2ujpQIY%)TA!8 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 ~!eB*}l^zvJ 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

    KDX?T6h}|i2f-tj$B`H=|UMM7Zid#e|O0sw# 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

    ZrK+)3VAFUV5H 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/minor-version-demo.gif b/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/minor-version-demo.gif new file mode 100644 index 0000000000000000000000000000000000000000..fbe9bf1ac1477612bbeb8b498782b794501f3cf0 GIT binary patch literal 1003102 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

    hk|e>QSxPU_FN7VyAmI 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%0Dg{UAu|oJQHYpX7RfI(+w5qu=ab0rx>H=PH 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 K-F+e%NJBj|16`Ze9YlR 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�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ΝT@Ik|ExejWbA^W%sR@&3>+*Vw6@U7HR49fKYe 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

    E_2`T$@7Ayq0gUADxeJ|Y*l{9g7}MOlbe1U_3L zBWXx0!S;l*trOrtU>Fk|e>C6;&?93W9B@>A2JEob4dWDW8Z2Jq5)A@X)e94;wXCu1 z6qe8^GqN(wobFU(8!*5_3UV6SV!@=4d#2W4+K>l?^Z+}h(%Wvz-d0tu6byhUQ@N?C zXtj52DGShm zhy4bZ`%FMOr@LMSQwfR&7C)6UUkq#X4a zJz42=u0q3XhId+)0NMt9e8Q^v*r4WEf;KVW%M^MsUR=1teTbq(lubFi+OR}vgH>g; z@=O**n!uYY0ivv)grZ(dz8^3K+0|RihB^)i;98G~S_Yhb?ntV8-^sUo<`|}cx z@xFc*Ia6>X8pDH~FAIrVFBhd_+M%64rOd zXaA3yJWk;18Ue@_9#y}Tikq3N6djrJH)A4SVFw`E?yWPRG!kru)%w+Su7LZd4CwBj z;k%WDp#4Tf>+C**jK~g5)aK1+rdR?Q`L45n?yIlkp^nMrt|FPOyhdaHL()f-^o44B zj0;)d(U4Yz#hIpTT2l41zY?`=0X`FhALDgUVRbwe=1-M|$jkbriI`8WX{<~++&C`U zv(r0ecyZ{<)K!@fyk&rv(*iyh_-jEm)@QBtToDp@wttEIu@(Yc>9nZr$Nqrj89MWR zn~efo;S9i}R5=;pqy+>XUL?|iUA8|SN?=;s0SDcqBDYQU%u`t~Oi94GI!s$eZ~qZ( z2&5QpWXJlh;Rjwe!x~_NY?V?gaAc%^9LkY6DoDGh3!_uMuQN)(2B@0&K=r+~e;2vA z%S{b|RS_o!z_32Qcv0Esy~pa7>FAiy0Eku~gkl2j5Q`q_OSJIa=BW7aQzZa0-k$7t z=>2y#_;cxJugr6oniYS)1iM9IEq*)t@gjhzNEBh0Iq=$MS#dCX18~5p4(K0 zGqbPpEd!#TNI}8V`ISCi)GdKG6_36NhT*9Xu0a8EecvTiN$YXc@TFN=VcqrdTCWWP z>=m1<9UqaI-6MHi5`>*1Hq5W;5 zC<@&YMe$AtAD&6D8qeDB)wkpH&p&N*c+qRhSVvR!TynO|p+9&SVibNAYCDuqoeA zJ|#c~$j^03g5(1-EC7$Z+$wC|^QGc6JQ>QB3|KzH0`eA4!k!sggdB~{?1@V%EZ`kX z-Py#HPl8)JoDdO~kUZ6%A8AE*@dGb{pT9gED6$qxz}dNkn*Rj$FRlH5yWK!U1@yD7q72}PV6Y8ImxQ7c4;ZIuGT^6Mdk=Dm?Kxos5nX`ZVBN^MpK-bW+@RN z229umcolG3XOP-azAU9yJO@Z+0RyO3b`Fp6lv5ss6g@>w8d*e;2FQ*TsTY!zEp%2K zF2pKj0CIU9;8EddqKi~KfvN2QQk|1(%#?tZD0<2UHlMsk>Zw4f|%|ioIVYl7R6CM-l@!?dy-rD^M; zVrCPjVN{(%@(^frK5H0`M)<@^|9RcmB*2<3DT)RSy`E^XPRn7zh_|ecsm3b9Y9o%) zj{7~BRMc4mpq4om5VJO#*l}i;83yoKgsy58OQc|2K21TyJfR)jyStb;)-)|tT+VmKGNf(*GRTh5)Rqy#lUl>{P9Krv_RcgHRGSHGiym-p%MW#_mTBJD|vbC+a?8MzF5;DM9G)AilwWe44YJvI-oYgL4Tmh&aYrn|P zJ@BpB{;be=skD5C*}#a!=~|rPEZkk(d#V|YZi1tUYTB-6ZJCYc>A?fkNdbbO!J31^ z?ZNTB&U5S;P*HBcBu6O(0w-)i7)$`xI#2WhRWH#;Prk>ajjje9j>Ki_xE?6kQi|-- zuG(hRTgZ>wDnoUUR_*3l+SC>-Ku$8rPS^Sh&e6;FHt+uKn77LY59r z9>fykf~@F%D}j1nZ7He!QsASVOaI+9&`PWI+=#L~m)x=IVBcHuFddvKs^%~|U8$;^ua_+^>F8>UYMHkR=Y)FIas(Y_dJ`1I+~-#of6jvr%W_!_E(5_U1Fci6{HiO)>Md7|A$0C%kTRlExdb z{%?O&8YkibytZ>Nky~5tkdmR0+h!v=zb5we$PnG6`J6HKR!RUzK)AnUlz~+=2g=H9 zJ?9uSgC~ZTT*|1!P3R&*8_xeD4Gp-KRonfISO+v|Msid857C9jB_9nR&24DRfmgtC zF2J+a3T|JXvRt<{GrTo@h{*?AZA{zV|IIai;BvqMafBwQY=>*vGF?}kSMY+C`W>}z zA0_7oaA7y|jH-v~F2VsUfSLV_g?Xj%nI~GGYgVsxa&$?6!kiARB~$MT|GZ2qi|pc+ zXyZne5#lbhU&wXp754 zfWT7dl+hu@(r5~7m$m<5>n`IIX>({Zh z@b6AT8CUCKE8cmBGx`=9*&a0h&}HN#c5RC|4mmc03t^Bql?-xPWpDJ0gD>-r1lX7d z$c!j5a7$Hu!Bc-ZoJUTcka;3kA4zC;2*L-mD90?^G{EL`lnU?l!srs%S`wMAkH0!4 z0y&s0b&1D_-O|j^tSMl$Bzo_4eZwgF5V%#UHK{B%atL`(0y?J;LnG+rl-8@6k9j#4 z@{&ip!t_p=U;_VJytf0zc0UUNic6`}sPh5Wxm56o2l$D9=ibEVb1C0AJ)gUQer0Sw zc?#(u(M5v+J9LPE5{I$tM~B9)+ZysUpsD=Bl$VHD`#PqV2weY~>+P{$vq5@HjR~I> zjQ4qOUNgK~iFh|qQWGxM(XMz1yF0XUwU*8j>pCEKbP&$ z6gyUY2K0D(vXkqww?he+btsBhAoJY(@(E^f>D>ehqKi%(KhWc#5cidF8!hX?v-`}xu@eIZ48 zTsz~Gg-ZX*tK}}kck0l0Os(0zF9%Tv;mJpS9X9^LtUOSPw7BG)0WY)1PcO|wk=i@? z4+?P3@jQaKJF-79x$ab6uZW+FNZ9xEc&j&SVD7{B`rgl|9`OP1P_pzK`(pbqi8$rm zL2^7xG`0diVdwcoYjqEkeVng7n_iF*qCRnYGyAoNvXjCG%?dIlP^kV5m~&HREj-P8 zx$U1en5?$2Q?~k%y5XC8Vl--Ww(&A-kA7~(WFWKy|gHl0ssR63>-Zz*VXrQ@S#q* z>Q_M7@bV#N3qE841F{KrO;-U_M5u`q*wD{9M}!~+aL_2rf+c!3vCF2)TM>^3SUua9 z$(==RM95U|b#M(MMBE$(oFnduM^gZ9o>a(_(jg6u9AV_B^U6`ANtG^T+SKV&s8OX( zrCOCrL_rLK0;p)@oRXCphq>{3Pl1JbLM&{Epa2k?Wgs!2ja19+kP6S(WDV1nzybd~ z6p^S~FkxDn4I(G4?b+9Dghdwv_c^*Rzo>aP&>;vRMv>h2uUW;`e4= zge(P(L~Aye&gvo$J`S=eV3C%Y0&6DDC;4p~&$tcNHL`FI?A-$BrUcAyQA&DyvZyW+ z)HFviN3goZ7Ck%mBcTV+yVHALa@-L=h(ukXpehZ10b9Nt41REA=(6iPwc1dPf<+bp z5E)pIvxu^qh^mYc1|EoDf(#(zPl4DfI)IJc>}p3GoR2wpDGPd##sK+8CgFv*}V z!|F@xC7BlNqoxKN@UX;7Ff)lO_y#0mM!}llDX;K~0_8XeDuT`ctE#l}N-Y1g)N)HM zyYwq8Bp&MVuLli*c46KkgT+W zWX@D|O+B}|D@6u$JO)uaVQjBb#RS!~%!MdTqe<5Q9pXA8=GpMnJ=T&{%`;6^Aj~n@ zbTLu!#MIQ#YYRPt2sY%Hf>QGBG- zFI#r`Wtd}@d1jiCN?_y%Qr@%OXTw@TOl!>I#0x4I4J0^# ze&vIsC6ELp13*N2K*Ee9&Chkdk~CgudCsX}dE5PGVU}AQ%k6dTQyQM)<5g z7Wij7yAN(|asURXdoie`-WG9PnM4AvLpwMcf?NY9VV0qH{%#w)Pkg%Y8eN230Y|J6 z;!`}Kfm5x}1!Y;{=5(20tuA5*o{8%M-&pS$g*?37gm~pP{q+CL8+&#NG(uqZn)BCx zfByUT|9=1mP=Es*3EBu)GshiJfeU0HQuftAsU#4B6Qp1TEqFl;W>AA0+)@|H#KA2| z5QHNn;g>vE!YW{cZ75`63tjj^7{*YBD7=H%X6O_V-cW}-OoD)T=nKpJP>4e$ViApa z#2MzxEJ(aU4w?8w3@TB6I#iX_pm;?rW>Je<S-zrv&m8<_`Wh-6zN?68Hmb0W~Ep17t zG`dzY$6%0pv`{N0(n3ZXFJ{bPI$%>D&(}nqnLuu%NbCf`{ZXo{dvoM-7GdH zi_-u|=bOx#!*{C6S)W`-H3gA?IIkNhK9koy4X6+ogqd9iz?TKtF+*q_;*&xd%0|hB z4`~VcXG>lBQkeeGJGx01z`TVHf;OgJDk0giXw{}M3B-N8(AGuMm#u)|#au!A;zja; zKbpR8eN|)>A`%)?tY%fKTlHU1^3nkY_{aj>K+^yC6aXECAvC9wD?nGE_bhvIrfzgG zW``!>HO+L-CN$-M@lYfI?ld4Wjd`1MX2(&tWT0x+8dT9Dx3jBqRkD+%Y-O#Im+KL= zO?Vgt2%zxPcw8(u4(i*vep1xzpzTqAs|>i{r_`!WsBTDN>GTNklb|JGE48(3Z+-h) z;C_~jth*da)d~f5bnG&R!Bmi7+b3S04WrH#25O6&+I$)WwcNXmaR*a@3V1iT<0Wr- zCmR&y28m=MOCvp<7d|n?mb$kS*_w1g8H-p~0QkK`c<|F-g}`o1HHxck>sGb;rU_YW zP@Q1+~Fp;SE&d{S#tHdp6Dh4j3Ul1i2;1#{xG&TBWkfV{i{KYngED`oLK)1tg{x!IC87omK90`Yea<&-(i<{0Cf<{pl*dg zA94#>-u_zN^QN~PF+C0VmJ3;}Ypior>SGUo3#b;GP@aT>xNfsL5ts!)F&MqgUX>K$ z`8LM+;7hs{*IVNo=eQPwotxU}a}t!|tl|oH7E<%nPNxIR??zLY-DhWe+ui=Uwl6=X>A%{&&C!Uhsn_ zeBlj$c*G}O@r!4C;~oEa$VdNPo{Mla3a8Gcnn+&rn

    jTS#1&WuEh+C;fQ~^ZCeP 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�_J&B4m=G~#1JGc0 zGut5y7>4XnhVBBjhx*qg(030s%22;{9zPCW3c*M*qxG&4X-ntsRx`ZFFc^}togR=r zP>PwVZbgZ4*<6P(CI57-=C@z2&^IsjZGh)o$H;XZH>wC$7fEze67LW!&W!w~SLaWD z0T*u#&d&6++MX0}A$K=RXJf{be~?!&_z4L$vlyaRTy@fh&8QrRm2$I|aB0_|FbNZ! zj&jQHTY*ckOlpK-R79^;i5)m~p_3;`7<#eT30!b_^*C=omiD{`H_5WMAhknv4n&J` zDI+qg4hCPB7>1AoiR!pq8~E#tH*?SSitS+B=)eLF61D!dffaUpBXfNVYs+{uVca1m zPi|$e6?fT{ec#utKA<3~_jqxxkiYbP8!=3fwVe9*fBn};TNEp!iJy8jl`nIZ+lhhO zlw?a!Xy<}xng1BKv&wN`}-IH7_wk9{?GB%tk7 z)ROHuBcwNN0eL3J=q6xUY1N{Zu@x{Ewo%*BjGPN4xS?s(1b4~Im@AJEk?wGtIB^5S zitl)yA=f51CeOV1jY%v~VcG0f^`WQWgZuI;T_kklXJ_1a#o%~g$(@czzv-gqDky0d?Hg*QR5v@!S!_Sk*7k$$29gl5<&pKe?4<*yLz>G zQ68I9l$SR(<8xow7;~FXDwc+seRq*?z^iC*^}pfw``UAsTWr zphVXbFaP>WuQ#kKqdy5Tm|^*6pLv3%c^-4dtyr({V2^82!l&97Q|V)z7Wkye2saz` zRv*F6}BR#FehvBNlbb4_C-x^yzFo>x+-ZP{&q^4!K& zV9Q&jDJ*U(rbszExM+H-W5(!8uK_s_3~F?o}|Wn)gm+Mg^(w7>YD#jX`CoSA90Un2O%qZva(O9X6zBK&c!6u`k439-9cjXZO=aizce z&10kpyQYfhe4@|0uDF@H!E-|sK+i9{%gdZQPK>@GuD&k(MJ4pD6xsmZ(kb^`B_p{z zU7Laje1;3$r}5QpBcQ1%a4fk^$kn@dNzJRJV>|pu8>#{R@a(GrDtfL}6wwr00JmN6G| z%S->%cZ2H4HQU-^;fDOZFo2_&kJ3%Sr{__jq5pLhTVdfK zG`$@*W-!=-&C!dNqiddw%L(ED93TU7U4l#%hJ5GQ3j4L~xr)}>FTv|1ZI3vYTpHs- zz;~`A;r=zY{q$2@#}G)kl7NVr*sMAcJrmz~(DZT{{ef!($I~ORBa!SIT_u$&qS#u_ z|2-?%!*7S5n=wff#>Q`42pldKJpr=L#QAE)3bY! z<^%BXbuyXmb7<+KDQc{}wdLYXyh;mq5TGI0_8JfYffv9tElOcN>N}jnGQJhIh=3Sk z7wpO+LN{VDw(3--1&xFh>&$;IAoluU$gxFiHQH9-Nu-0w7Z*r;&aWTwYmo1l&JqQ^f zjdKWMbe~8@q}B%!KshGWWQ}doAWa*hSDsb;kTM@?5%PgwAgN?x$#3-W$JbLCMwJY37A<}@JvJE9vGN-7!qV@wExLIM;xhMdhp410c{+}bd+ho zp-7*I4(1~kcmaLHm`F2{xn6Tlth9guYc6=&F9p1~fnIObd8e1#jZ-F1-?gS=WWY%f ziks#HMB93CLDHytbXbT}QagUAR1pkVqzpkxJpmhB9hTRCkpvW~(lHdh;$uNl9Z)D< z9ry_%UG`yjo11?2CsrC{P3OyR4c1cE0~Y==fr^t>G@F_wQOMk2v=r5gVVu_E9jK5T zP(UHWZYt=i^jv1?km4Fif@qnIR%wDgjW}wsrfz3!h6_Ca2fT60WR_p|TASrdxqCFZaF{IqD|6Jj?gDQxuPFMXKsV-Sq00gbidGypho%{4Umsv} z7dw&V0EI&D<*3Mq;7s(kUugO3#aLdeB*17+@$iAtVO)2b6?5LX=by(7dZ5GxB)aLR zqn^6ztFzv^>#xHeyX>>mUc2gGbZoosyGzNt@1A?~yYK|RH$3O+wEbuC#xrjct<7&Y z%<|B4ggo^eA$z^{wM)Of_rD*Iz3AbSO#cSu-=m+t`s=gbzWbtoll=S5!*%}ruTy6E z{i0j)r21^YsaGc3AL??FzJaw5fa$9r0UH=7JvlIfmLiYp+Cf30h);qV+#m-#=t0|A zz<(cv-3Q9lfKcFVgcT!S3RRdW?{R?^!EytiIIsb!xsXo={2qnS7sF)Hkb1Bp3JP=R zzTtGoi0iY3vQWpwO^gkLNmL>gt7ye5V$p>s^2!Fj=EX09(MZ)YB9`cqH0t?GBMS&% z7C*Pc>v5n-@@rliWy411ZE=ikq@Nu3xIF+_t%4_lpe+1o$U`DBk&1Mk1vYlKMA|Ee zWJD0xs7EK3EwW;7wB#evcS(LBivM|yM9v&DDLaOg(v+%PB`aI$%2&cNma?2BEo*7Z zTjDa8y4)o%d+Ezx0yCJx940Y~Y0P6HGnvXyB zLtE3rXwZXt0-(-gouon;I$;7u0tiJY?4mV7^7ZpVT}qum2?)20&M9Y3)J!4e8NA!+ zkyIk()0Y0ifc`P74Pfkq7i01opjE|kXW-e=qWF{#q^Mf^T1zVJ7%ya5LVpSvg8vTC z0X24jke}<+M4RFS35Z84x&I4k!IZ|uwyEO*-l0HM`=HQJL=j&k&74CS0~!{V3;-E0 z(x)!+q-#_XNo!^4Q(u-!I)F-2JL}6{ITFUB2H<&fAV#+8B^fDd@>d=p5&6<;F-baA zSfmqRX2i-7n8Gd(p8b<wX1B|d=dG^zrgc)jx!5I%n zb}LA949a!lu`5U<05pPS>=a8=luZ%RwwGcOz6b+d14jAA#%g4%3;jj8jIj&uBK9{7 z=w9`TFjFYi)TL>wTmM#9GZFv2NTDq8&3HDuno?$90ZNsW%}61J`mzUpzP0Wr>Z{cn zI&QWnqC{A|0|FNNAv6mp?VuOR zyqzybmdD*aLfA<9(d}S2KVn>KW$J3*74m|?FAgoROjFtkbeTO>`7Z1>2{|D9SPHTo z2j=v9kvrZjxw<{nbi#}oHQOT!Q?8JojS5*l#W`osrLv{S%MTnMG}1o4b9)4H6*>om z(b2K=oCv+TLJ9cGt6T4dyA@?6<9VHtn68GBzW-paFd-ro=&jC1;L?@@WWa`%d7^IW=V`yl0Rs#63ZUDe1WAG}+G23C z@`}?cJD_gaExy18JYZtNT6qrgfa^J`@X}ygYP6XXmApHLg(9{Nf#-O}0KUdRc{oRF zrb#7Z2C$5(NEJ)=DwY-0eOvV*Jfvu9hyifdH5{!_9!PY6k$`f+sldq{xFAFZOKM(S z#jeJSty{pFGXW34TNa+pfQkUUx{wdG_Xei3qWc zEp&x^DoCpSY{~tdo#Md(Gvc-gZLTq&Z=jc^^7bOJ70|Z`LNUVNk6Hl<#E3=%DESZse9}x5 zxJoBpDg4$ZJ}S(e8j_=w44H(cC*ai;ss+4g0}uj&ojWsPXDVZyo;qmk(H^H*-&Q%7t`ea&WpZ;np17OnWj`5<4;?N#?k3R+3gbrjy#ZO`oWgL3&FKcJsF zh#jgtAXga-uo%i-=tu6Mp7TA}3k_JJbry_0UHA!*hYiozrH*Jh*#^oV_<=;;p<4|` zR{sl)&n6)O(qW4fd{Hw{Mb6;CtL)m&WrZ(%VCh5%1F9d1NML2*)-bRGHe^s$WWoEX z!+m_-w|Uys+@E5kLLO+@oQY2vL53Q_!;f*9<`4;`j8VZsA6U>#T~OSoXj!-Dh79f; zS>f1|!J+z5iKEHN!Z=;bT-J^NRk<7+nynxe{)hy)T*_2On7G{h?Lq-aps?jgo<+tP zNztf8Kwm}8Ghhber67%XSr|YK0OX)n$bloKm^z@t0TPVm5FH+36v%7@-VKBP;Nr=E zQu+O%4l+jEMO#goBE88CCaB^RI0K1=VbjrIvT+3Yu!{vQO(m_@%T2*X6$=yoqW}0D z*`Fv1F2c>+v=wP3AAOVu8>JYKDa_Ac0FKEasWq5@D2M>Qpc8iC7qj$8G zuk_l5OWD+TXD8^JQazK=H4lHy{TXbKM{TRD}8JWG!;*8&8 z97X%NO_dDL1Oe1Z8P$!DNX?9n6i!Nw;8yr3S{s}NO!&h4F~Tvx#TI~J(vVp6T}X0a z-EAmTP`v~k_y<)Aq#K@8f;bX+(4pICRhOj_PqGw6P$ZdPTHg!++kK>FJf-*m$jd0) zz)21%lArn6Lh;lZOQ_x|y5nLQLMMu0NgRh}{8Ohr0EvWJhFFDrbb~Ia4F3vt%Qx($ zP|8(7rA8jaT>zL>ip`!jI*CFSM@^C=dLa=dGz(qyOPhH^wB1!y96`7z@L?F--Q6`n zumpE^4est1G(iS;cbDK6TnBf8ySpa11u~btXYKCG?#rG&{ZfzJr|VR8ec%7L+W-@A z3R52tBh7OZ*A`mR1?1DE83W0qC_zl3%!{vsDN3Yp#0e<^_l^9)HoRZhwYN(GvvJ83 z*nv8^#5kh3%)F13rX zlGbKV3S``4(v}nvqYO?l&t{OHu6e?SB6h_^!}*R~S5K!lHj zn~f0)<aw~D>xjQU3EcyWAW@B>{-UNa>+yB{fM`jm;Qz>!*<_0{%h zN718@A^)zz9TjPcX_3Y)Rdcp1tdd#hITBwT2_8*~2q}v=Czo^F;>8juHTOf)L@Ob# zVlRmH>iUcBj2QlvGy^B24dCd9Q}_}VuD_y+BoZd~%319a>=x%9Y8+Jw3`(B1B2-|o zXq*%*6jzy>2aaM4#x}44V4H;i4V>K=BZPyj4}TTI#9Qsq(!BSHCBRuWY;_0QsM;db z=@znK0@8hDB)g2aShbirR@|e;rrUo6OIuPgo0YF3or2(lH_zk8$)Zb_gCI!uVoX(M zXVm|8A7)SG^fF_~Y5X0ljd&v7cGnIBE5qRrI3{K2v+OKpFipHpwf6KkD6P7(!d&~s z@@e4iRaWaG?%QfKU?Mg+^toEECGEMw6x}&5GcmS#h@2A|;W^5Y76v;|GcgYLtdf)q!wzZ?L1fUTuW0V_qZuxteIYCB3g~-EEYEtG3guJUj1iN5!z?@hr<^ z_VTVY+D68+lcl8<%}N;Vz+Z;2!Ly;CRKwUQfvP;E>w@u7PrqWu|5V?|Wu;9D52}5c z3F;h0_6EZ!`vY#zw7M#*LMfGe`p7qPO+?mAjED29g*k4KgF7GWpd_l*d&tYWmxyah z^f$o@pp*iKuz|##tN9=+uzJC!6u^Q%Fi5E8;$NBL+V8)?gZlk@x2OX*^x9~3S|!tU zXyPmxcPn>_YrM+r?n&2mLm%oYT`a?>)ooBB!%Ts?5Uy7e>H2K4Sk9Ub%ID#R6iDB& z+11#PynT@ZHH)k8TpB&LeW~VP=q01E{2(0v`NWQ+tZ;NZvkf-&et)xR-^)d)YMex6 zL0ag0B8v1D?kTGXovSVsu=U6x<|!wp ze+XGbS})sKxwJn}FI?6N*dGu!HN7TOWyVasVBOQpC_Dug|H*R6_0sOE^c0w{w8}!M zl6E5f$rwioS?1>XHrH=2Ez2Oy{OhKl4a0M5FnC(Y0ZRDNXe1Xq>BW;$RCDnnW*kkZ z1$)ayle#6!r7uz8p2^n7mi^H^ZWrF&cicX8?}wK6?NgphYNGq-@UUzkzA`PAfQrr5 zkYS{%Ja74JIfTe#%o;N?49~8v*|L$Q?#@$KS7zu`1Bcrb7-n+NJd_aEwioT)ZEmdW zMJ8Vsk0sL%&Tw%qEtL#(C4g}oS>pl+w=I$q&WFh1G@$p|QR+;x$WM*{Lr9uJJTc0N zf88jV)1T6-?OTa*9Ni45ZpTxu+su0qrVk7o$il8%(c~kecuxR&OjK7FuGU}YXSTK98Wxy9Ml9nh&N`$9qNfSiMCz*`+b{c?eLlj3KN-9Yx2S)pmh+r%CG9{043eG)g|~A%{EfE z;Pt_|TuaHwZlT&~2{?bp0kFQjfqyL>!)=Vf@Yc?+ zDM+D9A^+QhOql(*Nnav3$Tus7U^s30H$%RO{KQT7kv%Uth{We%Dd?`5B+}6te$t~! zajY?mB5RC;^?>%*fYnbD>$rj8Wm_6{f&GvWN&hFwK!@~Cuk0ir-COMYuVwdlbcfn` zdiis|`fmp}YW=pg#!O>;@pUk-dZVYN8L=`kx*|~N>RK2qC!9G_Mhig;%ogQJ6Y&e^ zEtDi%inEXiKkqz{LCuN--{bO%-L>q&$28E45 zIzsVw%n??Oj*JhVYQ{rP8^y63l=ROXl_ow=&p%@S^7&)_a`jQ{TBn<9ByZwadGCDD zc#|ieKz*vN^wp&b{gJawn;vEVg9p?{{m%=@1SUSkn`m*Z8X-i33Jy~dhypX_ElDre zA1Hq1PYuLmWGKiKMq38Jz2F%D$?F5L0D&kH^`SN3kyzE%zCQR5joau(l-GW4_QAwE zZv8vN0DOVY}r}=><4OhJ0DmVdAonH3rryWJR(g80&nDEa6tofesqVHh+UJDmS zMRh07Z@o+dqzBu2-3tg?G%;Nym4x~-f!1+?H%jRb!}p(jUkz`H8KRYF$&oxoO>BU( zG{TmKl$0l{I4rh$dgY<4^sQ*ss=?XPb){7w_7%lWf6k-UC%O<4Pnj@PC{zYzY|-tG zRer4IhV>BlD=kVvRuh9Zd<-T0V+Qn<{>B6W5O1bgSG}PPB_QoEjCSlbU&OwjwUJxV z^9wDelf!oA1cU7^lEiIb@ooMtA^>gdwuEb&wbQpNYD|Qv812Cq1T##_uSa;DRF^Rb zmb0)O8s)-q`UxcVE^3u}`g4CW2@;(Ch$wgY6+KUZ+3tzCLW+e#qQcoB$sz`+hEbb30Oau`iL0iZ-Vq zbR2py3jA;yDK=biVq&Ug2y5*CMpY|w42kQVQ&#G@7|tqurWf(+;VMjZ#|ql6h99WZ;;E&Tc-^?`#x)fn|1e^i7lRuD< zGmbg=;6bq9=$B}XX}_p_ONat~-%g+yd&F#-SxMnkTPQipO_h{kCLlrdYT>6a=_U0w zsWAscV^*qkx0-njJMoWJc`(IY5xO4XaV*0n+`qH3@4h4KnEP zW}*uUjvzUzg(fK}ATrmJ2Ezm;t^%pHh$~NuqAQXNBL+SV>#$H^)vpfR<&Vos)pl^d z`FqO?n#Yg8mhMey+z|%=3BZa=;2kh5aI3o4R2UyXd zME-h~%?nzSfrWFE-pbl;m$FJ5{eeK+zD?@>7_zhuJ7b1*fQa^2*d~C4Sjg?K=+wg{w5JV{Etj_(%#zEMEd74;h&lS@-A*%p-e$qNrf~|`4jLX70;luND z1#V1%zVrU+&FX?*hvy`Ys&ZUOXD^w?aARtJ2we16JiE{Q0B8}$6uXhUq24|>Odh28 zJy0HP{yp!L?A z&}Vl3F&5(=zl#E4g;`~(n&4VB5sMBBRX-%dP*SYPG(J2d5N+G2!Qv-l9ir`!8Dr{5 zlxgz*;fcY<{Hy__;jhO}Rp7_B028J>1|fc`^CK-D4jtuUVyZM(5fYr}PSa^132s1~ z?aagQXsk3XKW z{m~0DIOyH^iY#My;!EN}$wZxjt4tjzaPx_B`+{#2&+x{KJDL_#fsy;(l0)UPN)k#H zDlsfr>C9V6urj zu2FVZVH)rv!UFRO8wFz}U0N3%9P?ZNNV5?7Xj@>W9%MjorqOr4E5nkvE`eigTR(-# z20)Obe<&|u6{V)L5^kCdD}zsgWu{D)f68Zy=7v0PNJO$|>_rZm&Ir0570Lk)@5@GD z;^eC+2o9z5w5i~AT-ast5w-aaPo`bR81>b^>`EW+@@?j7vhGKiN@$NoD^xIOp%HEX zwF`x&R%^2E71IR!k|1Y1*4c!dI}851Q`}PJIV^4@hhTbg1X>f=m!AV7jnI#PkOnS- zRwOF9`(w2k4$2CJ%TO8GPx!C_61D0Fwldf&^;e5PRcTdb(|rW3O2UGWJdZgYN4v>_ zhs&Dz3`NoZ7}2~!+0MWYz+&z_6q>Jm3OSDmKPW5jhp8uOPO7v zlBeXD1dD0QUGqv#zKfkk4=u~xe?p!84+V^0mX>=Shn&CNcN+hDSnh?!I-|n~ng9vB zAtKx^!FUFVxI^xJ7-248Izdxpo%em;uuB+Emnr(!l>rKP&WQ7aekf*o+kiuVb);5T z!g9^Z(1$SB7)wEO;^mcLzG2rm&)1#V%axHQt&R9kis~E4tD`c~Zb_+K7W90pV=7^8 zDWy3S5arczong1M<}OS2ud5Tr@b2$r-Q**YtCQB!?pcdnR=lmNQ_f-TIfsJQpO;ss zzYe?S-FI0FKd%1z4)0L_CuAc|ur?De?NNl+Z6nRMHX9%2Q9>tVE3dOQmp<%K#?x)9 z{B>;vhlwyxAcOU=gg?V}V0_}I%Wcm3s-t9BDS)`SJm zV;x5Lzmy0sh*xh%oi$#I#%l_1hTw$r#ZEyuT`k#~RK0dBQYbM#g zuDq=yu3Rt5Hvl)K*e&OqAz68m@m(c&vTaj-89et7b?eXz9s$_Ss^`0JouLz(FS#vKJqyy5*p7vW;a?&mv)_3^+Hena&=ET z&yQ68jr*A2gIKF?m-f{-31#Hqa5iFgmC5hlXA_tR36jb0b)rYgYQ*Dz+jnSmQA!r_ zy0fP4OUAA5Y~8+HD*W*WZpO!Q-h`j++%kMcY(d2o99nNXTI;HZh5a+oJ6VO%l#GCj zO>n$m8aijj^wiPvQ-JPGq3$0H zE}{ho9T)Gt1pYu#sHzXkgSuGg4SwUZ*nDzqd3Map`})tI0sA1k6~aPn0FyEsLDQ#8 z3SWg?aLRNaj5Bsa@T7+g$xI<+&0*=sM!E`{ClT((No%p|gI4y}&XC=&5V}MHTyE;v zafP4ciFGTY(XIe$g*_$;dFSTg6-2>MiNrKcQYr8NibX6lKoXM3Z#SAN3llXfi`;

    zv6BkF0?dagQOTj#pv`vCm-2`lGAu}(QTrgR8Ccv$uoX0{R5J9D8jH+)4h4l~UY`lwP%N_Fj6v?m=8R~>8>b9G5@Hty1 zDCXzrupLhI!glbAioMF{^S+u% zIJFC4%mhvp4khXiN-i*;ZsEr3B2Dx`&4^UQ^C~M9qHa_po?$B^y{QIQkX#-A^82UaQ<_@UQ%enXy@Q( z_>hi`JB6Z~;S3y72zEA{L0im6xSR^I#ArFzh!~PaWn?iG`0^fcMJ8_`$WJd#r440f zZ>q_!b4-w5|7`luTw=wyh6c9=HYNLFIVEc)heh(69{nX?v3kVOdSDb4N>96*u6GR3FhL0oM{G6nr=du**5Z|{*1iUxvjd51 zhHm)AN=9tYC{(r!QnV_Wv~Hcq3-V-gWd!Wq;12+lesh48Pl(4(B+hZF*D7$n*=Ek_ zFSEs>d#f`X=!PH$Y8QF0AY(C)|JCz)E}4fL(-2n=0L7E&#i@Wvu+P;kon; z1^ZE3r5HOxxM^@@yzM%tlPk?~2(cGx&AFSMS^$c^3MdtIRt?d)iGg=%@nd0JqWj+%vx>axf7Kx5UIgmkq&(|+7d&qPD@okcte zF@GSNgiyjRoP;PxXtCrO4yiA0E~csj*)JniEGPqanvtlTR+>{SA})2vFR97S3Tcu{k&P1f=u|I_}?8?Fi+*>mqFi(hJ}nN)O3{ z=qNE0@oU%=X^V>f4KTPkig(}FRwf%_uB~m~EXZ4BtFa3s!=q0YO^CdJ~wv-FSp1SeKTrt(khiSwf9mgCkh}YU?dJh1~KIj3!OKo6t zcu}{1rLR+aAychXj8V;_#?@0OWq=7)UJ6*MfdHc|!;=Cnd|gl0LWAFD+GWR1(*~YQ z)mBqL{cpxHMfTCI)<)WB!eh~6Xt2JQUkuN!of68n--KTZ$O3SP27QjwR1+qkw>+-I z!Eg2_K0(P?oky{vqez;fOj1_yzkfs^AD7c?u}|CQIH}~U5chq9^XW|1M_j@BeTtrI zR}w@-;k27uris8N5`+!$;;@<8vJr5`Auq^NJU|5f}E2 z^fWK3))ueHpMU0sd$>PVvfq&OeEExF!}dK{iCSub&8U=v)}vX+Wp%o2r8uZRljY2 z)^`0Ha2TMKX@j^yM&MdIR6P9og=|=%fc@tbnHeFTc#Oqo$5P?ODW|g{vjkY&j>@5y z1JI+sn|XwnpnWfH6=SR;^7m`Eyqi;8B4aLHlz3E#1@h5WFztvv)pyG@4|-muq>u+o z(D&KDpyLfRjaD^YN({G6G`QG1n^W|&(*|zFF1Ex?{v>OC!tU9N=`u;Qk~x~A9iUGk zEf#R)$*fa47mQD%O0Cg$A?D1NPN@%uMG`@7H^D^(6aE?oEBVU9+zn?1qsZ3xCxm%bPK;ZrF)(!93M^9e(kja873*(+ZAZZ#P052OYk zaocQLU7V&o_FzBKeLpt&K`s8CD%N6uC!IFYa{=r8ph=REFRD@iR?aJ*t>UU-wrm+%I{2^!P&w^Nayiui;P3{_DXwzGwJo5$+0JLyrIRT zhf=yVW629DKO5N2FjXayTEi>B$qP~V>zJ1F<8X)hSNJ7dtQ9Eoc_V4UuC)E=PI-kb z_^X|w{45-w?CTF>zqqfF-h4NfWRMgeAZ2%ScAiz!*P`I;aj9SWB=HF-P0!sUr=3S9 zC~qz?Xn622>i>%Q(pz7u82$l!y`x8*n|ti_c@aGb&To%s{t2dYe@mTDhwH6cG=w^M zJNt|=+;2OdUzG(2SnizGA%pAOd%`o_R(HP5xP*>gW*^$g@ZB{!8_|M*au7-v5CA#I zt)dIWsAxr9AE8$_zHjQo%7F!g;>8h@G=0*PWpNMU)luRf|73*XRh?Amm=33bE$=Of z6`&vvs~D+96t3v6;tRsll+ytuDaMny8^aj+`Q#(X=R#G1saR!My52AuHEQ^2YT=2b z$!e*X9TA4QnWfrj#UahQ2=VI9z9@M;sZl-IjS4su21}h;KdP&MzsMDS#T95Pqty;4 zn;2!{_~v$NV@|ak2aa|~!=Q(0Jz3f>AdP+CPayx42`rsXK{-ct!x=<1OY=ua@4CTB zz!(24vlJm20;4;m0NmLfD6ke6L(r-3o1=@#D$gX4(3%KE*P9Hw_h&ZczLrNQd=aKk zi5OCXd>NLOKa|GEZ&6UzeIQMbAxoCW<%w$~U{pZhxTYWbZ+IAh3L|O_bQ-@RYPn=1 zBy_4^`QBx_!E{xnbj+E>Ss#P;VdP+N5w>*-#q%99^#Ra zvLZ&ibUa`!Ub2rQnkyRdI=_F;IK-!w?`n&b9+#^Ez^fV{lgimI(dOc%*2R)Bi6y)a z*M!kPb~i0baLbgHel>^uxa1G(C-@v|Nj4s%QZ+934GK#!gtP319tOku0(MO5Bypp| z3L@H*L5AW=!y zBTE7R;>LTRB>hFwo?iQ4qUoW_gjG2+XStdhBW2qnV|M0JVh0(64B%O@JRF8$J-8cx z_Bw`i@nlu0t#NiIF*8NmM$W^^0UG*=kVbBshg#+Hez)QlLPo|F^K85+iyi9Xczvw+ zhiIk`vs@&n50Xcj%4aaTbPBvMQ!EPP&Bn#}9jhN|r0pfQ?0S-P9!w~UWlq{9KF(r% zZErwpo&2FLzl?zXE8M&`;wV;qE?Zft|3`cCqxLk$`P#zDtLY@e&+U|by;&`WpI&+{ z`b-6%1pb6o9gxJwq-+eDPMf&ZldQM6hZj70e6_C{nETD4Kj1p+Ewd*_R_H@xjOZ@ z09^smCU#)K-xo(YQ8D=Gzl6{%ukdt(n0PBh#-vB$P~?3dSux=Tgf(oc?otOzdGvZw zt-*yl+ImU<{bWjJvk*4yV0IY9QS6P%+aB7%cyw6Zyjj7)79DUu9q8jW7AZrYW+@sh z#x8|t0#)C=WswlhD0zR9bP7pxl_lavKg@m#~jr6vwhQSm{fgM$DLIX?j1-(P<`CLi~WGUC)12yi?dto$1@zzw{Q zK9G)8BD59DUf%;1j zr8G(RQ_`^Qu_;4r2FQ}I%dsf0PknQ}NkSN9#CQy6Y>2y(@JRp=(L7cqvzU#Vf;R5N z&3L?-`Q_w@)?Q=O^8%&fCz>QYLzupdXB`Pn3*6L} zCJ;*5d<*uNcM{>$lySU?K$^9D=i`|W3-w&8UbP3D9J8T`yaq$y9#)-8>iw0PhV+=2 z0~em5j`5%*l%(5+Nkf5A>bs>{wplY9>`b7E0KKk>6`QA_WtA*eVD0PMf;~^F9htG` zLLKfBQYEfK{KF^+^PrE^(NJC=?{Ti17n>ojX+_e{J(k-5;1XM8YH-=IXdmfSqyl%k z^bdJ;h@7d^EH}{>4NuQTj-fo~=b5W(mG1V9X34Uqif$|N%t+jvx;k5p)6;_b5Zmus zR5&}!51Mnxdvt9kx|xdAAUy{){GU3db{}%1e|ZOS{&Y*yK)6{`$$wAk*-9$5r?yvJ z=~njQPX!rtM67NYEqg{Hox%S-`> z+>B6!PZGG>lK_g_Ytwf5B`M11Xaqt|06rjS13NxWoW23Zi}~Q98^0fa0%M9t{O?w*spYGkde6)ZYuWQF5QCURf1tlcIq>|;$Qs-UBz$s$ED zOe6kep!ly8!|&W+nq5q2xjv9`;Djq=Rr^u0za7cWkGh{od#Oa^)bce3O*@dcdgCKCUx;lh*lq$PxZ2 z*xc#HeE#*w?v!Nu>-25j-wlz^(Ds>dWslTkv303!pG^m@+mh|UQ`Pv6g&$jPi6L2M zR0u>%t<(3lesAaMI{3>pa1Y6Kr583TeiQSB4=tVDp3Z!qj1(uS>OPY#y8i0i+Ek{_ z|4evUw$-_Vpz_q8{fdW|L zHezSTx}5RrkpRVGiDKitao^s=$iL?m0s_2*ynwyqU-fxETv0X118UuS{+=NCIand* zEMo{E0;rxraA*Jkfc5O4ofLQ-yoAgdV{DlV6dWV2R!@?sXqoQMCr%9CtuFiHxeBedo1NabXPXnPb=$pxuqfn;ZS}hY z5jZSHlWh(ABMCGLd5Z0ghq+`x??D|(2tXPxpA``zrVJZi#l_Gy+2L7_kag?%Z^KeF z5M&BS!0#52gF!-T(oIN!L4sXK^Pq^>6B_`m!_0Y8#vSp6Dx=ftx=8l*hoQg{8Q5NJ z-aas6(b~+QL7M;SVdL){bpgcF=P%tKo%UXRll~l=7UsB)s+k2@YbmOl5W(ibPsTa`G{1C+RZ80!3_Ce65FXor zksOcc#3~G7EotFZQ4P2BNY;r$e)-S?rVr@;iG^%iG|%>9cQ(LWx88%h=ihy*g#i- zV+baxqLYVAwftEu0te*`U`JexsngD>q`F^HSJf`ywtIqe6gdL5z5`gD4)75!vKg%6 zla~iiM5gHleHT@(!W=zJ^|Qg^U^%$L+%0{z9Z)%GpZ&=c#}DV-%{)_v*DGAf!!(U$ zf7?-we&-xy9v%yTmvYgpjuD4Q7fxb0yTE}6$BCW3N$h-*T)oKMtjQs~It9ZRZWBAM zfRL)dJHYy5{slh!2PQE}1-8Cm1YC6QqiMDE`!=?8d)A6vzlR)mo9rCt2G-8ECpUTq z+`Di77zfbSnxUu~5CXdsA@4YlAI)JiK!(+GD~o2P8NOoVciV=P$=&B#L%%KKJ6vLt z4!gLIBwcrL>m)wFS{ATJ`;4-0$E6`O<7+!496@+Tp4I^r9X_#ocfD@jeX;~NkhJP) z;cN=17U&uytWl?P*&H`F40fHE79Z5jh z&?Y|cEG57Tp(q~{eNd2w5&}y^0|~{|CXeA!1&g<30hkdxX=30#2C9g$-YpKQKnPgI z#NguSr^E&vt9#ghipz#JF&KOTqvWuI6mlYp`dap_yhHy*87`1?3k@j~d8-z2h9<%k zs`CAN2niPbU3Cl`Q|$8|kxvwVk5%kRyg4`yV|Ar#hVA_f&BKC%%mr}Sgc<&4eWPfu zNxGx?`di-YvKxFw1Fl^{kfZ`J!mP9$?otBs7nA~4Ax=o97&_HVr@>fJSnEGaE>TYp zUEsbIT#&4tIfX&OR+1`9GS3{ZJh-3B^_X3U9_G7Zf$72Lqe;QwOB+f4BJ7o6utqR; zj+-LQ=F*8mvMmVQyGM41xS+7h6C~YD8eCZ4nxMIMt=BDA;E2csGCOTRRL2#yI(mkn zuyQ83DDIQT6DXKzB?B}kN;-mlMgl*HW&h(oxEx*i)jKwW^q|QoIUlJ^&s`Y@U9TvB z-h7(KG6V90!1F;b73FnGcloa&izTRhnvZIAvTS>00^5Y*^sF`+{$1r^5tS+$OEy^w zJ7kz4p)<(M6@dznvg@LD{?fcZ1qx(#@5b?`q1-TD=Kunf?`wiByf8ncQy67W?F3_Y zSUm(aw&6Ftr{h6sF`o>|aYidXh`%Pm_K-X}iy`_9cIrfQ4?U{2xdYH%x*tv|W-gq3xstwz3h@W_^AAD=AOq{yhB+i_UcsUkuy7_=N=-Zks z)TAq1dLu?Hx5~I*J8@B2Q%oao#b(`xsJi8@qu(LYwVRYV>j}(;T1MqTn;#aUy&XqA zvdsBsE9@!{TtZ;)bUxPmWY{|WJX@gKL)cBW)bRZ6Sc$6INR87UBpYGZ+`-<8-^FxuRZVGuRf1IZUZg$ zKCbZOGJHR|JdySa&X>(m|99EX^EUIVF`!jH?=F+XSC@l^|L!Nd_#U63k%h=sy6a)f z1=jZ6FBF*DY^nC2=ZF_of4^<2%a*Sy5Z%_wj9w%tty^5?d7-gT3{ZS;nMH|)6KXd= zLZoPt4DZ#`^rOHI;S=1ojTSG)2GB?uq^dy?Csm{Wlt+36bLwPVbpP-K}wov}#F!rlG; zk?+F~hc5)7U7Fz+rdFsNxP2!vE<} zEBJIlj$Pf)P)cL9MUJpQN}bWrTT=$Jo<8CZYc7I?5TLyr5qf}#K%y#Swoe-MQQxrK z9F3lRtdw_6T={TbNPF1-RZNgqmP)l%iHJ(-0GdMhyOe{Cj^p-z}D6om(;pHi6l9(k{C{umx_pof2lC_F0NwV6H7dnk4@{x&?2uz?eV*Du57V0Z{lHfr9#ez5TgO70sVeCpe zKRhG%FpWn~vA~vW2tqUjSydl- zHY~c2RSy?7`;u2}!siv3XLe=cS^&o41ZpFq*;wb@*%Bh%!=E9+1FeaB;jpLz`mzVoAFp7C0p28=H_E9m6kCVGp+cOPIASa203;3j~#Q{XZ z1b%iebyzDiDPZ*c0io0k((nLR|LjxghJ-^;n*vZ3-VV2{;-tH=6LN?e;-_-(Y5gR?z}zBGqS&Ds}|I)a#^;sPEw zORQf+2zl0Mk-(gPCbcMoIr{p;tq2n>DCXY+rcaqvgt?3$uaKWc;H#nOe%60lMMcfD)?G$T4r6zz;P)~qWW~% z75ALQ{JgAqC!S1ZJ8&^`Bh-q85K1ll#GN{}L|F+YCCN^XP79}?Z~j#7FD>OHjN*mo zB}~)Y@}%SOR9LuNA`)sBNQfBm8`)jtsrow8uLR%jTCc@gzdfLVIkB`=%}g9T)k4$PzevpFB@jnJ1${p2Zlpz7G>Kv~;-ZCY zMvXYB%30sOeUyYS*2~XLJZD;7ItQiOpTiXXQ@XxO+s9&rg^BOx_|i3B8=z%vBGe|` zhfz5)Ax+Hekcee9pQxzWe!9DUkRh7R? z^fJHV|5FgibL9wv4rW3vT;%!9NJNXz!`L!&I});z)eICPbwtj-gh_( zwB&t?T+;}l@MraW{GyL&fJj}mQbx6&cS0Gbl&<@|@(~@zAcRo$+5G+0+T-`H8+S zFpO(KWjRw$u0!Jw@+3t=wWQM-x>Y^FpLqnxlcHq>^*MGeV5D#*+$-EgCgh#=rL~_W zMDE2$i-p*pH5djhNMlsKJT^Z0cc#m?c6$D_NseC52xA{D@AHlyQTUb29k=E`YZ^43 z>;*a671d`Qpv+a?uvI{;8MU8pKBQ(s_xVMu#PJIz^(;C9Rzdgpb4q^~ByT=vuC$x4 z#Q&qCf~)^DJClbo5#mU6%9rDrE--{}bHSo-s)>u^@80a*tx!|jKF?Wf%Bm+tMEK>)PzqjFJo`&nRThD3X?h0Q&# zcMV~amV5;h!Ti(b=u~m0db~Y=Y(*hueVfu1Ef3lO^31*zD6F)&Zz8FWH6X}a1{i35 zAg3As#(gkSOb*{J_yM8*T7vjiqQky^+f4Y#!sy8A+mTJ)k=?(I4_*3%5ZaYdHmrhQ zQ6r5CxYBe@Vt9jLAS_)5fe6%bg%W>|GWO4JDQaa*(PS>czXLeGpM>?E93@H|Culks z(q^St$ZZ!lnp;_288+dPHDS@q&z?51e>?lg2`J17arvgVl!&d=pj{pG4V3m-ptc6Pw8 zbQFNn%E_-dW-q_FP`M~aS!$63ob~roIgu6h-tDCkBREy@o^DGo_=mHK$M*upJP64( zEbsMYi3z&m!JLr07^~hAkj}FHk{x=(L2=6^a?1_rSk<0B1V60{l2Q+8bR+(C?23@A`cev zw5k+w=2{Z7-{~2B)yGVC_c8$Fe z(tWa{F5PoyrVt>GukEDIYAnFZzFEy;&E%_NBF zb%p_N{;chN)}~kQuIqD-QS0`#&s*O1BNPS}4gm=T4Fd}YkAP^3I}DyahB9S~J{%c0 zhLJiG!Vl_aFX!cqrRN3I#?flSA%_8pGvF2Z1c2PxjFjD#J4pqMan#I3alFD-3b3q= z*alT)nDvOP4zc8gTx~qx;9-sfl62rjb z@+X*xg&<(jYqlkrN`zxjNtfK7h*j%iiMPX8bK=9&zko;A5RsC5T#6%N>?nu(aO31F zuc(JqlwngU&Cm+&v7>7J6W~!H5g_YX^dn|B(x|~hh5U4EheW8Yt0)Vi4LhaiP8^az z=^x2C*8O+~oJi~0GOf-uNBvgk-QiRLoy%en8grArRiv(wuR?4&a0s*vhft0G+Ki3Q ziECY1>3NS*P+5}EJviP+*>@O(%j;CH2v+Tk?D-G6?yuj1UTuK$n_3^m;)oAsrFZW|mx1cZ_`zPdy*Td<; zOLKOfzwgWM{jv1_O+ft2|MBDV6AVG+KLkX+9+nG&c}=5SF%Peh{8@T4m@z z1O$TWFlsZel{mO<^MnN2?~k|<>`#-J|6@R?juGCevxq~xirMfG%{(NIlP4;uO;Bdq zFHTSw#x#v#vJ=d3u9ZBF)ZKJkElx2HAgF&45DZJx>OjQR6XT0YjqA6ZhSg(} zxu6B3Ap?OyOOShS`*vDuMeCAb1qRWEg`9w5A?vlHs~i7~T#k{(>$~#R-(^$)8qB40 z+gYjY%Z$JNg>)SHwoRRw-ThBGraa{RiAOc_^q<#l>J6qR8EwzB# z1Pl)_eJcGPe9Egtc)#*_UKjDHaj4&Uzijlpyf$mHw(xSxdFq3m?`GZjQ|uD36Yb}( z^N*Yc#P`#NeC^!0Vbp)Z@bmB6Z(@@DOp8v95Mu{%I0fyPq2xziWbd>o&~CsYt0N{9 z8pTll;h%I-M8||+H$VZFvx!L8%rKp>PFP|`0(MBHlF_8y4pJrv?s9~``IB?sUOzNB}3r(*C-R2G-&afrPi5@JU>bUgajLp^h2 zs;9b4W&fLG4N8qe>{ncsAf%M2e}AknV6#+0nKXVt37+BM;;BX|wb&u~pP|xZsm40C z7-4;_4e{WqCB~(cP;#Ejs%ELB)}@p(dYsFf;HhWMrj&8Eo-4X!spsCLlnXwcD}M&z zX%r%*R!DMQs3vAc&yT0wJ6P4-CNYwFi*W8bUD%^dgT|u?JQf zVm+?RNb%SGW1DmPyZgbdTthbl!F*V~1MN_t^PSp)3BaW>7rs*)JgZ2a^($4u#+GagJJOD_&nTaj!C6^6@} z*P!g|B)2O)|}6z0w#sWZckV9xXnWpwg!QmIWEc7WRA^% z+=fS+4jmz7diBwE5eG43z!Pl9ysw1Qbc@zzKf>F3Yc@yAX2tl`Zu;=r9a_zRPf#Vk z)spDjCdi!iXnV+AxG;a7)d9F|ZJ8E*_2A|dskW01Z{AS{nM`$}iFa1(>IT@Y85V{Y z5oED7ynFa=GQH6fWNoBjvsVCoajnA-m8!Y6nr4g>CWZ!h_%i}}pLk3Gr|7PUhSvL+ zCkTrr860>6Jk}Ep=rJ3d54-MV78E7TG|u8R1-za@#gr!r)ostMjk(vj`-^RV=iRU; z$-A_qPJ;WANjPS}Ep{?hJbHI98GP0arzFjCTEA0LPG>{n5wTLFMDEgvh#%77{IVph zZfir$bN-4-iEbgywNIQOMC7-Ryx&*&EpJbzT;sJG`?iBC3RpmDqfxv-y(wjhj%zuJ zbRb}OmH!=g&Ya6R;ly4Trd&mj=aXJA()jLYYa(h8{Io#C?IRozVZf>EHC;g-dWSW` zO>V9~XJgov;*jT2>yKKOQEo`~}+$!C`C{lU)%=`_vB{PW7l{bk{8zq`U|{ig!* zVV3yGo)*YzxmrKFteePd06FjW5H@UO0k>`HA4P)CsI#fWj+OY5CGod^>`W<$4u-^p zJ8iP&?IV9qs_S*K0+jcow0q70!B*|J2J98^#J=luLbngeaLfZ@Q81SoL}?R%(KMKy zTb1mgVkPFH=$r2y-`FM{4$Yk#M0YJJB5G6JuwpC}C|3_Mh`Ly~y}tLrro65_WnXb! zFXRV2)o*O+k~Yha=NhPzv~|yL0q~%vkp+KG+lXFt+#3zJ*3|pDkJ5+*uMLAWo=tVX z*38ks4l@h_V$8u3tG&a@Xl9-MayWzYq6|cV+v;DRa(qU2GyyQ>%)m$j<3oP$3z4+9 z^+T9YzXdP?4jGeSP=HeOIcbQUYz6ai@MtJujlcv}$KV!FC2Z6@d(>rUkDSb8C3qnV zTLEy4l|B55@iS^SM(C<3*F&P^$$ zk`m(eEz;es4w6ZF-8`Z%Boe8FiIVg6eFF;O9m+~XA4l0tKb;)lPSkITlLir$wh@i- z4vm!+ozn%Kw-H_N4qcQLL(&C9wh=?|4nvg{Q_}@grxDZO4%37c%fbcArV-2G4$FlV z+rtIhyAhjks#0zmJJbay(xs*+$_B3yC)EWv^YbpBrw+G}6|ZzbKhFiP_71P{PUn>l zzq1j)*F^#_%jI6f>6IXWhuV*)Vkrf+-PcICeMdNS2%A(rwRc6SaZ8Xby`>UIhvGCd zjz9#)M)GsvYP6R5acWQjejQjl3b1-#V}Un6Ack}$qgBK6`~p74^Zq1YO^OhMquho# zEX384$u?1>s}c#8LnV$6VKgP1I#Qd<`^-;M*fdeOC6aKnnM5$&SGhdK-3D$c2mG6) zifp3sP`$cn(gaQi`U zpIzwKP3XK?==wqEPJPpvP57-@xYkw}yo6<19!9tXz(Df3XI5=FEP}c$OqhZRh9N>D z({9c#UXUcz7bnT|D9YP{N&YBI^BKV&Z7sp2AvEaR7}g}NnSvp_EKFk^B)2SXs?p+z zSf%DJ>B8|Wbqf}b*a7pU(UwgDFr58N+dyKhM>K70?(F)v-nOJ{OdP;*R5&6L8N#98 zeq$hGgqFSF_keTg)CAT&+i-YK|Txa*%q`aHyG+#VX<^U1%7#U48 z?*%hfA3Ul50EAWXs{SP~H`p=+LZ(!H16Z>@9y_W*o}N=rqa{Q2HQjrzo#>;>oE~d6 zeAu%*v4m;WzK%&xGkzKU90zxd;RHDxg@AdPe$_e@NA_aau?z619$oq9e=bX7x`Wl- z9*_))Nm}j`v5`Wk%suhhXH+qWhOs?@YJMV}#Srw1uqQ82UFkuEzfeWWeZRurSZM;0 zq2F-&n=(jJ*zbk0(T0&ZB*@s0kJ`tynnu@5NN}$Ho4r_#BY8MD)k?x0pP|f}y=g$g z9yO6NyI~M+!f2sA>~RelUW~9*n>BPLdeofYaR^C+wMrMG@|kdcg|cMDoE1S^3bB_u zrEv>r7Gr$2$+x5PSHr6cvwqM7YjYxIt6gq`oSL48J71V^recPnInr;#h%>2mK9LYl z()>^n{1@d<=g8vydAMrdW-Z#!s~_axe+zT3#WTQYMO*l$;lzykMwt#2s$S2tl}bi(3;yO3nckm6er|2wrBMI#_dqaO+ZC2Zp++|>W|iEe__KbW4;42+yJCo0HSx1)Qug6$U= zb>9n*TBfl-^6R6b>&t-idqN*aC1wB?m@&Ddo2+MkWO$(mRSkBByK?R~ z=olf)m#vjsmBDX8u$r>xJ_d+3hOIO;%j^-Y`Q8UX0BJ3XveofXIwDT+9bQXuBWdoQx8^r4mM?`$ zv7gK;6Xz{t3svp1mA)y}LA)kg8VcK4^JHuFf@U}-fL-LJnNMBTP=Jqweah$ zqy4FU8?1cWy}R4}KiY%%J3@UsBD*_cKROcmJ5zl-GrK!;KROHfyGnh#AmOb_!Zky#5*lYe;W#vvN7M!T> z-A;|R_}Mm__}z+h(W6zss$K9*Zf5NnXIqhPC9!8?+kcNdnkl$8;bUX-ifa*-KE1he z@o;FkP<(MoUH~q4k9DUL_z>#n%^JNu>+p7aWX(y_x6UjYNf~@U+Jn^Y9{C*MtJ!qi zyLZ6ecaj)GG0g9_41A6`z~|xw!AYeO_0HvzT|k!)Tw5CygE@D zU@vLqq_J;rw_6MG_E4`T*Ys&w(SvwkZ*1c48DyU~rzXXM$+a+h`Q<0~<#Aqvqk5PU z3nXOr4)QaE-F#&qP)2ww%1moIzj${m&-h_uaQo#v(*K6=^Nv*bp7O^%?azD0udgEE z2hJZ4ygwfVKOaPeA0>Z0%Km&*{Crdue$xE$r1SI1;Pc5ucr!3jh=fl#DLlD!RrtXF zM4bQG{}U23MJCP#^0@faxUioMBbQKl1{QTrA+RbG~n) ztr-_Uk~HwLGVs!p@@UROmYpYZasV}0DE=gh^4!aoXky*pDfXGL#%yaESj0MD<)(Qf z=#$FOq$E~RZjl*aVoFBBA){mC6O&WZGqZE^3yVw3E31FgGcvQXb8_?a{Sh1<9iN=; zD{ozbTv{&7(<@mpD7*02Pyr_JJeYK5mYKK-Tfq>V%Jk$_*J{|9RTxj`4UeV(tcWTK zXCa7(LIW)*Q+L5ee1WLIT<*%n{b6h;C>VVCZ}JO#5O~6~07qrQ&C--R&kPtMojc7! zkyJdHVwF4XQkhb|Sga4DaW*nBBa#m{#Tpnr-u*Sae952hqlELi!Q7U^)0vYDb_zrr(7~FhV_hb zC0mV|;h2RK<9S-OrB(y3 zA0$CavXg7r1rgwU(Ad-gf5P$nk)XI$B~LttjeO{vJU+ignsSI4`sbjel(7CIlrRX6 zOBE$ak?;w}1oT9JChYKC*GtolK)7WYW=T3_oC1cPsp2fU)Z4_=7w9t#qm7m3$?ihd zhpcw1m4~T6-e`tni5Jo1(YJAVOK~orhU1|2amfqvR|sJ#N?FMEXcVeiX=2hWL3mXa z#YwtVmE~EJIH+NCOD6acy)tK|Y+3+n;rWug?TGJ0x}|wQ8dWp#JJF~U$)H3Uda$I~ zM4G0gwFmg>VVMit1Vtniix@h|?5u1w4>aPc!z8`B&eNjox~{njIGbu-ka?PRjqH{1s2X(z&LkWCjo&;J;1jXtDGghHa6PQ8wj?WJ^LN^%>sI3! zaWFyCcu^7WsN}Xq`|tRdu%PO`(8)ustauYK_N3vji?@al(C)bBTa9y;2?# zs{0kVu3u82?mGvY@!ZVr`KaAsc{-xHaWkvQvj6^mx5I~*&PwRxPg}Rt;`pxpYo>(- z!pNrQI|N`jd_d-Ox%(SY@8goXQSVcGFX|`v&=1ei)NlF0d4`)K^O67~8zvT?sDFbq z?^T!l(s&@T@jOrT2FsWAY?H{`EfNPT5qFz=orU|;s0B$0c0-%s6c*PY6%J#*n5k&n zFH`{S?cDR%=6?|o1IVCT+-)7{vdR98<3FlV zY}A7ynkMHXivDpNNOiQ$Uw3qy(DusCp4w>K6gg z`K-nI)TqXV9sM5y;$9z22mju69i#q@?SBY}&TO5Mn)FcyIij@x5D-^k)DZyra>eGa z){Ozze-jYuS(}v*n5no*4%#jNJc0io0r7D@_XEgL03@Ulg}0p#CgUiCGoTU2znBjf z<0wMQrIDn!U5Ga2D8}2Sk>N&vJiN3K@(A*t&wuiZm^69;juiVoYlJ9 zbo`l6XeOkrqzW1ncO`N%)I0?SdPk+vS)&LwuAFtQx%8~zOXVvVf$83zC-~-A_03RH zxycyV+a)Im9gCceQ3ecjsdVF9%Wy{FcA-Kkr7+W-%U>)TgBAbfx{1$|`#xK#+K*Ru ze@>8fylylk{ocsjAXi(H=CKS;k`BCfBFw~anU2*{n1T(RZ!;m2OLVqe-hq{>>Xj@W z31DSwh6!Vv45S%rw|!}v?pkPoBW1lvf10&qtOU^2X|~&WDB^Z)HPDKou;6QZZEa`C zw)eTT+x-9`5E00b`|Y^u-U6TN`NSDlI)b$SknwyDz)4MhM_?hmW{pUscB!UcXdhM) zu|inTNl~im-a`)N8E(dvwNd5=Ou(S_dv>1$d>+Hcy@G?#FlMhM><{q|Uujjh3~5x$ z7}3-!VODaqbh}47fG0c?a)xXwqc$u04E7H$byW2O*i@bS(!)dYIyrn7Wu4@&RylM-#- zK<5L+a*Uk!%Q0hVktNOqVRgk-`9>kPi^HGRfe>e2_y#{2R%VSw)ahB}5L!}vv)33? z_Sm=8jm5l4VDpgl1Y^RgcuBdw+Lv$@2=?2wCXagV9`2LYpa zFCKZZdxt=Ye3D0$X-I~=iAY&>x}>FQ|2=O?z6MI#FfdBe~lPaeL_;JyV^TNtgh*W!LZ!ML~aD$zWr6O zBuf_L_5`?E+~d!tmIE9E$Pa3M$9ux3 zJV&_*Jz9A}jip|`&ieIO4_ZUatV?lt>JZ@$3aSOH9^PYT8jSxL-{O7^11{#c>0 ziO#O@?=_nqx2OQo<~Ik1n;m`3(E41g*Z=V&mU*tDuAXX(BT@Q5cDs-&pQ5Z}EQ&>E zK3b(89^Leg>Rk!5{JPKcs?0$G0nrbHZrSVtn?wkT0MbeAStMwQWB|!RILCG8Y|<$5=pc+y>12N#62Moz9#68Eq00UURz+ZDCh-avgU=sac=KWwt zBbJFIz^J`)Mu~s1L%x5v21g8c&q;pG410%9VZR3#?bwF*g`Bk(z{1!YU4oCUeXRq@D7KpYZkQ;n_%3k z1Pmp^jnIf4l>_RyJawGC<>6c>jj(8*>0}%rB;USUAu74YB=l$zr$Q!k+1L#WNi+>9 zH_9$87ZkV6-i`w}QW?RghxsP1p$Qw30mlZ>1?d*au*9~Fc-XcguQ9HOpBdWPa8Um& zJJ(Rvd0}ItDQ?Z)XR3Zj;>d9%2vcU5>WJ|6_K=<9fW~X8DCCeyXhdTO@3*Uyjr~?Rwqt z_6f3|R}%#c>YvOJp=tEwv>~C-7N!_31X98!YAG zYjWa8vONX3W$%p7Pd`E_oK+sl=s_?l0)_-K0Zm)|(6#G)uVLsESgm1efS8Pq*y6AM znzLga_+upYFs|qW7bMUMw9rn58?zD^X88gvt#4*29YzZPdXjWUscU5##~`RzJV7Na z?)78iSbSBi8IynGqFhw}W^!oG;(jO|F{Mdz_HLSUY6 zprp{_$aQ-QjsKMzvz1X%CeYw08-Jzi6Oa16kCnLy>EuqLQWTh?vKKjxouDYVErE*v zRDB!^Xc$V=c#I?<#!e_9hR-B=HG%vsVIfpGSpFqHC5aPWRZ2NdRDmLGg{NqLK^8Dp zJb1JC{h&|1Ma12|hTMJW6Vo&D0PLd)lKIM`IaP#MKTC{zEsd@cDv4~;8=?k+%Asp> z`Nd*RSL8*=b>@Dc7(ycI#5koIrT=?8;kiD31-Uyemg8{+X0MfQorDC16<$s3S}xX1 z>gsl7WxhVG6^2qi%6VqpF4=&JrHd5*q-aaxri@pmXO~QN2GVwoqV?Yd&0+j~1{>k1 zVX0||Lk^(g*AamW^8FivVAiH?!Ex#Rwk2d)xILU(5gjWEg+?XjI3p2P+`L)MsVP#R3Oy7~+f!O1A9_U}Xe^&C#8%Xc2+^lc>M_;ii zRmi6WL`YK7p7O-g-%DMvkd=(XId#cW9-2E+x1W#bNq<}V!$c5Fg2O!6Kp z?ply1bSk?x*cdWSy%?FzWER7u3fU;-+LzE!HJSojNmdtMI6)8zSiAbA! zQscc*(N3!F&2rG+ADwbUkA92t6E@#b>Eh=g5@n9In>|h=Qh8s;KCdOzjwLZT&BbR$ z8C~?jg(HY@e-iu-)dV7F3-4@Y7BGsR3L&>x>82zbjhpRNl&FV#{pAV`(kb`}z@hEr zyWQ$X8!Uk?3_;H&X-Xn(lu?aPtNt51P|NUqYmTn(qKjHn+;RsLyvkGl(EYYJrw7>{ zN1^q&b9<9k18|`aT;VKRX*{!*%VNc)6zMyKg{oaLTMBv))3y3|H6t4`sesBYN93)v z>xTq#u0>*uh;fdjuWLo;qeVtzg_bloSEHbsTa;L&Qi*nL&;l#MTbYx!M|j=14eG6! z{j;g>Vywil8 z+sR>WnCXo_Vzufmf1U#kUif5V`h?c54 zZ_xfVbI+6Qo6qmpe|R2_2PqYLin?HW5@U0ny9x7%LaudS%0&{><*`tgoVL!IF@_Nr zwey4Vp%}7HnXr#s+m2z5?A771VY@2>QizSv=O!4$IBuU@FISI#- zCs3Ju2Gf&n%z}UxOdFUW5!(rDo}F0ji^)9BNn!($7=}IcmK-Y`_zhT=J>3Vs_4LJx zW@ODgMNebYXdM~(TrF0w)^&j%d3X3t?q(q60$=S_qmmK*r<|0f%cu4I$u$W(6LjUN zVtG58-N-Ev=GV+Z*%%Q4TN>{ww;IGqOS9#B+MKhL1(Q_}Nap-#g^}Wzs3@z%{Pdw@LEB|Bvm`l9jtJ(FH^I^k+gWxx$PjHWO#E`)YLB0ln8?; zh$kcBDgwn;YJ_i8#{CGdTy`mgT|=&t;MW5fe-5GhJwvM9dcgVno%x!po7u+hP|kx` zxIOD4+ohKKdeJ9wlJbg^)bT@<*VR(1BMN0|S zM!KmjBLMKIQ?v~R%uX^Fm;RnM-gWeq!bfS0$y`i^Mh0wO{Bw6SgoQg-e2L-SefO^F zQtDgn#FcZ0jt8PzEaq!I;(%h>Y6#(Xv#a4DuG7QpgHz0LXGL;5=^+@w7&qQ@NDIIq z>8V21inVJ;GpTwwjr=4W6S)O(K_UZrxaFdHJ8RNEC1$#Tw3fm}0_6!A*R5H7vilet z&1?2DMifuV@^@WR?g=6^_Pw*lx2oT0QTx(%p1KHonjwf57=dUAg@vZgWpOpsdK7=M zp44_JH!0!>|LmOWYSLkqekoDCjvnBW`V`jke(O&p*+;fkpjM_foRGj?!57b|mvb)8 zN1{1af;mIZx|U_$Hx3BT^*DMfi0$KMfbho3f%FGcz>j!ql`#Am76UyH;y zpAM#wPT6+0IwgxTi?>g95@(7r9=?d|Hq@8bsGLMg?5{zANXYSfJVX)I5JCqF^#BBs z;6rhGd_-~^wWVsd4{qCJm&`GaY@+*rna;0DblwDm_8;SoB)KH5W+c1uh5%ce7q#?m zBKfMqk}@iKHb#wr=O;4PUt&iE^)%&W!vP5ArKwFBPIoM8L7JjY2%dL0JIE3&zchzE zJTaOe8@>lst#QS+%coO1&oK~0d$Y@S4GaBls~JN>)^o{-JOruoA&%!!8Or46d(`e5o!I+mlFUmJ8TTDQH26D* z-gDKD&ImToR^-xy8y>G{c0HV7{J=Ux24~tSxSwrafgQXK(8y#F_kC8+8*%M#K$_6Y zuD;;z0Qv`pB9C#Sk4a_$>FOSokC^gp)?(;-?^Vzt#3v29=E7-WNxt3+&G~VIlV>yT4AqdtzC5cD+BQ z$qAvG@9cqso39M)HXU7D&y(EIq=qf??E9aIc8R^%)+TQ#Q z-rw+Fz%Dy`Si#$SHbp6XphL*HiO9X#sC}pB1YVB?U6tP3)x8h!{bov#2ESQ&Bi@}= z2lV~uQ}Y$dtR5b&el{*whGpjI$!Li76v)Zf%u_C|O>Jee^{AP$5a#Bw{-!!gak16U za4|ULitY24$~$Ne(V3YKUzf6k1o1fB#O3|3ZvM|_;$E-hVqaFlCS;M6SndEb2^Iml zfc${dtiH>9K@=Pyyy!v)3{K4Gq)KB5oPc-<$ej!hK;6#6{3s zQ;h4B*k|2Q2>rJey}}FK_>A6GJdpmgy9uyW?Y8A(hv$XX(lgwXVy$nAz`_@z5Fxim z!P&ZmH)AeH-*3JJ)2cB-hmpbA6N}bG5-0}K0D4ab-~;|J$gKjTdKX!?CH%6(0=Sad z-yalvwF`z7xdJ|d$Cbdh88`a#^y)#TC1EuoSt*`Iw(5qf&r0P?ImG^wWeN15Dhp+f zCI{Mq2a_^+Kj0|(U{^(x$jIG8LJPh2W^l;t$ip z3kJ&))S&-DSf@9IBzF`Y+*b>cj>MCI_13UybF+7xahptuST07XM*&ra(cm<2~sN^2Q$x z>t?y8J1!u9bG`09zPp}mCYj^dn}2MWq_o$86R2Sj)vQxUC!thhCM8v~}m)umGuj+G7|} zq;q7&@T2v&eTME#Ps_YGi2QnRZ>%Rt2<~_K+54sx-(N!@bAP75!F6e%Om{uu{(O_U z(C5V=eJY}VbUfe}f;&}%?lK*!PXw8a!@T7-kpLVnphysU!>;(TvwnyKd*!@U0E9Sx#}VFkZr z{7()LTyDtgDqgJU)yAcxol3oYI=adwT=kXd@uoo@w<$6k0V0x706M=qVU@?|Xo2~g z(Fpn?BrEO(oHAq<8yxQ6%#=B8U+|%1^=;LAak{y~Ha&9`7Uz1Qf*fabG?_Cc32jM+ zZ}4Wa^qlDN{g9zOcHbwiXn}YlWW7xy;z+7fNN2`BkNnj7gVbVT8^1Bakh99u7`arM zM#tv3??-`Y_X`3)35+Xxtvq@~i~{BW%y9B3M4C?=j%Mh{n(xcq1gGi_EtLe|BQ7{}fj zIKg-Up!AoZvtrZ{$wQwL?N2Z1$HfH{$F~Za)=tfFzh5Il-cUFyW0)jaG1iC{8#dqF z(oh*N;ulUy=fz)`b*-7H`qGguq6$E;U?$yz}?1!1BuLdJ-nDL_nQqGozuMcDx>gJh?O2DL zl>||hL`&?6^w(^SG>!MlTiBUO4t;+mo)fsj5MPcB7m#Tp#Zv(E;*j-5JrSb;ZGe(^0`E$rh)na1R3_%GjKEzw3y^5ke$!h&CBW(8*0gcdf24eOS!#BF1x5k*ueH z%?9#LF&Kc4skm4#Mj5LXjx0>O@tG<(aFwBuLzS6oQ7Hj^lT)|vj|Y1!CY_+owd=a{ z4#lu^*`q-hvkay#eJpdj5w9C@U<Jm_ak82E9*B=2}LHWy4{*wLGtawc4T55W7lA?a#gx+hDLdaz)X8f=};Z-P-SoFYMotw&d>4d6`fsO#Dk( zeqpi!sc?~zcO?0f2&Q!vbwvp0b=|u1t;>2;34zGE-w-UbzYWJGA_<*=FPTrv1(=eJ z-s?p5z`rTD_avMS%xB}|SG*dztfI-?eN_n(6@PvC*$=X;DqEZ-6l$gBAP@bVtn!r? zb-a@#QqkSl^&zlyQZA5fB0v7aU`?8vh|6pzjn6z6gjB0ZX>@_38JP^YK}P z&G!FO>ir@hy2{1@_uk{Dw)_=YtL>wlY4~Bh zN>1Fre$KK91_@p{!ltf`8M*;{W9+{k@_d=*10~gG(2N%S$HMF=SFKq~JCEh&rVrM0 z`-q~0OFI9|O-VuLO79KL%RxLn!rhg2ugdpdn@cs>)xA%ICn~=;cR!)L`XPm!LD*Y+ z(9&Lmn0?M++*|v|;ap4vC??$0dbalhU`2sHMFpHTzuC z+P99G!@Z|1gxs=zZJltBdCz+Ex#hiVoeD$y%!dlO7h!LoNlW`IruIEX8CB{Hh&m$v zoI$%#@tIPpKSyZo^QiOOzGVO7)>5qSbe;kn%CNR-e>XU_OJ1+aH0v6mEOp6XN(eRo zy_#!0aLN|`vX)t>RKnWWJ5eOLq{1&vFFyhK8B5#Hj+y650K@PGzF9sYPkPGH7(f&+ z(c5iDfV5xl(u*+eQ9*SxwSV|4;+tAw;ftilsy!dqq7jPfAdsVcCyTTH6U7Re2?RmM-)qo2Q+=IpD;L>lSth05kvMaij1NSZMlOM8Gr%x>iaCylUsVg$u!M|2rh5=u2 zypIA8!C?l5TgFB-CE9S|OnQaZ>*tIF_esytkKfOVTXXD+b{L6g2Ox?d5$V87JMltZ z$4kUK>c6Kabsh})Nr#STU4SXaSv!Ct{8moxM@Swl@N8O;K?7qR7_sV>9%4GcIt-*; zhGGw?_B|6z$|B!M?iaf1(t#Ibg9WE_7YECUvo2;y6r=dsyww7TwiXR}1o1iQ@atr= zh5;*>2_%pY+2|u%f!WMxo#GcVea~iv!M4m?ONiRyqCBANpLo&V6NHFN0HP^FVvmfM zB-E+>BfEv-=OW}3Ae>2`{&jX7;T%#ww{ocgO!GlX&q^_A*kN{6F`9Mp>WmRBzoDOJ zI9R%LFLndE{0!U+iMRx{CpaSmpTJ`G?hwN1;&yLXYM|IZm>vTaY3t=w$6&GhY(!od zQUvEO2Bm`68CIf@%`K3SxG-t4TL=VEFQr1tn%u>Ij~x37?tjEcU5GuRhBTjy9^jtz z4F%`}$j=aKZt{gnE6gZ6AASEA6BmenwvnNON79~1P0{YnL;=P|j4RNLi24Cuc(MZ; zp}jN$lQdY)x*^udOHv^k$ufr@DuypI+Mbe+zl(Kg%?y zmjbu1#A|hinzrnj^Hk4aL|A5S5`{tsLC8-6k)t=j&3baQ`}hiiSRZ};NGEG+Q%+_B z+olSc6)TIbf;a)LylYBRB?V)WH;Vip2{t>4E#HLG8l?+&Sq_R=oh&gGKeF$15It@Z z8V#7B8eylN&>o)V#N}iM+NlS=2~4!^x#|3qX6V;x2$Y;TK^}xw@mU3VpkzV{RP4Y5 zNAtguNbG&+RtyOE?XuPu&bQ#EEQz^|qp#r$o8;o0#{L|mL_+Rx)99u2U2-K#j|f&_ z+_=EZV~YY1c0TA+qbjZiAIoAo(R>rjFs(_K8#xFc6zqFeAzQGu5z=uxa6FCn5S z?r?bWV2!UkWwFUzjec3?KrKyioiPe*f!t?Q8kAVNSl6Bb82}fB(~8)kp1iOm*?!Js z5?x5E!0;r7RwOe|uOkWL4+T|RFEIkxA(Q(ht4fC`{#QKbkuO*nD9S#wh}0uxwI_7U zgE#_L@B~7w6%TBRoOaV$PUS^=CPCei4d1Ilyiy;S9vJW|4khfxA!SM%W)rS_^c(R5#AVQ7SFdJ;s}xZ>S+tP$ekWb4-2{8#o8JUm}ZLmo~bBUK{$H$_R;!i3`BG?P$nJRq~Z;P?Jid0r@vT zG41DDS8q^YXzQ;jLD^1Bb?jaxQu_pA+6He3-EIhd8iD!&19bq8J|>|+!QR%{D}zWv zZ6QdXYo%NbAkP8AJ+)tq%DR2ul7iu0)+?JnzCY*!r?g2JDaf1tUP*L`4-5fia~vZq zx90Ya|9TaV64)RB>}|kRg7#$keH^s;Mq--#;XYdmI(y@O{Vn&6(WW8MTp-nsXVepA z88>SX3N_Hi8-xPe>Vm%-(8|z0Nr}cX9_%o4pePxp4 z2z3pv%$xWISWwU@*}6i%M=|JA3N03q{EeAZk1$#-g`Zd7nhrFI63aXiRR061cJL{a zHe({-|7rk<#*fQ1MlQk(8{D1ED~lpH)8xMSn<98ny|VbV^mlgAdLY zy}R+OH!%JY6m~bliBd!irS~F%fS8#(w_a4|BYZ0sw8-Cu!2#V-!_wBfI+BODKbCIbvgVUbhw>pZX>hb?-PmrHj$kf z7225~b7RJVAKa@lq@WM2j6!ZWFwOeB2=-O0L7VBe4^_9RZ1pLlh+7j5 zai*nOtL}Df^cibJ6BL1~#!l82BAR*7-hJ|8Z;L=5`tEqaP0IxOSj15Vx<06%ZCk!n zhoo5F5NVGuK~gycDw{zyN8rYi)j%&4YJIf-1i3C#O<_JDg-jHr5#?v_lRi|~3-Ve6 z@J>#ds+d}Z*&PrK&IHpUlOfa7Do_2a-nZEUoYEpAw-uStYO@X&*#i%m4(>$hdDcM4 z`IBZmGnRM2ml`miW*M_sUJT>7*pIUw%_q8J)lTqE+5FRauN$U)yNhjk zNWb9~Zv}r<4v#u-?~;t_D!xx$eJg?}QNOksWXyu{d!t79%Q#F=Ppkv|p9Q_BgnR1PeMK6IoP zNHAKtCBoVl&kSeET3MIwR|oU+Cb3~0)>WJ^P$H9#uid-UeO5cxxAr>@Dnh?)GIqHd z2qaz+?4g|Bvl{_29QNFp}gIn_wY@gTMXF{E@q*&gO+G)Jr+bl$J!yF)mVxcwPw~B-^h+MPXO0Y3n z-O%+Ymb>eR+Y%$3^XYK)%C8iyU#lKed=H%bdTY(*-S~diVtd*rsNP1h@&r48MPKs; za>K#oEBzGdzO~wgaDAQfg?`XizGWhs&X;8oAAF9%5F}*@3x{-U?tphJhj2pfKdnX+ zlO-Oy@pwO&3h;X#{(BeIF-PibNltSA-Dv*DX9x{;al?1>I265?5g@@;oLI=~9@K&} zr7FShON`v_qqDX$k&}SHvP50Cs(*GkvsTBqFkeHz-%{Z{JK%r(2yXZ8j131PsE?BS z^J>wb*Ea{W(ODizRRcsA|6b4SD!?MY zfE?V+D{q_`?4_KP!vsDK)7)VD%)oP>Z_Irn%f|vfd+yjZs)e+Dt+9QWtnhr$afGCR zd*VhvJ)q0$f6MRLwQ_4D`{>I3q)L5#lAeQ=Q!!X{PU7seuCnI$owXL12B06+;E29h zHqa-HSbC2wSx&!pNr9-HW3uCssMW}l0xT;D)J!6)%y`GUX7=v9{Uq|S=m22SR{{O zFDWYHDjm;~i)+>z9t#7`Z9FPA5;m{UIFPEJoivbi39!1UEOh-xj~JSJYY|m+aDYu2 zTTiY=6y5^X{tsENLR4b_mvPJpR03F)g}iGyv}K7(j)jGY1Kq|L?QLOWWt_ss5dKN5+gd}aRL}=P9Z!9 zc+r7_5=)1XO1Gpzk_w}teBw%yyjVz!Aglweg;S@1ogO#`yl!$c%8wg>H9?7~#LVL` zsEaNzG&XTo*?CGR21CNGPR5;EO@cjRG^O1ljQ??AAcHec&rnLD>^;{6AYHYcPh$1s?FKlJsG|X|i4i zD6>HTh0FsHm(vp6r`6yqQ^`~EJ@jLdA$NlY{*89{+b@#@N;~dk_s?`i z6)JEEMnQemvr&LRp*I^Q)xp76D@-}~pnVE9XAd_p!DAjP)A7O6XQVZSz+iB+g_#s( zRYy}bplO64VH8&O901Wxmw*?WS(j8c{eAPnAWAU!pKi7JIAC?sA*h9Io3uv|KFTSF zjwenegJDOb93q;KX-t+#du%xLq%D@oc>iRLMwTdCf>E_-*knm8wIhCQDkj^Hf28*6NB5miLx>TLAQ*ABT_#*-Nh4nx#m*l2e~^8Eiv}0cH3J z?4_-N#SD4l7?aG0qcZB8n`-I8=9Z^Ax+tDkk>?zS9r{F@7~}nkrj}>2$}V@MVd}+J zVZy@P82}xU6t&N#!b?xsHPxeF1g8RIpV>ZJ9&EVW$X~paaWyGX3yuWbubjy_pMNen z;}Zf!{w6Xg6hy(SB?>}35)%!wX#c3J^G^7Yh2~)xFpRNcC?TB(hx{fu$%H`8cGmG+ z$BU9t$WQ-)%S4)!Z0wKbJD#Jg<9l?s#d+F$9970H3=Y1+d;M5o|(iU zw5_XgLK59Ons!6UljQ9+kkf}QpxBde5VveM2YRJPbZc0C?}E@HMw~d z%#0$zX$-%g#MeGam}WmvV|LH{~la^RTf>>N8I~s5wvRD+L0mLx4aLsP{^w zupRRk6Uujo&Ljl4JlnzBV$Z@vkWQ%wPPCfCh%;EGC;i((m%Cf6gPaGgxV#3BVnhUK zKks6b*X{;Puv}qCI85iCvi~sa;AO9f+OktUy=(M;Ce$T1^I?%qmbZ*VALEf6a;B(DpB!*!JZKgXGMbQUpJ5zzq`$^ zC}}8O1$opIqCu}}xVsvCK(w`*N#K3UL15UPHaxPe=sh80BJ!ZZL;G2c9xsy~*YZ{? zzVU8v#(UP>&LuGdSVJ7;0hZG0P(C#V1VQ3L$XyK3HUT`&QXcf*-zxSmJH;sk*8v9{ zL{r1tVJ3KZ`@?afm&Wip4SanlUNPb{q?t?+5)gu<10sP#_G|`mBGIB3hE*;W-D3*E zlbH*77swpyF%sih3jZJ1!AM@It4KEj*7WXi%SZk%efrzp2^9v5D$EU-Q`6oSpBBf} zQL<;RR3HVI$ieUh(v}OrmtkTVLSSvj234n$)p!IZ357OSH^e7V&{i!sB5M z$ul@9a)uGin~oAl4%LOCPM=Z}-Qe;dWg4+I4w&3KJBTACx-&!5KqECrLlyHa=~ATR za8%Xj%x4BL!E&0?83AV$(AOngjEC8+``4A|_f;vf_4tqnX1lBL3)@~}sHTOdJcI9Lu~lFTg9qOjCi!u*vS zA;Rf{x->n`ma->xOclqDS)$?XLZRqP!(t!P0Lpswupb1jLRL$F102Mf2-VznLw31!G2o3VN6HSzrTnk?w;wSO@>wwn6DA zuVLpZ&;LZ4vAMWN$cd+B!keM6rX+CiMI8iP0+6&OhXfouy_x}%2I(ZSnSgF1+AHw> zVXNewK#+m5os@n>i1B;zx(r3$|1iLoMnf*V6e7e7)C*+j#6XW({97g#KmrXIL4A$e zOjf-ZLLP8Nkb}n~*_=$Nvsgeo#H`*k#NutXfvqmObOj77$D(8iYNA2<)Sxjq6p)-M zSA;v=02>z`1!ht!Q?@NYYA6jBQj`V~z15%47np8>1QsotA}a^!z&ZuVpT!VGmHux# zqhqZ}>1^i`!_IzUNTGvC8kC?UWGN}jsXu};H%S*|+C`Cz10?HeMc7gi3z|Y^(Oz&rSp|iiziBUUdI+zJAtN-VWEb8 zXB?UUJYucaEjKs%?QmI$`P}LL1%;4}+I=cQAXTubEwZVQn&dm--!2|#mARDt8Kc~J z4TQt<$&|9SbH7Up3d7xl?MS#O6gsyKpLLY;^a{14ZTzPm;T`W^)G4X{p71O+?C`4^ z0_n&s-*%>%lwJ`0Z9)RBhp){#Z*Wq=_I?G9T z=^|N$8RaICl&eDWi0if7(aw2LhLLQZxxDYKfwyttZPNt@~uqm z>oz8Smz68&j4a;ad=P`!?oqOO-QA$NE|JYe$NY1OftbG3DY?l`UK@vo5*gTV+jq|N z>AQ!UlMskmzu_g|Df5k(SFd$>UT*%99XSxilkGJx8SG^Q72sAa26C>2DeNb90Ox&p zHB2q_A7&?GHo*ik@@CQ22h(*Zqycfd2P|Y~GzS0_k{~wKMIddHZXPEM-UV_8l!21P zVU=J3yf9u0unpt1Kq&J7WR@TG0{|O{MBfyFHsdgBP=N#}Hw2-9lVCD)m;Y=36JcKf zeR$Sa>l0(?fq(h843u>!=Y(MxZ42!MW-$9Qq5Oi^VVwV*ZyXoScy0U)M`-onDV%P>Ts6+9xe6N=V zT~;D4W{A|tgVpyH`UYrQ@KeOWiP%U)?dXp02#@h7kMl^6^=Oaxi2slIsE_-|kNxP6 z{|Jx)DUbt6kOgUw2Z@jgsgMiFkPYdOLQ)L$_mC4wkrio?7m1M>sgWDWksaxg9|@8n zDUu^ek|k-9CwY;(gOV%Bk}c_yFA0+|DU&lvlQn6RH;I!usgnoUV>{`SKM9mUDU?G= zltpQjM~Re4sgxwiAn&!5PYIP#DV0-6l~rk#SBaHbIhCMQgIej8UkR3BDVAeNmSt&{ zXNi_+sg`TWmTl>lZwZ%iDVK9emvw2EcZrvIsh4}nmwoA%e+ig@DVT#vn1yMWhl!Yp zshEq&n2qU}j|rKPDVdW=nU!gomx-B~shOL}nVspGp9z|wDgTC4LZD1(%mpaRQy`hBTAtN+)H8?U)W)C`h_fH%7%L z-3gD_L|K;iHn7x&O0k6Hxqmpchw}$}`?r7xVR_8RI85@5Yyk=i%4I);0glI;snA^< zP%oY6j`jA5=ro?<$bvJ4p6W+L$z@#Fc@T#8YgN;rLsT{9X$C5JGz+FprBw+cXk2Ru zki*G_;CB%y_=7J3p)%Evg>sDsDpB(oPGv+G!$?mwHUFb6Bo*Q}ZpEcVvDgMcdO_a= zfPlcG%II2TM+sQ+Z+|Fh;CV`_Xo|&ioReYzK8T2f@NHy7q3GsR_qcxxLW3KSCJ`AG z)_9H2C!k4`I|mUZ$!Kkc2X50Dp;APKKj%;oSzAr|o$ttrY&d$t*b6nso+$dKM6{lX zM|~m$3SMJQEA@`_xqsd$U4U4Isc3!4mTTtOH|e==AgUXu`aT7>sCFS?c2sWx3Z64Z zM3ERG2d!go!VNfxB3WQS&egnEhiG?^$QS?8-n#G+%+QK7P6q*0%|qnv@acK3K~ zDbtL@3V&VqGXN=llt@I(*^UmlIH35f`;?8{@c*q71EsK16w-NeCu$w=;i(FNtRLv5 z#q@PdMNF?-Qk-{t<{*A5 zrW^Ac2hMv$%=Qy)8^4vnMDz<$0;~?jTV_!8SnoK%x`8LY^^R8Zjv(A1Wjc>ufEEcu zJR@Q#cl5pxcz_IfBKmh2`s=nTxc?6saJr6~8x zx&tw8MSP&7!Ei}(DK?zEF}!g>j8G^AK(Q3N`zW7M$}<)0u26(`7dpae5L=Vvx94)Z z3LC&%GlMP*uVVa1aA<%ZS~q6k2g#8(t3Wzou>lD~aGDgd6PJvkREvqA0a$_(@-P|v z`zp~<$QK|}XsCluqh>36Z2PCbr@Vm=tWxNJX=xGbBS+ErYk>s)6d&$r@4_5Dga`4ipDBv~whi6Uj|*2v>kA zexu9iYg+c^QlFtTT>@{q_hQ$Fw6HdvYqMHdfbx z`pmuDD_CO7ELg$FM*nKOg2P^&U`eWFd;}-LGswWIB90xYOq9jWf{XU%#4Nnfuktb- zg~KQ8U2&Vi>fqUt>P1`>*tvGvoT3cU2&&dmX$56!Km;UuFdUPB2oM@gGsK^w!4q8f zA-@eR5GtL+@NX6D&94Cr(>7ggRG+d<+oKQ#dvkMZ6R_wM+scGhQA|Dbs@K{*8$s8e zNtG0ODo58nbw21r-K@wtyIqq#5Y-&Beda@{61l}~6*xSq;}Trxdev_1C%5aOOpLCO z@Y(G8w}ZUVm&A423?r#K)%uBUhdS1Vai}wuNRfL8O7h}}S09}VLM_tXIHz{!ncP$5 zDsNq9$1Mnc6aTgQTOkC^wKw!u+gpxM2;yy|6{#l3h!gi zubg_)!KG(l=H~Ih6mvUa)O{*KA-o+(ns9U7Sm##iyBeG0z@blnt_-cI%rLIh{{o{? z?uS3j82wBvPkyjtSJIkJ=k8(WskJ8M4CIz(4$cQV`17a+-c%zL#ZNtAzpH17l;>ov zOudjMP8m44wqW%E=NLp;f@lY?4N&hVaJZi9JjE*YJf*^ZI;|TWqCV^Yk^v)R!f7W9 zigLI{2LH^`LclBM%JReSkjVLGB@WFwI_5JHSB6MyCL!=mD@8)f(TZ9-}=sp-vgPd3C%Z4T}-C zdW_E1K-~@orYfyYC&bQSvnD^&C}gRC__w6jxbo`kJU_t$+^K+Z%>y9#nd8|!4=l0%!!@J~)B!Kq7omCj80b(byRhpX} zuB=B33zL)^@^q>xo=F0a9!XoSN6_Y1?c(w4f^Xx#DFzyrAM{l9y&#^548q~N{yC%{ zHAJ2b+b{(Zc8-x?qjvr3wc5lT?EZX_0H*uV3~zR~=p;%RY%D~~L(3IcL)F3;$*=)p2-K`8>N!-%soi*WPFfr%0oQ~$A6 z^0rh9?G*|X6c0dvqe;MGlvQl?igC-skXC~BY)a3z;|UAnk^(o<3gMO;$*(oM!8oze zKpmR2wW_T-YQhvMj@~_Rez`tCVU@fCpZLjB;=zh0Y0DIZdy`4rA$N83O4ju(TQ8JR`kb!^$gLdxqVs*#eFlbZ)8CbM!COjzew(KLYae)<{R(vw_hmIM# zB?{>9BZ+KGIAI$pRl9^OoiJjSjs;CxrDHr<0HYw{1BNVEr}@^ZC7W~4*;;8LC23~w zszht=DssZdsm)#iLy$ydyKB$}yat^>d8WZJ)WT;tJ-+A+Z`8i7@B%#c?bnp4iJ8-L%>;35wK`?0=G@8r^2VPLPcVB5N~r}2d=Gl&a`_nqK`-c0ylawi z6#HPKg~lkL3@n(K&Is)`5aR&F!dlJ@;<$tCyq1)hMZNgQ8x6z^ePK|Dp^`YIt9RzB zZw&2N(o4Jm3$tUuaTGX6h!d^o>bj@oFk>A7v{|jNRz%wF9Sh4t>9Ce8j7h!%SnMe# zUcQOq$mk5h@1ted@v1p4%bJLZ=$NUpFawj*DGdZPcoR;#zIsZdLI3u_iaoa?pzbD<^+R5mm=CI0{QR(t z=f*gOLvPS~5j{NB>ddnV!wfHtQ%KD56=8{VMk)tnGi=R1xFwdgQFNu1T^t>K+ zl}P6#ZL3_@B+#z_c+H?RtB1fUbFMGxJK&|@?Y6Dd_#m)fUxzW^kL{7I zej30Gcn!nzmzS6SdPT%naLC)!!8#J6QZ1thw?SN(^5-Or#UwDp ziPu^R(1B9i%3j!NNh1()4DX$6cvw@}v|w{2m>?G7iAsj&l3NYn<_+HeLBK7%QqAPfV=0)b~(#0!nEhU46` z3+4@OgT8B`w?ed&2Ye8E{s`LsU{$5I^P4?EDEXqd!X7RnqUA(F7_v~sU#Y7T1JDFO5HU$cq9<*?2wdj&=s+&4 z^pb-p1rxdWK!`9kr637ulN72nIib;qx(uOs45>)3{>BO;nPh*G=eD6X3QcQ+$Uco) zRi|dstsoQKOS1qzy;Ucp#^Yx#WXa913jgzYxJ(1_zV=W$;xtXaA_7ZWGER(151ESD zCnxqH!rm!|tC)GBVO(@f3-q#@==)ng0ZO86j;WEEjp|;RC_$N$6Skgp%qPazSmP0p z8^v^{QpL1Dyef=tS+b@tz1dXRg*6LCe5`Hb>Ix+_@f}`xOBwdU$~=%ZkAJnr1ulxP ze+H2^!ZoA_dloMz5OQ4}5Cv3=c(AK#m6lrtZ;WbD4Hc%L5n8x_O+GZlW9}zEuW;N3 z)5Z%PDoVR;CBPmNh#6as=>na+Bi;tVIgjoVxn^=v>26Dea3BVJdR$A0*R`mkrso*I zIwLWrHwk{c_qa)|g0lj*RG>D{DgUDI*=m1#p*^L=x;mW;e!OL=`0^G{ef=(G?WM*= z&T6pmjo_#xU>fnAGm-iurm;vY6a?2AmtB;q;p2^sQ&++4zUqWqhL~(e)GyA(uE6qjB7LjXs#<8` zCW>$qBZz=R&D7%5LKraaHfcajjtUEEIgjLI2N)*RZP`9oXN?*CkPbnG>F7=$pA-7SI1TtV^j`w*rx%T4L{G+Yy$xp_>2 zsA;h%htg47Ni!XV5ToRlh{l(A^rfqxY@R6RsiX-nQbL!ySdc_`(aXKCD|QTv{yH_e)4= zzz4YtGXr>l0U5aAM*m6D0eWWYczNG@kG7(LZeW1sEx!gL6|~Rm#Nj$Ggtxk2kEH=r z{-}M!y*&heWz^--AR*|S*K@d};{Xydg{aN4^IC1M4Zsc&iiy0X;0Go-pzw2alrv}F zIoCg(&Y!0e^q%r5vQWNu2SJH@8dmOikX?|lsz?w+?9ziB?2iB#0FZh_r=-LI4j>rT zO_y>`Dh>!Koq%*d{K&<8@RPO*$F2KE#bf!EifF&Hj0-giPJkC}MOY`8P@DeIP zzz-LYWNRD{Q2(StnSM{}Chqap3I-{}_5dP=X6Gz;$3s9PLF9r-`b_$+O{9p-B@{$1 zo@ZZ-?Xbp0>2_{QzQEw*f;V z0_tNFO~DiWkPrCe4LfGl2+fPL;(&Ls1(CXE^3SrTPlFEYZoD|4tGo% z2@xqM;zf{(`#9;ST&C^b$7&VU6DByky0RaqvMS_w%IG`@&<`BD55n&4h)Qj|-CWtoc5wV~PH|mAz z&m*fcA<@Mb!=Uc0$ralr8>OHx0pKq4k`Q?ZhY%p7!qF<*NVm>H1IDR?q+-8nadh13 z-~afKB8p1^M6y26uT8?hg*_ymX6>2!4T=eHy0obGR)f8;Ek*kn^2Jz z2(jhTP!0BMGvaX;g(5-vqXXfy5Dc>=cm^5*FiHG#K$UYx!cv6zk~KTiJ-@1K;#2PS zEiHSIK)sSa-N+XoGXgsll5A!<0l^YGAffn^D7AwP)rvdCA%?I(GzUghaOh^LlSC!L zAH`Co@USQPQbLDENOKAD5=TBZG~*QTH(8?z3sXr*Gcv=I33`Mpj}tkE6EBBLum7}^ zOS{xdHSJ5oR7}T|Ov}_v&lFA5^cB^VP21E>-xN;cR8Gq$wdT}L?-Wn-R8RMmPy5tQ z{}fOIRZs_&PzROM3e`;I2vHZ6Q5&^P@gU3`RZ=IFQrXnMDiu>RRZ};WQ#;jDKNVC% zHBYHYR0*wAPZd?gGy_;IRa@0n@$?ad@KtA(R%_K(ZxvT_RaeOrha@mntMs{cRahyt zO{#BLk9Ai$0FIgxS)0{apA}l8Ra&Q2M^Um>@h4cRRa@tjD!0{JH&q@k^jpW3T+7v5 z&lO$MRbAJWUE9@N-xXftRbJ%6hYy%yS^4|!xn5$wQK)!KZlFKx^y-(3j`#@>NXBN zmJ^Fh_o2>*qGHjWKC`L@`u zQ9JdJJ5;cKEDmzdG9eIm&zMSmHiVd5l6Ro=3ub}gq$xF4@=#MnDjtNwD#JIg%d$|j z10mo|W=KwlvKU#zZA0p6VHbbKX?VLetDpu}6m&^7*Ko^}0ping@6Vt})ps$oEz_%R zmGL>ybA7z@d@F!O;3I=!xoKb1C)PL7da6u?5+QKz7u0A(6PKA>K7&lX_GUzar zAttwT@|O#+(;A7Aa|a=Y)kcIF0uOwqbVnh@a?DuCU;&U;MgK+jQX#7-Q5cm}IF(4) zEZdAulPN3Q%oyfF#J+&3YS@#|w}P+CJ}E?m%q2CB=XopAP=q)rjb@JLD^9(ah&lK@ zWtS#B5H+ReiW$q0pK>SPcT5GDCylF5*zg0?7$ovAU@)0W^|BYvw+6d3fISzCd-w~) z5QCXRAjVTXnGJ&TRxTn{*qV~>npkzcv}Wk77VaeMa!||&jt@PsM9Ea|2G33R4%omr zW^~d#himUzC7@a+|7>}he~==w^-GmG3ICuqB=F!w*NmTOLuy0p7DYnfqxc4D@4T

    c^ZCm?s+9z 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%0A&fXGB^;dFPa{&B645{jFP7I3{co+4xXOm71 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

      DRs9J7oRTRfc|t-(h260Nvcekj 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/semver.go b/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/semver.go new file mode 100644 index 0000000000..a580fbc014 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/semver.go @@ -0,0 +1,466 @@ +package semver + +import ( + "context" + "fmt" + "io" + "sort" + + "github.com/operator-framework/operator-registry/alpha/action" + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/alpha/property" + + "github.com/blang/semver/v4" + "k8s.io/apimachinery/pkg/util/errors" + "sigs.k8s.io/yaml" +) + +func (t Template) Render(ctx context.Context) (*declcfg.DeclarativeConfig, error) { + var out declcfg.DeclarativeConfig + + sv, err := readFile(t.Data) + if err != nil { + return nil, fmt.Errorf("render: unable to read file: %v", err) + } + + var cfgs []declcfg.DeclarativeConfig + + bundleDict := make(map[string]struct{}) + buildBundleList(&sv.Candidate.Bundles, &bundleDict) + buildBundleList(&sv.Fast.Bundles, &bundleDict) + buildBundleList(&sv.Stable.Bundles, &bundleDict) + + for b := range bundleDict { + r := action.Render{ + AllowedRefMask: action.RefBundleImage, + Refs: []string{b}, + Registry: t.Registry, + } + c, err := r.Run(ctx) + if err != nil { + return nil, err + } + cfgs = append(cfgs, *c) + } + out = *combineConfigs(cfgs) + + if len(out.Bundles) == 0 { + return nil, fmt.Errorf("render: no bundles specified or no bundles could be rendered") + } + + channelBundleVersions, err := sv.getVersionsFromStandardChannels(&out) + if err != nil { + return nil, fmt.Errorf("render: unable to post-process bundle info: %v", err) + } + + channels := sv.generateChannels(channelBundleVersions) + out.Channels = channels + out.Packages[0].DefaultChannel = sv.defaultChannel + + return &out, nil +} + +func buildBundleList(bundles *[]semverTemplateBundleEntry, dict *map[string]struct{}) { + for _, b := range *bundles { + if _, ok := (*dict)[b.Image]; !ok { + (*dict)[b.Image] = struct{}{} + } + } +} + +func readFile(reader io.Reader) (*semverTemplate, error) { + data, err := io.ReadAll(reader) + if err != nil { + return nil, err + } + + sv := semverTemplate{} + if err := yaml.UnmarshalStrict(data, &sv); err != nil { + return nil, err + } + + if sv.Schema != schema { + return nil, fmt.Errorf("readFile: input file has unknown schema, should be %q", schema) + } + + // if no generate option is selected, default to GenerateMinorChannels + if !sv.GenerateMajorChannels && !sv.GenerateMinorChannels { + sv.GenerateMinorChannels = true + } + + // for default channel preference, + // if un-set, default to align to the selected generate option + // if set, error out if we mismatch the two + switch sv.DefaultChannelTypePreference { + case defaultStreamType: + if sv.GenerateMinorChannels { + sv.DefaultChannelTypePreference = minorStreamType + } else if sv.GenerateMajorChannels { + sv.DefaultChannelTypePreference = majorStreamType + } + case minorStreamType: + if !sv.GenerateMinorChannels { + return nil, fmt.Errorf("schema attribute mismatch: DefaultChannelTypePreference set to 'minor' doesn't make sense if not generating minor-version channels") + } + case majorStreamType: + if !sv.GenerateMajorChannels { + return nil, fmt.Errorf("schema attribute mismatch: DefaultChannelTypePreference set to 'major' doesn't make sense if not generating major-version channels") + } + default: + return nil, fmt.Errorf("unknown DefaultChannelTypePreference: %q\nValid values are 'major' or 'minor'", sv.DefaultChannelTypePreference) + } + + return &sv, nil +} + +func (sv *semverTemplate) getVersionsFromStandardChannels(cfg *declcfg.DeclarativeConfig) (*bundleVersions, error) { + versions := bundleVersions{} + + bdm, err := sv.getVersionsFromChannel(sv.Candidate.Bundles, cfg) + if err != nil { + return nil, err + } + if err = validateVersions(&bdm); err != nil { + return nil, err + } + versions[candidateChannelArchetype] = bdm + + bdm, err = sv.getVersionsFromChannel(sv.Fast.Bundles, cfg) + if err != nil { + return nil, err + } + if err = validateVersions(&bdm); err != nil { + return nil, err + } + versions[fastChannelArchetype] = bdm + + bdm, err = sv.getVersionsFromChannel(sv.Stable.Bundles, cfg) + if err != nil { + return nil, err + } + if err = validateVersions(&bdm); err != nil { + return nil, err + } + versions[stableChannelArchetype] = bdm + + return &versions, nil +} + +func (sv *semverTemplate) getVersionsFromChannel(semverBundles []semverTemplateBundleEntry, cfg *declcfg.DeclarativeConfig) (map[string]semver.Version, error) { + entries := make(map[string]semver.Version) + + // we iterate over the channel bundles from the template, to: + // - identify if any required bundles for the channel are missing/not rendered/otherwise unavailable + // - maintain the channel-bundle relationship as we map from un-rendered semver template bundles to rendered bundles in `entries` which is accumulated by the caller + // in a per-channel structure to which we can safely refer when generating/linking channels + for _, semverBundle := range semverBundles { + // test if the bundle specified in the template is present in the successfully-rendered bundles + index := 0 + for index < len(cfg.Bundles) { + if cfg.Bundles[index].Image == semverBundle.Image { + break + } + index++ + } + if index == len(cfg.Bundles) { + return nil, fmt.Errorf("supplied bundle image name %q not found in rendered bundle images", semverBundle.Image) + } + b := cfg.Bundles[index] + + props, err := property.Parse(b.Properties) + if err != nil { + return nil, fmt.Errorf("parse properties for bundle %q: %v", b.Name, err) + } + if len(props.Packages) != 1 { + return nil, fmt.Errorf("bundle %q has multiple %q properties, expected exactly 1", b.Name, property.TypePackage) + } + v, err := semver.Parse(props.Packages[0].Version) + if err != nil { + return nil, fmt.Errorf("bundle %q has invalid version %q: %v", b.Name, props.Packages[0].Version, err) + } + + // package name detection + if sv.pkg != "" { + // if we have a known package name, then ensure all subsequent packages match + if props.Packages[0].PackageName != sv.pkg { + return nil, fmt.Errorf("bundle %q does not belong to this package: %q", props.Packages[0].PackageName, sv.pkg) + } + } else { + // else cache the first + p := newPackage(props.Packages[0].PackageName) + cfg.Packages = append(cfg.Packages, *p) + sv.pkg = props.Packages[0].PackageName + } + + if _, ok := entries[b.Name]; ok { + return nil, fmt.Errorf("duplicate bundle name %q", b.Name) + } + + entries[b.Name] = v + } + + return entries, nil +} + +// generates an unlinked channel for each channel as per the input template config (major || minor), then link up the edges of the set of channels so that: +// - for minor version increase, the new edge replaces the previous +// - (for major channels) iterating to a new minor version channel (traversing between Y-streams) creates a 'replaces' edge between the predecessor and successor bundles +// - within the same minor version (Y-stream), the head of the channel should have a 'skips' encompassing all lesser Y.Z versions of the bundle enumerated in the template. +// along the way, uses a highwaterChannel marker to identify the "most stable" channel head to be used as the default channel for the generated package + +func (sv *semverTemplate) generateChannels(semverChannels *bundleVersions) []declcfg.Channel { + outChannels := []declcfg.Channel{} + + // sort the channel archetypes in ascending order so we can traverse the bundles in order of + // their source channel's priority + var archetypesByPriority []channelArchetype + for k := range channelPriorities { + archetypesByPriority = append(archetypesByPriority, k) + } + sort.Sort(byChannelPriority(archetypesByPriority)) + + // set to the least-priority channel + hwc := highwaterChannel{archetype: archetypesByPriority[0], version: semver.Version{Major: 0, Minor: 0}} + + unlinkedChannels := make(map[string]*declcfg.Channel) + + for _, archetype := range archetypesByPriority { + bundles := (*semverChannels)[archetype] + // skip channel if empty + if len(bundles) == 0 { + continue + } + + // sort the bundle names according to their semver, so we can walk in ascending order + bundleNamesByVersion := []string{} + for b := range bundles { + bundleNamesByVersion = append(bundleNamesByVersion, b) + } + sort.Slice(bundleNamesByVersion, func(i, j int) bool { + return bundles[bundleNamesByVersion[i]].LT(bundles[bundleNamesByVersion[j]]) + }) + + // for each bundle (by version): + // for each of Major/Minor setting (since they're independent) + // retrieve the existing channel object, or create a channel (by criteria major/minor) if one doesn't exist + // add a new edge entry based on the bundle name + // save the channel name --> channel archetype mapping + // test the channel object for 'more stable' than previous best + for _, bundleName := range bundleNamesByVersion { + // a dodge to avoid duplicating channel processing body; accumulate a map of the channels which need creating from the bundle + // we need to associate by kind so we can partition the resulting entries + channelNameKeys := make(map[streamType]string) + if sv.GenerateMajorChannels { + channelNameKeys[majorStreamType] = channelNameFromMajor(archetype, bundles[bundleName]) + } + if sv.GenerateMinorChannels { + channelNameKeys[minorStreamType] = channelNameFromMinor(archetype, bundles[bundleName]) + } + + for cKey, cName := range channelNameKeys { + ch, ok := unlinkedChannels[cName] + if !ok { + ch = newChannel(sv.pkg, cName) + + unlinkedChannels[cName] = ch + + hwcCandidate := highwaterChannel{archetype: archetype, kind: cKey, version: bundles[bundleName], name: cName} + if hwcCandidate.gt(&hwc, sv.DefaultChannelTypePreference) { + hwc = hwcCandidate + } + } + ch.Entries = append(ch.Entries, declcfg.ChannelEntry{Name: bundleName}) + } + } + } + + // save off the name of the high-water-mark channel for the default for this package + sv.defaultChannel = hwc.name + + outChannels = append(outChannels, sv.linkChannels(unlinkedChannels, semverChannels)...) + + return outChannels +} + +func (sv *semverTemplate) linkChannels(unlinkedChannels map[string]*declcfg.Channel, harvestedVersions *bundleVersions) []declcfg.Channel { + channels := []declcfg.Channel{} + + // bundle --> version lookup + bundleVersions := make(map[string]semver.Version) + for _, vs := range *harvestedVersions { + for b, v := range vs { + if _, ok := bundleVersions[b]; !ok { + bundleVersions[b] = v + } + } + } + + for _, channel := range unlinkedChannels { + entries := &channel.Entries + sort.Slice(*entries, func(i, j int) bool { + return bundleVersions[(*entries)[i].Name].LT(bundleVersions[(*entries)[j].Name]) + }) + + // "inchworm" through the sorted entries, iterating curEdge but extending yProbe to the next Y-transition + // then catch up curEdge to yProbe as 'skips', and repeat until we reach the end of the entries + // finally, because the inchworm will always fail to pick up the last Y-transition, we test for it and link it up as a 'replaces' + curEdge, yProbe := 0, 0 + zmaxQueue := "" + entryCount := len(*entries) + + for curEdge < entryCount { + for yProbe < entryCount { + curVersion := bundleVersions[(*entries)[curEdge].Name] + yProbeVersion := bundleVersions[(*entries)[yProbe].Name] + if getMinorVersion(yProbeVersion).EQ(getMinorVersion(curVersion)) { + yProbe += 1 + } else { + break + } + } + // if yProbe crossed a threshold, the previous entry is the last of the previous Y-stream + preChangeIndex := yProbe - 1 + + if curEdge != yProbe { + if zmaxQueue != "" { + // add skips edge to allow skipping over y iterations within an x stream + (*entries)[preChangeIndex].Skips = append((*entries)[preChangeIndex].Skips, zmaxQueue) + (*entries)[preChangeIndex].Replaces = zmaxQueue + } + zmaxQueue = (*entries)[preChangeIndex].Name + } + for curEdge < preChangeIndex { + // add skips edges to y-1 from z < y + (*entries)[preChangeIndex].Skips = append((*entries)[preChangeIndex].Skips, (*entries)[curEdge].Name) + curEdge += 1 + } + curEdge += 1 + yProbe = curEdge + 1 + } + // since probe will always fail to pick up a y-change in the last item, test for it + if entryCount > 1 { + penultimateEntry := &(*entries)[len(*entries)-2] + ultimateEntry := &(*entries)[len(*entries)-1] + penultimateVersion := bundleVersions[penultimateEntry.Name] + ultimateVersion := bundleVersions[ultimateEntry.Name] + if ultimateVersion.Minor != penultimateVersion.Minor { + ultimateEntry.Replaces = penultimateEntry.Name + } + } + channels = append(channels, *channel) + } + + return channels +} + +func channelNameFromMinor(prefix channelArchetype, version semver.Version) string { + return fmt.Sprintf("%s-v%d.%d", prefix, version.Major, version.Minor) +} + +func channelNameFromMajor(prefix channelArchetype, version semver.Version) string { + return fmt.Sprintf("%s-v%d", prefix, version.Major) +} + +func newPackage(name string) *declcfg.Package { + return &declcfg.Package{ + Schema: "olm.package", + Name: name, + DefaultChannel: "", + } +} + +func newChannel(pkgName string, chName string) *declcfg.Channel { + return &declcfg.Channel{ + Schema: "olm.channel", + Name: string(chName), + Package: pkgName, + Entries: []declcfg.ChannelEntry{}, + } +} + +func combineConfigs(cfgs []declcfg.DeclarativeConfig) *declcfg.DeclarativeConfig { + out := &declcfg.DeclarativeConfig{} + for _, in := range cfgs { + out.Merge(&in) + } + return out +} + +func getMinorVersion(v semver.Version) semver.Version { + return semver.Version{ + Major: v.Major, + Minor: v.Minor, + } +} + +func getMajorVersion(v semver.Version) semver.Version { + return semver.Version{ + Major: v.Major, + } +} + +func withoutBuildMetadataConflict(versions *map[string]semver.Version) error { + errs := []error{} + + // using the stringified semver because the semver package generates deterministic representations, + // and because the semver.Version contains slice fields which make it unsuitable as a map key + // stringified-semver.Version ==> incidence count + seen := make(map[string]int) + for b := range *versions { + stripped := stripBuildMetadata((*versions)[b]) + if _, ok := seen[stripped]; !ok { + seen[stripped] = 1 + } else { + seen[stripped] = seen[stripped] + 1 + errs = append(errs, fmt.Errorf("bundle version %q cannot be compared to %q", (*versions)[b].String(), stripped)) + } + } + + if len(errs) != 0 { + return fmt.Errorf("encountered bundle versions which differ only by build metadata, which cannot be ordered: %v", errors.NewAggregate(errs)) + } + + return nil +} + +func validateVersions(versions *map[string]semver.Version) error { + // short-circuit if empty, since that is not an error + if len(*versions) == 0 { + return nil + } + return withoutBuildMetadataConflict(versions) +} + +// strips out the build metadata from a semver.Version and then stringifies it to make it suitable for collision detection +func stripBuildMetadata(v semver.Version) string { + v.Build = nil + return v.String() +} + +// prefer (in descending order of preference): +// - higher-rank archetype, +// - semver version, +// - a channel type matching the set preference, or +// - a 'better' (higher value) channel type +func (h *highwaterChannel) gt(ih *highwaterChannel, pref streamType) bool { + if channelPriorities[h.archetype] != channelPriorities[ih.archetype] { + return channelPriorities[h.archetype] > channelPriorities[ih.archetype] + } + if h.version.NE(ih.version) { + return h.version.GT(ih.version) + } + if h.kind != ih.kind { + if h.kind == pref { + return true + } + if ih.kind == pref { + return false + } + return h.kind.gt((*ih).kind) + } + return false +} + +func (t streamType) gt(in streamType) bool { + return streamTypePriorities[t] > streamTypePriorities[in] +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/types.go b/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/types.go new file mode 100644 index 0000000000..971718b34c --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/types.go @@ -0,0 +1,82 @@ +package semver + +import ( + "io" + + "github.com/blang/semver/v4" + "github.com/operator-framework/operator-registry/pkg/image" +) + +// data passed into this module externally +type Template struct { + Data io.Reader + Registry image.Registry +} + +// IO structs -- BEGIN +type semverTemplateBundleEntry struct { + Image string `json:"image,omitempty"` +} + +type semverTemplateChannelBundles struct { + Bundles []semverTemplateBundleEntry `json:"bundles,omitempty"` +} + +type semverTemplate struct { + Schema string `json:"schema"` + GenerateMajorChannels bool `json:"generateMajorChannels,omitempty"` + GenerateMinorChannels bool `json:"generateMinorChannels,omitempty"` + DefaultChannelTypePreference streamType `json:"defaultChannelTypePreference,omitempty"` + Candidate semverTemplateChannelBundles `json:"candidate,omitempty"` + Fast semverTemplateChannelBundles `json:"fast,omitempty"` + Stable semverTemplateChannelBundles `json:"stable,omitempty"` + + pkg string `json:"-"` // the derived package name + defaultChannel string `json:"-"` // detected "most stable" channel head +} + +// IO structs -- END + +const schema string = "olm.semver" + +// channel "archetypes", restricted in this iteration to just these +type channelArchetype string + +const ( + candidateChannelArchetype channelArchetype = "candidate" + fastChannelArchetype channelArchetype = "fast" + stableChannelArchetype channelArchetype = "stable" +) + +// mapping channel name --> stability, where higher values indicate greater stability +var channelPriorities = map[channelArchetype]int{candidateChannelArchetype: 0, fastChannelArchetype: 1, stableChannelArchetype: 2} + +// sorting capability for a slice according to the assigned channelPriorities +type byChannelPriority []channelArchetype + +func (b byChannelPriority) Len() int { return len(b) } +func (b byChannelPriority) Less(i, j int) bool { + return channelPriorities[b[i]] < channelPriorities[b[j]] +} +func (b byChannelPriority) Swap(i, j int) { b[i], b[j] = b[j], b[i] } + +type streamType string + +const defaultStreamType streamType = "" +const minorStreamType streamType = "minor" +const majorStreamType streamType = "major" + +// general preference for minor channels +var streamTypePriorities = map[streamType]int{minorStreamType: 2, majorStreamType: 1, defaultStreamType: 0} + +// map of archetypes --> bundles --> bundle-version from the input file +type bundleVersions map[channelArchetype]map[string]semver.Version // e.g. srcv["stable"]["example-operator.v1.0.0"] = 1.0.0 + +// the "high-water channel" struct functions as a freely-rising indicator of the "most stable" channel head, so we can use that +// later as the package's defaultChannel attribute +type highwaterChannel struct { + archetype channelArchetype + kind streamType + version semver.Version + name string +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/build.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/build.go new file mode 100644 index 0000000000..c35ce80c92 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/build.go @@ -0,0 +1,93 @@ +package bundle + +import ( + "github.com/operator-framework/operator-registry/pkg/lib/bundle" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +var ( + buildDir string + tag string + containerTool string + pkg string + channels string + defaultChannel string + outputDir string + overwrite bool +) + +// newBundleBuildCmd returns a command that will build operator bundle image. +func newBundleBuildCmd() *cobra.Command { + bundleBuildCmd := &cobra.Command{ + Use: "build", + Short: "Build operator bundle image", + Long: `The "opm alpha bundle build" command will generate operator +bundle metadata if needed and build bundle image with operator manifest +and metadata for a specific version. + +For example: The command will generate annotations.yaml metadata plus +Dockerfile for bundle image and then build a container image from +provided operator bundle manifests generated metadata +e.g. "quay.io/example/operator:v0.0.1". + +After the build process is completed, a container image would be built +locally in docker and available to push to a container registry. + +$ opm alpha bundle build --directory /test/0.1.0/ --tag quay.io/example/operator:v0.1.0 \ + --package test-operator --channels stable,beta --default stable --overwrite + +Note: +* Bundle image is not runnable. +* All manifests yaml must be in the same directory. `, + RunE: buildFunc, + Args: cobra.NoArgs, + } + + bundleBuildCmd.Flags().StringVarP(&buildDir, "directory", "d", "", + "The directory where bundle manifests and metadata for a specific version are located") + if err := bundleBuildCmd.MarkFlagRequired("directory"); err != nil { + log.Fatalf("Failed to mark `directory` flag for `build` subcommand as required") + } + + bundleBuildCmd.Flags().StringVarP(&tag, "tag", "t", "", + "The image tag applied to the bundle image") + if err := bundleBuildCmd.MarkFlagRequired("tag"); err != nil { + log.Fatalf("Failed to mark `tag` flag for `build` subcommand as required") + } + + bundleBuildCmd.Flags().StringVarP(&pkg, "package", "p", "", + "The name of the package that bundle image belongs to "+ + "(Required if `directory` is not pointing to a bundle in the nested bundle format)") + + bundleBuildCmd.Flags().StringVarP(&channels, "channels", "c", "", + "The list of channels that bundle image belongs to"+ + "(Required if `directory` is not pointing to a bundle in the nested bundle format)") + + bundleBuildCmd.Flags().StringVarP(&containerTool, "image-builder", "b", "docker", + "Tool used to manage container images. One of: [docker, podman, buildah]") + + bundleBuildCmd.Flags().StringVarP(&defaultChannel, "default", "e", "", + "The default channel for the bundle image") + + bundleBuildCmd.Flags().BoolVarP(&overwrite, "overwrite", "o", false, + "To overwrite annotations.yaml locally if existed. By default, overwrite is set to `false`.") + + bundleBuildCmd.Flags().StringVarP(&outputDir, "output-dir", "u", "", + "Optional output directory for operator manifests") + + return bundleBuildCmd +} + +func buildFunc(cmd *cobra.Command, _ []string) error { + return bundle.BuildFunc( + buildDir, + outputDir, + tag, + containerTool, + pkg, + channels, + defaultChannel, + overwrite, + ) +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/cmd.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/cmd.go new file mode 100644 index 0000000000..c318db6beb --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/cmd.go @@ -0,0 +1,22 @@ +package bundle + +import ( + "github.com/spf13/cobra" +) + +func NewCmd() *cobra.Command { + runCmd := &cobra.Command{ + Use: "bundle", + Short: "Operator bundle commands", + Long: `Generate operator bundle metadata and build bundle image.`, + Args: cobra.NoArgs, + } + + runCmd.AddCommand(newBundleGenerateCmd()) + runCmd.AddCommand(newBundleBuildCmd()) + runCmd.AddCommand(newBundleValidateCmd()) + runCmd.AddCommand(extractCmd) + runCmd.AddCommand(newBundleUnpackCmd()) + + return runCmd +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/extract.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/extract.go new file mode 100644 index 0000000000..3952a52b8c --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/extract.go @@ -0,0 +1,71 @@ +package bundle + +import ( + "fmt" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/pkg/configmap" +) + +var extractCmd = &cobra.Command{ + Use: "extract", + Short: "Extracts the data in a bundle directory via ConfigMap", + Long: "Extract takes as input a directory containing manifests and writes the per file contents to a ConfigMap", + + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + + RunE: runExtractCmd, + Args: cobra.NoArgs, +} + +func init() { + extractCmd.Flags().Bool("debug", false, "enable debug logging") + extractCmd.Flags().StringP("kubeconfig", "k", "", "absolute path to kubeconfig file") + extractCmd.Flags().StringP("manifestsdir", "m", "/", "path to directory containing manifests") + extractCmd.Flags().StringP("configmapname", "c", "", "name of configmap to write bundle data") + extractCmd.Flags().StringP("namespace", "n", "openshift-operator-lifecycle-manager", "namespace to write configmap data") + extractCmd.Flags().Uint64P("datalimit", "l", 1<<20, "maximum limit in bytes for total bundle data") + extractCmd.Flags().BoolP("gzip", "z", false, "enable gzip compression of configmap data") + extractCmd.MarkPersistentFlagRequired("configmapname") +} + +func runExtractCmd(cmd *cobra.Command, _ []string) error { + manifestsDir, err := cmd.Flags().GetString("manifestsdir") + if err != nil { + return err + } + kubeconfig, err := cmd.Flags().GetString("kubeconfig") + if err != nil { + return err + } + configmapName, err := cmd.Flags().GetString("configmapname") + if err != nil { + return err + } + namespace, err := cmd.Flags().GetString("namespace") + if err != nil { + return err + } + datalimit, err := cmd.Flags().GetUint64("datalimit") + if err != nil { + return err + } + gzip, err := cmd.Flags().GetBool("gzip") + if err != nil { + return err + } + + loader := configmap.NewConfigMapLoader(configmapName, namespace, manifestsDir, gzip, kubeconfig) + if err := loader.Populate(datalimit); err != nil { + return fmt.Errorf("error loading manifests from directory: %s", err) + } + + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/generate.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/generate.go new file mode 100644 index 0000000000..417a22c379 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/generate.go @@ -0,0 +1,60 @@ +package bundle + +import ( + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/pkg/lib/bundle" +) + +// newBundleGenerateCmd returns a command that will generate operator bundle +// annotations.yaml metadata +func newBundleGenerateCmd() *cobra.Command { + bundleGenerateCmd := &cobra.Command{ + Use: "generate", + Short: "Generate operator bundle metadata and Dockerfile", + Long: `The "opm alpha bundle generate" command will generate operator +bundle metadata if needed and a Dockerfile to build Operator bundle image. + +$ opm alpha bundle generate --directory /test/0.1.0/ --package test-operator \ + --channels stable,beta --default stable + +Note: +* All manifests yaml must be in the same directory.`, + RunE: generateFunc, + Args: cobra.NoArgs, + } + + bundleGenerateCmd.Flags().StringVarP(&buildDir, "directory", "d", "", + "The directory where bundle manifests for a specific version are located.") + if err := bundleGenerateCmd.MarkFlagRequired("directory"); err != nil { + log.Fatalf("Failed to mark `directory` flag for `generate` subcommand as required") + } + + bundleGenerateCmd.Flags().StringVarP(&pkg, "package", "p", "", + "The name of the package that bundle image belongs to "+ + "(Required if `directory` is not pointing to a bundle in the nested bundle format)") + + bundleGenerateCmd.Flags().StringVarP(&channels, "channels", "c", "", + "The list of channels that bundle image belongs to"+ + "(Required if `directory` is not pointing to a bundle in the nested bundle format)") + + bundleGenerateCmd.Flags().StringVarP(&defaultChannel, "default", "e", "", + "The default channel for the bundle image") + + bundleGenerateCmd.Flags().StringVarP(&outputDir, "output-dir", "u", "", + "Optional output directory for operator manifests") + + return bundleGenerateCmd +} + +func generateFunc(cmd *cobra.Command, _ []string) error { + return bundle.GenerateFunc( + buildDir, + outputDir, + pkg, + channels, + defaultChannel, + true, + ) +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/unpack.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/unpack.go new file mode 100644 index 0000000000..82bddff772 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/unpack.go @@ -0,0 +1,167 @@ +package bundle + +import ( + "context" + "crypto/x509" + "fmt" + "os" + "path/filepath" + + dircopy "github.com/otiai10/copy" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/cmd/opm/internal/util" + "github.com/operator-framework/operator-registry/pkg/image" + "github.com/operator-framework/operator-registry/pkg/image/containerdregistry" + "github.com/operator-framework/operator-registry/pkg/lib/bundle" +) + +func newBundleUnpackCmd() *cobra.Command { + unpack := &cobra.Command{ + Use: "unpack BUNDLE_NAME[:TAG|@DIGEST]", + Short: "Unpacks the content of an operator bundle", + Long: "Unpacks the content of an operator bundle into a directory", + Args: func(cmd *cobra.Command, args []string) error { + return cobra.ExactArgs(1)(cmd, args) + }, + RunE: unpackBundle, + } + unpack.Flags().BoolP("debug", "d", false, "enable debug log output") + unpack.Flags().BoolP("skip-tls", "s", false, "use plain HTTP") + unpack.Flags().Bool("skip-tls-verify", false, "disable TLS verification") + unpack.Flags().Bool("use-http", false, "use plain HTTP") + unpack.Flags().BoolP("skip-validation", "v", false, "disable bundle validation") + unpack.Flags().StringP("root-ca", "c", "", "file path of a root CA to use when communicating with image registries") + unpack.Flags().StringP("out", "o", "./", "directory in which to unpack operator bundle content") + + if err := unpack.Flags().MarkDeprecated("skip-tls", "use --use-http and --skip-tls-verify instead"); err != nil { + logrus.Panic(err.Error()) + } + return unpack +} + +func unpackBundle(cmd *cobra.Command, args []string) error { + debug, err := cmd.Flags().GetBool("debug") + if err != nil { + return err + } + + logger := logrus.WithField("cmd", "unpack") + if debug { + logger.Logger.SetLevel(logrus.DebugLevel) + } + + var out string + out, err = cmd.Flags().GetString("out") + if err != nil { + return err + } + + if info, err := os.Stat(out); err != nil { + if os.IsNotExist(err) { + err = os.MkdirAll(out, 0755) + } + if err != nil { + return err + } + } else { + if info == nil { + return fmt.Errorf("failed to get output directory info") + } + if !info.IsDir() { + return fmt.Errorf("out %s is not a directory", out) + } + } + + var ( + registryOpts []containerdregistry.RegistryOption + ) + + skipTLSVerify, useHTTP, err := util.GetTLSOptions(cmd) + if err != nil { + return err + } + + registryOpts = append(registryOpts, containerdregistry.SkipTLSVerify(skipTLSVerify), containerdregistry.WithPlainHTTP(useHTTP)) + + var skipValidation bool + skipValidation, err = cmd.Flags().GetBool("skip-validation") + if err != nil { + return err + } + + var rootCA string + rootCA, err = cmd.Flags().GetString("root-ca") + if err != nil { + return err + } + if rootCA != "" { + rootCAs := x509.NewCertPool() + certs, err := os.ReadFile(rootCA) + if err != nil { + return err + } + + if !rootCAs.AppendCertsFromPEM(certs) { + return fmt.Errorf("failed to fetch root CA from %s", rootCA) + } + + registryOpts = append(registryOpts, containerdregistry.WithRootCAs(rootCAs)) + } + + registry, err := containerdregistry.NewRegistry(registryOpts...) + if err != nil { + return err + } + defer func() { + if err := registry.Destroy(); err != nil { + logger.Error(err) + } + }() + + var ( + ref = image.SimpleReference(args[0]) + ctx = context.Background() + ) + if err := registry.Pull(ctx, ref); err != nil { + return err + } + + dir, err := os.MkdirTemp("", "bundle-") + if err != nil { + return err + } + + defer func() { + err := os.RemoveAll(dir) + if err != nil { + logger.Error(err.Error()) + } + }() + if err := registry.Unpack(ctx, ref, dir); err != nil { + return err + } + + if err := registry.Destroy(); err != nil { + return err + } + + if skipValidation { + logger.Info("skipping bundle validation") + } else { + validator := bundle.NewImageValidator(registry, logger) + if err := validator.ValidateBundleFormat(dir); err != nil { + return fmt.Errorf("bundle format validation failed: %s", err) + } + if err := validator.ValidateBundleContent(filepath.Join(dir, bundle.ManifestsDir)); err != nil { + return fmt.Errorf("bundle content validation failed: %s", err) + } + } + + if err := dircopy.Copy(dir, out); err != nil { + return fmt.Errorf("failed to copy unpacked content to output directory: %s", err) + } + + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/validate.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/validate.go new file mode 100644 index 0000000000..c1044c05c5 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle/validate.go @@ -0,0 +1,114 @@ +package bundle + +import ( + "fmt" + "os" + "path/filepath" + + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/pkg/containertools" + "github.com/operator-framework/operator-registry/pkg/image" + "github.com/operator-framework/operator-registry/pkg/image/containerdregistry" + "github.com/operator-framework/operator-registry/pkg/image/execregistry" + "github.com/operator-framework/operator-registry/pkg/lib/bundle" +) + +var ( + optional string +) + +func newBundleValidateCmd() *cobra.Command { + bundleValidateCmd := &cobra.Command{ + Use: "validate", + Short: "Validate bundle image", + Long: `The "opm alpha bundle validate" command will validate a bundle image +from a remote source to determine if its format and content information are accurate. +Required validators. These validators will run by default on every invocation of the command. + * CSV validator - validates the CSV name and replaces fields. + * CRD validator - validates the CRDs OpenAPI V3 schema. + * Bundle validator - validates the bundle format and annotations.yaml file as well as the optional dependencies.yaml file. + +Optional validators. These validators are disabled by default and can be enabled via the --optional-validators flag. + * Operatorhub validator - performs operatorhub.io validation. To validate a bundle using custom categories use with the OPERATOR_BUNDLE_CATEGORIES environmental variable to point to a json-encoded categories file. + * Bundle objects validator - performs validation on resources like PodDisruptionBudgets and PriorityClasses. + +See https://olm.operatorframework.io/docs/tasks/validate-package/#validation for more info. + +Note that this subcommand is deprecated and will be removed in a future release. Migrate to operator-sdk bundle validate.`, + Example: `$ opm alpha bundle validate --tag quay.io/test/test-operator:latest --image-builder docker`, + RunE: validateFunc, + Args: cobra.NoArgs, + Deprecated: "This subcommand is deprecated and will be removed in a future release. Migrate to operator-sdk bundle validate", + } + + bundleValidateCmd.Flags().StringVarP(&tag, "tag", "t", "", + "The path of a registry to pull from, image name and its tag that present the bundle image (e.g. quay.io/test/test-operator:latest)") + if err := bundleValidateCmd.MarkFlagRequired("tag"); err != nil { + log.Fatalf("Failed to mark `tag` flag for `validate` subcommand as required") + } + + bundleValidateCmd.Flags().StringVarP(&containerTool, "image-builder", "b", "docker", "Tool used to pull and unpack bundle images. One of: [none, docker, podman]") + bundleValidateCmd.Flags().StringVarP(&optional, "optional-validators", "o", "", "Specifies optional validations to be run. One or more of: [operatorhub, bundle-objects]") + + return bundleValidateCmd +} + +func validateFunc(cmd *cobra.Command, _ []string) error { + logger := log.WithFields(log.Fields{"container-tool": containerTool}) + log.SetLevel(log.DebugLevel) + + var ( + registry image.Registry + err error + ) + + tool := containertools.NewContainerTool(containerTool, containertools.NoneTool) + switch tool { + case containertools.PodmanTool, containertools.DockerTool: + registry, err = execregistry.NewRegistry(tool, logger) + case containertools.NoneTool: + registry, err = containerdregistry.NewRegistry(containerdregistry.WithLog(logger)) + default: + err = fmt.Errorf("unrecognized container-tool option: %s", containerTool) + } + + if err != nil { + return err + } + imageValidator := bundle.NewImageValidator(registry, logger, optional) + + dir, err := os.MkdirTemp("", "bundle-") + logger.Infof("Create a temp directory at %s", dir) + if err != nil { + return err + } + defer func() { + err := os.RemoveAll(dir) + if err != nil { + logger.Error(err.Error()) + } + }() + + err = imageValidator.PullBundleImage(tag, dir) + if err != nil { + return err + } + + logger.Info("Unpacked image layers, validating bundle image format & contents") + + err = imageValidator.ValidateBundleFormat(dir) + if err != nil { + return err + } + + err = imageValidator.ValidateBundleContent(filepath.Join(dir, bundle.ManifestsDir)) + if err != nil { + return err + } + + logger.Info("All validation tests have been completed successfully") + + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/cmd.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/cmd.go new file mode 100644 index 0000000000..202d9597fc --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/cmd.go @@ -0,0 +1,31 @@ +package alpha + +import ( + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle" + "github.com/operator-framework/operator-registry/cmd/opm/alpha/list" + rendergraph "github.com/operator-framework/operator-registry/cmd/opm/alpha/render-graph" + "github.com/operator-framework/operator-registry/cmd/opm/alpha/template" +) + +func NewCmd(showAlphaHelp bool) *cobra.Command { + runCmd := &cobra.Command{ + Use: "alpha", + Short: "Run an alpha subcommand", + Args: cobra.NoArgs, + Run: func(_ *cobra.Command, _ []string) {}, // adding an empty function here to preserve non-zero exit status for misstated subcommands/flags for the command hierarchy + } + + if !showAlphaHelp { + runCmd.Hidden = true + } + + runCmd.AddCommand( + bundle.NewCmd(), + list.NewCmd(), + rendergraph.NewCmd(), + template.NewCmd(), + ) + return runCmd +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/list/cmd.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/list/cmd.go new file mode 100644 index 0000000000..0f234e39bc --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/list/cmd.go @@ -0,0 +1,124 @@ +package list + +import ( + "os" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/alpha/action" + "github.com/operator-framework/operator-registry/cmd/opm/internal/util" +) + +const humanReadabilityOnlyNote = `NOTE: This is meant to be used for convenience and human-readability only. The +CLI and output format are subject to change, so it is not recommended to depend +on the output in any programs or scripts. Use the "render" subcommand to do +more complex processing and automation.` + +func NewCmd() *cobra.Command { + list := &cobra.Command{ + Use: "list", + Short: "List contents of an index", + Long: `The list subcommands print the contents of an index. + +` + humanReadabilityOnlyNote, + } + + list.AddCommand(newPackagesCmd(), newChannelsCmd(), newBundlesCmd()) + return list +} + +func newPackagesCmd() *cobra.Command { + logger := logrus.New() + + return &cobra.Command{ + Use: "packages ", + Short: "List packages in an index", + Long: `The "channels" command lists the channels from the specified index. + +` + humanReadabilityOnlyNote, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + reg, err := util.CreateCLIRegistry(cmd) + if err != nil { + logger.Fatal(err) + } + defer reg.Destroy() + lp := action.ListPackages{IndexReference: args[0], Registry: reg} + res, err := lp.Run(cmd.Context()) + if err != nil { + logger.Fatal(err) + } + if err := res.WriteColumns(os.Stdout); err != nil { + logger.Fatal(err) + } + return nil + }, + } +} + +func newChannelsCmd() *cobra.Command { + logger := logrus.New() + + return &cobra.Command{ + Use: "channels [packageName]", + Short: "List package channels in an index", + Long: `The "channels" command lists the channels from the specified index and package. + +` + humanReadabilityOnlyNote, + Args: cobra.RangeArgs(1, 2), + RunE: func(cmd *cobra.Command, args []string) error { + reg, err := util.CreateCLIRegistry(cmd) + if err != nil { + logger.Fatal(err) + } + defer reg.Destroy() + lc := action.ListChannels{IndexReference: args[0], Registry: reg} + if len(args) > 1 { + lc.PackageName = args[1] + } + res, err := lc.Run(cmd.Context()) + if err != nil { + logger.Fatal(err) + } + if err := res.WriteColumns(os.Stdout); err != nil { + logger.Fatal(err) + } + return nil + }, + } +} + +func newBundlesCmd() *cobra.Command { + logger := logrus.New() + + return &cobra.Command{ + Use: "bundles ", + Short: "List package bundles in an index", + Long: `The "bundles" command lists the bundles from the specified index and package. +Bundles that exist in multiple channels are duplicated in the output (one +for each channel in which the bundle is present). + +` + humanReadabilityOnlyNote, + Args: cobra.RangeArgs(1, 2), + RunE: func(cmd *cobra.Command, args []string) error { + reg, err := util.CreateCLIRegistry(cmd) + if err != nil { + logger.Fatal(err) + } + defer reg.Destroy() + lb := action.ListBundles{IndexReference: args[0], Registry: reg} + if len(args) > 1 { + lb.PackageName = args[1] + } + res, err := lb.Run(cmd.Context()) + if err != nil { + logger.Fatal(err) + } + if err := res.WriteColumns(os.Stdout); err != nil { + logger.Fatal(err) + } + return nil + }, + } +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/render-graph/cmd.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/render-graph/cmd.go new file mode 100644 index 0000000000..d3f7523e1a --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/render-graph/cmd.go @@ -0,0 +1,78 @@ +package rendergraph + +import ( + "io" + "log" + "os" + + "github.com/operator-framework/operator-registry/alpha/action" + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/cmd/opm/internal/util" + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +func NewCmd() *cobra.Command { + var ( + render action.Render + minEdge string + specifiedPackageName string + ) + cmd := &cobra.Command{ + Use: "render-graph [index-image | fbc-dir]", + Short: "Generate mermaid-formatted view of upgrade graph of operators in an index", + Long: `Generate mermaid-formatted view of upgrade graphs of operators in an index`, + Args: cobra.MinimumNArgs(1), + Example: ` +# +# Output channel graph of a catalog in mermaid format +# +$ opm alpha render-graph quay.io/operatorhubio/catalog:latest + +# +# Output channel graph of a catalog and generate a scaled vector graphic (SVG) representation +# +$ opm alpha render-graph quay.io/operatorhubio/catalog:latest | \ + docker run --rm -i -v "$PWD":/data ghcr.io/mermaid-js/mermaid-cli/mermaid-cli -o /data/operatorhubio-catalog.svg + +# Note: mermaid has a default maxTextSize of 30 000 characters. To override this, generate a JSON-formatted initialization file for +# mermaid like this (using 300 000 for the limit): +$ cat << EOF > ./mermaid.json +{ "maxTextSize": 300000 } +EOF +# and then pass the file for initialization configuration, via the '-c' option, like: +$ opm alpha render-graph quay.io/operatorhubio/catalog:latest | \ + docker run --rm -i -v "$PWD":/data ghcr.io/mermaid-js/mermaid-cli/mermaid-cli -c /data/mermaid.json -o /data/operatorhubio-catalog.svg + + + `, + Run: func(cmd *cobra.Command, args []string) { + // The bundle loading impl is somewhat verbose, even on the happy path, + // so discard all logrus default logger logs. Any important failures will be + // returned from render.Run and logged as fatal errors. + logrus.SetOutput(io.Discard) + + registry, err := util.CreateCLIRegistry(cmd) + if err != nil { + log.Fatal(err) + } + + render.Refs = args + render.AllowedRefMask = action.RefDCImage | action.RefDCDir | action.RefSqliteImage | action.RefSqliteFile + render.Registry = registry + + cfg, err := render.Run(cmd.Context()) + if err != nil { + log.Fatal(err) + } + + writer := declcfg.NewMermaidWriter(declcfg.WithMinEdgeName(minEdge), declcfg.WithSpecifiedPackageName(specifiedPackageName)) + if err := writer.WriteChannels(*cfg, os.Stdout); err != nil { + log.Fatal(err) + } + }, + } + cmd.Flags().StringVar(&minEdge, "minimum-edge", "", "the channel edge to be used as the lower bound of the set of edges composing the upgrade graph; default is to include all edges") + cmd.Flags().StringVarP(&specifiedPackageName, "package-name", "p", "", "a specific package name to filter output; default is to include all packages in reference") + return cmd +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/basic.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/basic.go new file mode 100644 index 0000000000..5d34ec2cd8 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/basic.go @@ -0,0 +1,75 @@ +package template + +import ( + "io" + "log" + "os" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/alpha/template/basic" + "github.com/operator-framework/operator-registry/cmd/opm/internal/util" +) + +func newBasicTemplateCmd() *cobra.Command { + var ( + template basic.Template + output string + ) + cmd := &cobra.Command{ + Use: "basic basic-template-file", + Short: `Generate a file-based catalog from a single 'basic template' file +When FILE is '-' or not provided, the template is read from standard input`, + Long: `Generate a file-based catalog from a single 'basic template' file +When FILE is '-' or not provided, the template is read from standard input`, + Args: cobra.MaximumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + // Handle different input argument types + // When no arguments or "-" is passed to the command, + // assume input is coming from stdin + // Otherwise open the file passed to the command + data, source, err := openFileOrStdin(cmd, args) + if err != nil { + log.Fatalf("unable to open %q: %v", source, err) + } + defer data.Close() + + var write func(declcfg.DeclarativeConfig, io.Writer) error + switch output { + case "yaml": + write = declcfg.WriteYAML + case "json": + write = declcfg.WriteJSON + default: + log.Fatalf("invalid --output value %q, expected (json|yaml)", output) + } + + // The bundle loading impl is somewhat verbose, even on the happy path, + // so discard all logrus default logger logs. Any important failures will be + // returned from template.Render and logged as fatal errors. + logrus.SetOutput(io.Discard) + + reg, err := util.CreateCLIRegistry(cmd) + if err != nil { + log.Fatalf("creating containerd registry: %v", err) + } + defer reg.Destroy() + + template.Registry = reg + + // only taking first file argument + cfg, err := template.Render(cmd.Context(), data) + if err != nil { + log.Fatal(err) + } + + if err := write(*cfg, os.Stdout); err != nil { + log.Fatal(err) + } + }, + } + cmd.Flags().StringVarP(&output, "output", "o", "json", "Output format (json|yaml)") + return cmd +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/cmd.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/cmd.go new file mode 100644 index 0000000000..1c435e6fa2 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/cmd.go @@ -0,0 +1,30 @@ +package template + +import ( + "io" + "os" + + "github.com/spf13/cobra" +) + +func NewCmd() *cobra.Command { + runCmd := &cobra.Command{ + Use: "render-template", + Short: "Render a catalog template type", + Args: cobra.NoArgs, + } + + runCmd.AddCommand(newBasicTemplateCmd()) + runCmd.AddCommand(newSemverTemplateCmd()) + runCmd.AddCommand(newCompositeTemplateCmd()) + + return runCmd +} + +func openFileOrStdin(cmd *cobra.Command, args []string) (io.ReadCloser, string, error) { + if len(args) == 0 || args[0] == "-" { + return io.NopCloser(cmd.InOrStdin()), "stdin", nil + } + reader, err := os.Open(args[0]) + return reader, args[0], err +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/composite.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/composite.go new file mode 100644 index 0000000000..20c9a1e5c1 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/composite.go @@ -0,0 +1,83 @@ +package template + +import ( + "log" + "net/http" + "os" + "path/filepath" + + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/alpha/template/composite" + "github.com/operator-framework/operator-registry/cmd/opm/internal/util" +) + +func newCompositeTemplateCmd() *cobra.Command { + var ( + output string + validate bool + compositeFile string + catalogFile string + ) + cmd := &cobra.Command{ + Use: "composite", + Short: `Generate file-based catalogs from a catalog configuration file +and a 'composite template' file`, + Long: `Generate file-based catalogs from a catalog configuration file +and a 'composite template' file`, + Args: cobra.MaximumNArgs(0), + Run: func(cmd *cobra.Command, args []string) { + + switch output { + case "yaml": + // do nothing + case "json": + // do nothing + default: + log.Fatalf("invalid --output value %q, expected (json|yaml)", output) + } + + reg, err := util.CreateCLIRegistry(cmd) + if err != nil { + log.Fatalf("creating containerd registry: %v", err) + } + defer reg.Destroy() + + // operator author's 'composite.yaml' file + compositeReader, err := os.Open(compositeFile) + if err != nil { + log.Fatalf("opening composite config file %q: %v", compositeFile, err) + } + defer compositeReader.Close() + + compositePath, err := filepath.Abs(filepath.Dir(compositeFile)) + if err != nil { + log.Fatalf("getting absolute path of composite config file %q: %v", compositeFile, err) + } + + // catalog maintainer's 'catalogs.yaml' file + tempCatalog, err := composite.FetchCatalogConfig(catalogFile, http.DefaultClient) + if err != nil { + log.Fatalf(err.Error()) + } + defer tempCatalog.Close() + + template := composite.NewTemplate( + composite.WithCatalogFile(tempCatalog), + composite.WithContributionFile(compositeReader, compositePath), + composite.WithOutputType(output), + composite.WithRegistry(reg), + ) + + err = template.Render(cmd.Context(), validate) + if err != nil { + log.Fatalf("rendering the composite template: %v", err) + } + }, + } + cmd.Flags().StringVarP(&output, "output", "o", "json", "Output format (json|yaml)") + cmd.Flags().BoolVar(&validate, "validate", true, "whether or not the created FBC should be validated (i.e 'opm validate')") + cmd.Flags().StringVarP(&compositeFile, "composite-config", "c", "composite.yaml", "File to use as the composite configuration file") + cmd.Flags().StringVarP(&catalogFile, "catalog-config", "f", "catalogs.yaml", "File to use as the catalog configuration file") + return cmd +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/semver.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/semver.go new file mode 100644 index 0000000000..f67f9596c0 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/semver.go @@ -0,0 +1,84 @@ +package template + +import ( + "fmt" + "io" + "log" + "os" + + "github.com/sirupsen/logrus" + + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/alpha/template/semver" + "github.com/operator-framework/operator-registry/cmd/opm/internal/util" + "github.com/spf13/cobra" +) + +func newSemverTemplateCmd() *cobra.Command { + output := "" + cmd := &cobra.Command{ + Use: "semver [FILE]", + Short: `Generate a file-based catalog from a single 'semver template' file +When FILE is '-' or not provided, the template is read from standard input`, + Long: `Generate a file-based catalog from a single 'semver template' file +When FILE is '-' or not provided, the template is read from standard input`, + Args: cobra.MaximumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + // Handle different input argument types + // When no arguments or "-" is passed to the command, + // assume input is coming from stdin + // Otherwise open the file passed to the command + data, source, err := openFileOrStdin(cmd, args) + if err != nil { + return err + } + defer data.Close() + + var write func(declcfg.DeclarativeConfig, io.Writer) error + switch output { + case "json": + write = declcfg.WriteJSON + case "yaml": + write = declcfg.WriteYAML + case "mermaid": + write = func(cfg declcfg.DeclarativeConfig, writer io.Writer) error { + mermaidWriter := declcfg.NewMermaidWriter() + return mermaidWriter.WriteChannels(cfg, writer) + } + default: + return fmt.Errorf("invalid output format %q", output) + } + + // The bundle loading impl is somewhat verbose, even on the happy path, + // so discard all logrus default logger logs. Any important failures will be + // returned from template.Render and logged as fatal errors. + logrus.SetOutput(io.Discard) + + reg, err := util.CreateCLIRegistry(cmd) + if err != nil { + log.Fatalf("creating containerd registry: %v", err) + } + defer reg.Destroy() + + template := semver.Template{ + Data: data, + Registry: reg, + } + out, err := template.Render(cmd.Context()) + if err != nil { + log.Fatalf("semver %q: %v", source, err) + } + + if out != nil { + if err := write(*out, os.Stdout); err != nil { + log.Fatal(err) + } + } + + return nil + }, + } + + cmd.Flags().StringVarP(&output, "output", "o", "json", "Output format (json|yaml|mermaid)") + return cmd +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/generate/cmd.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/generate/cmd.go new file mode 100644 index 0000000000..7871a7f52f --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/generate/cmd.go @@ -0,0 +1,111 @@ +package generate + +import ( + "fmt" + "log" + "os" + "path/filepath" + "strings" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/alpha/action" + "github.com/operator-framework/operator-registry/pkg/containertools" +) + +func NewCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "generate", + Short: "Generate various artifacts for declarative config indexes", + } + cmd.AddCommand( + newDockerfileCmd(), + ) + return cmd +} + +func newDockerfileCmd() *cobra.Command { + var ( + baseImage string + extraLabelStrs []string + ) + cmd := &cobra.Command{ + Use: "dockerfile ", + Args: cobra.ExactArgs(1), + Short: "Generate a Dockerfile for a declarative config index", + Long: `Generate a Dockerfile for a declarative config index. + +This command creates a Dockerfile in the same directory as the +(named .Dockerfile) that can be used to build the index. If a +Dockerfile with the same name already exists, this command will fail. + +When specifying extra labels, note that if duplicate keys exist, only the last +value of each duplicate key will be added to the generated Dockerfile. +`, + RunE: func(_ *cobra.Command, args []string) error { + fromDir := filepath.Clean(args[0]) + + extraLabels, err := parseLabels(extraLabelStrs) + if err != nil { + return err + } + + dir, indexName := filepath.Split(fromDir) + dockerfilePath := filepath.Join(dir, fmt.Sprintf("%s.Dockerfile", indexName)) + + if err := ensureNotExist(dockerfilePath); err != nil { + logrus.Fatal(err) + } + + if s, err := os.Stat(fromDir); err != nil { + return err + } else if !s.IsDir() { + return fmt.Errorf("provided root path %q is not a directory", fromDir) + } + + f, err := os.OpenFile(dockerfilePath, os.O_CREATE|os.O_WRONLY, 0666) + if err != nil { + logrus.Fatal(err) + } + defer f.Close() + + gen := action.GenerateDockerfile{ + BaseImage: baseImage, + IndexDir: indexName, + ExtraLabels: extraLabels, + Writer: f, + } + if err := gen.Run(); err != nil { + log.Fatal(err) + } + return nil + }, + } + cmd.Flags().StringVarP(&baseImage, "binary-image", "i", containertools.DefaultBinarySourceImage, "Image in which to build catalog.") + cmd.Flags().StringSliceVarP(&extraLabelStrs, "extra-labels", "l", []string{}, "Extra labels to include in the generated Dockerfile. Labels should be of the form 'key=value'.") + return cmd +} + +func parseLabels(labelStrs []string) (map[string]string, error) { + labels := map[string]string{} + for _, l := range labelStrs { + spl := strings.SplitN(l, "=", 2) + if len(spl) != 2 { + return nil, fmt.Errorf("invalid label %q", l) + } + labels[spl[0]] = spl[1] + } + return labels, nil +} + +func ensureNotExist(path string) error { + _, err := os.Stat(path) + if err != nil && !os.IsNotExist(err) { + return err + } + if err == nil { + return fmt.Errorf("path %q: %w", path, os.ErrExist) + } + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/add.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/add.go new file mode 100644 index 0000000000..e3db1854a7 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/add.go @@ -0,0 +1,234 @@ +package index + +import ( + "fmt" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "k8s.io/kubectl/pkg/util/templates" + + "github.com/operator-framework/operator-registry/cmd/opm/internal/util" + "github.com/operator-framework/operator-registry/pkg/containertools" + "github.com/operator-framework/operator-registry/pkg/lib/indexer" + "github.com/operator-framework/operator-registry/pkg/registry" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +var ( + addLong = templates.LongDesc(` + Add operator bundles to an index. + + This command will add the given set of bundle images (specified by the --bundles option) to an index image (provided by the --from-index option). + + If multiple bundles are given with '--mode=replaces' (the default), bundles are added to the index by order of ascending (semver) version unless the update graph specified by replaces requires a different input order; e.g. 1.0.0 replaces 1.0.1 would result in [1.0.1, 1.0.0] instead of the [1.0.0, 1.0.1] normally expected of semver. However, for most cases (e.g. 1.0.1 replaces 1.0.0) the bundle with the highest version is used to set the default channel of the related package. + + Caveat: in replaces mode, the head of a channel is always the bundle with the highest semver. Any bundles upgrading from this channel-head will be pruned. + An upgrade graph that looks like: + 0.1.1 -> 0.1.2 -> 0.1.2-1 + will be pruned on add to: + 0.1.1 -> 0.1.2 +`) + "\n\n" + sqlite.DeprecationMessage + + addExample = templates.Examples(` + # Create an index image from scratch with a single bundle image + %[1]s --bundles quay.io/operator-framework/operator-bundle-prometheus@sha256:a3ee653ffa8a0d2bbb2fabb150a94da6e878b6e9eb07defd40dc884effde11a0 --tag quay.io/operator-framework/monitoring:1.0.0 + + # Add a single bundle image to an index image + %[1]s --bundles quay.io/operator-framework/operator-bundle-prometheus:0.15.0 --from-index quay.io/operator-framework/monitoring:1.0.0 --tag quay.io/operator-framework/monitoring:1.0.1 + + # Add multiple bundles to an index and generate a Dockerfile instead of an image + %[1]s --bundles quay.io/operator-framework/operator-bundle-prometheus:0.15.0,quay.io/operator-framework/operator-bundle-prometheus:0.22.2 --generate + `) +) + +func addIndexAddCmd(parent *cobra.Command, showAlphaHelp bool) { + indexCmd := &cobra.Command{ + Use: "add", + Short: "Add operator bundles to an index.", + Long: addLong, + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + RunE: runIndexAddCmdFunc, + Args: cobra.NoArgs, + } + + indexCmd.Flags().Bool("debug", false, "enable debug logging") + indexCmd.Flags().Bool("generate", false, "if enabled, just creates the dockerfile and saves it to local disk") + indexCmd.Flags().StringP("out-dockerfile", "d", "", "if generating the dockerfile, this flag is used to (optionally) specify a dockerfile name") + indexCmd.Flags().StringP("from-index", "f", "", "previous index to add to") + // adding empty list of strings is a valid value. + indexCmd.Flags().StringSliceP("bundles", "b", nil, "comma separated list of bundles to add") + if err := indexCmd.MarkFlagRequired("bundles"); err != nil { + logrus.Panic("Failed to set required `bundles` flag for `index add`") + } + indexCmd.Flags().StringP("binary-image", "i", "", "container image for on-image `opm` command") + indexCmd.Flags().StringP("container-tool", "c", "", "tool to interact with container images (save, build, etc.). One of: [docker, podman]") + indexCmd.Flags().StringP("build-tool", "u", "", "tool to build container images. One of: [docker, podman]. Defaults to podman. Overrides part of container-tool.") + indexCmd.Flags().StringP("pull-tool", "p", "", "tool to pull container images. One of: [none, docker, podman]. Defaults to none. Overrides part of container-tool.") + indexCmd.Flags().StringP("tag", "t", "", "custom tag for container image being built") + indexCmd.Flags().Bool("permissive", false, "allow registry load errors") + indexCmd.Flags().StringP("mode", "", "replaces", "graph update mode that defines how channel graphs are updated. One of: [replaces, semver, semver-skippatch]") + + indexCmd.Flags().Bool("overwrite-latest", false, "overwrite the latest bundles (channel heads) with those of the same csv name given by --bundles") + if err := indexCmd.Flags().MarkHidden("overwrite-latest"); err != nil { + logrus.Panic(err.Error()) + } + indexCmd.Flags().Bool("enable-alpha", false, "enable unsupported alpha features of the OPM CLI") + if !showAlphaHelp { + if err := indexCmd.Flags().MarkHidden("enable-alpha"); err != nil { + logrus.Panic(err.Error()) + } + } + if err := indexCmd.Flags().MarkHidden("debug"); err != nil { + logrus.Panic(err.Error()) + } + + // Set the example after the parent has been set to get the correct command path + parent.AddCommand(indexCmd) + indexCmd.Example = fmt.Sprintf(addExample, indexCmd.CommandPath()) + +} + +func runIndexAddCmdFunc(cmd *cobra.Command, _ []string) error { + generate, err := cmd.Flags().GetBool("generate") + if err != nil { + return err + } + + outDockerfile, err := cmd.Flags().GetString("out-dockerfile") + if err != nil { + return err + } + + fromIndex, err := cmd.Flags().GetString("from-index") + if err != nil { + return err + } + + bundles, err := cmd.Flags().GetStringSlice("bundles") + if err != nil { + return err + } + + binaryImage, err := cmd.Flags().GetString("binary-image") + if err != nil { + return err + } + + tag, err := cmd.Flags().GetString("tag") + if err != nil { + return err + } + + permissive, err := cmd.Flags().GetBool("permissive") + if err != nil { + return err + } + + skipTLSVerify, useHTTP, err := util.GetTLSOptions(cmd) + if err != nil { + return err + } + + mode, err := cmd.Flags().GetString("mode") + if err != nil { + return err + } + + overwrite, err := cmd.Flags().GetBool("overwrite-latest") + if err != nil { + return err + } + + enableAlpha, err := cmd.Flags().GetBool("enable-alpha") + if err != nil { + return err + } + + modeEnum, err := registry.GetModeFromString(mode) + if err != nil { + return err + } + + pullTool, buildTool, err := getContainerTools(cmd) + if err != nil { + return err + } + + logger := logrus.WithFields(logrus.Fields{"bundles": bundles}) + + logger.Info("building the index") + + indexAdder := indexer.NewIndexAdder( + containertools.NewContainerTool(buildTool, containertools.PodmanTool), + containertools.NewContainerTool(pullTool, containertools.NoneTool), + logger) + + request := indexer.AddToIndexRequest{ + Generate: generate, + FromIndex: fromIndex, + BinarySourceImage: binaryImage, + OutDockerfile: outDockerfile, + Tag: tag, + Bundles: bundles, + Permissive: permissive, + Mode: modeEnum, + SkipTLSVerify: skipTLSVerify, + PlainHTTP: useHTTP, + Overwrite: overwrite, + EnableAlpha: enableAlpha, + } + + err = indexAdder.AddToIndex(request) + if err != nil { + return err + } + + return nil +} + +// getContainerTools returns the pull and build tools based on command line input +// to preserve backwards compatibility and alias the legacy `container-tool` parameter +func getContainerTools(cmd *cobra.Command) (string, string, error) { + buildTool, err := cmd.Flags().GetString("build-tool") + if err != nil { + return "", "", err + } + + if buildTool == "none" { + return "", "", fmt.Errorf("none is not a valid container-tool for index add") + } + + pullTool, err := cmd.Flags().GetString("pull-tool") + if err != nil { + return "", "", err + } + + containerTool, err := cmd.Flags().GetString("container-tool") + if err != nil { + return "", "", err + } + + // Backwards compatiblity mode + if containerTool != "" { + if pullTool == "" && buildTool == "" { + return containerTool, containerTool, nil + } + return "", "", fmt.Errorf("container-tool cannot be set alongside pull-tool or build-tool") + } + + // Check for defaults, then return + if pullTool == "" { + pullTool = "none" + } + + if buildTool == "" { + buildTool = "podman" + } + + return pullTool, buildTool, nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/cmd.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/cmd.go new file mode 100644 index 0000000000..8ee008e097 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/cmd.go @@ -0,0 +1,42 @@ +package index + +import ( + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +// AddCommand adds the index subcommand to the given parent command. +func AddCommand(parent *cobra.Command, showAlphaHelp bool) { + cmd := &cobra.Command{ + Use: "index", + Short: "generate operator index container images", + Long: `generate operator index container images from preexisting operator bundles + +` + sqlite.DeprecationMessage, + + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + PersistentPreRun: func(cmd *cobra.Command, _ []string) { + sqlite.LogSqliteDeprecation() + if skipTLS, err := cmd.Flags().GetBool("skip-tls"); err == nil && skipTLS { + logrus.Warn("--skip-tls flag is set: this mode is insecure and meant for development purposes only.") + } + }, + Args: cobra.NoArgs, + } + + parent.AddCommand(cmd) + + cmd.AddCommand(newIndexDeleteCmd()) + addIndexAddCmd(cmd, showAlphaHelp) + cmd.AddCommand(newIndexExportCmd()) + cmd.AddCommand(newIndexPruneCmd()) + cmd.AddCommand(newIndexDeprecateTruncateCmd()) + cmd.AddCommand(newIndexPruneStrandedCmd()) +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/delete.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/delete.go new file mode 100644 index 0000000000..f7970676af --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/delete.go @@ -0,0 +1,131 @@ +package index + +import ( + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/cmd/opm/internal/util" + "github.com/operator-framework/operator-registry/pkg/containertools" + "github.com/operator-framework/operator-registry/pkg/lib/indexer" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +func newIndexDeleteCmd() *cobra.Command { + indexCmd := &cobra.Command{ + Use: "rm", + Short: "delete an entire operator from an index", + Long: `delete an entire operator from an index + +` + sqlite.DeprecationMessage, + + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + + RunE: runIndexDeleteCmdFunc, + Args: cobra.NoArgs, + } + + indexCmd.Flags().Bool("debug", false, "enable debug logging") + indexCmd.Flags().Bool("generate", false, "if enabled, just creates the dockerfile and saves it to local disk") + indexCmd.Flags().StringP("out-dockerfile", "d", "", "if generating the dockerfile, this flag is used to (optionally) specify a dockerfile name") + indexCmd.Flags().StringP("from-index", "f", "", "previous index to delete from") + if err := indexCmd.MarkFlagRequired("from-index"); err != nil { + logrus.Panic("Failed to set required `from-index` flag for `index delete`") + } + indexCmd.Flags().StringSliceP("operators", "o", nil, "comma separated list of operators to delete") + if err := indexCmd.MarkFlagRequired("operators"); err != nil { + logrus.Panic("Failed to set required `operators` flag for `index delete`") + } + indexCmd.Flags().StringP("binary-image", "i", "", "container image for on-image `opm` command") + indexCmd.Flags().StringP("container-tool", "c", "", "tool to interact with container images (save, build, etc.). One of: [none, docker, podman]") + indexCmd.Flags().StringP("build-tool", "u", "", "tool to build container images. One of: [docker, podman]. Defaults to podman. Overrides part of container-tool.") + indexCmd.Flags().StringP("pull-tool", "p", "", "tool to pull container images. One of: [none, docker, podman]. Defaults to none. Overrides part of container-tool.") + indexCmd.Flags().StringP("tag", "t", "", "custom tag for container image being built") + indexCmd.Flags().Bool("permissive", false, "allow registry load errors") + + if err := indexCmd.Flags().MarkHidden("debug"); err != nil { + logrus.Panic(err.Error()) + } + + return indexCmd + +} + +func runIndexDeleteCmdFunc(cmd *cobra.Command, _ []string) error { + generate, err := cmd.Flags().GetBool("generate") + if err != nil { + return err + } + + outDockerfile, err := cmd.Flags().GetString("out-dockerfile") + if err != nil { + return err + } + + fromIndex, err := cmd.Flags().GetString("from-index") + if err != nil { + return err + } + + operators, err := cmd.Flags().GetStringSlice("operators") + if err != nil { + return err + } + + binaryImage, err := cmd.Flags().GetString("binary-image") + if err != nil { + return err + } + + pullTool, buildTool, err := getContainerTools(cmd) + if err != nil { + return err + } + + tag, err := cmd.Flags().GetString("tag") + if err != nil { + return err + } + + permissive, err := cmd.Flags().GetBool("permissive") + if err != nil { + return err + } + + skipTLSVerify, useHTTP, err := util.GetTLSOptions(cmd) + if err != nil { + return err + } + + logger := logrus.WithFields(logrus.Fields{"operators": operators}) + + logger.Info("building the index") + + indexDeleter := indexer.NewIndexDeleter( + containertools.NewContainerTool(buildTool, containertools.PodmanTool), + containertools.NewContainerTool(pullTool, containertools.NoneTool), + logger) + + request := indexer.DeleteFromIndexRequest{ + Generate: generate, + FromIndex: fromIndex, + BinarySourceImage: binaryImage, + OutDockerfile: outDockerfile, + Operators: operators, + Tag: tag, + Permissive: permissive, + SkipTLSVerify: skipTLSVerify, + PlainHTTP: useHTTP, + } + + err = indexDeleter.DeleteFromIndex(request) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/deprecatetruncate.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/deprecatetruncate.go new file mode 100644 index 0000000000..33206e3235 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/deprecatetruncate.go @@ -0,0 +1,152 @@ +package index + +import ( + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "k8s.io/kubectl/pkg/util/templates" + + "github.com/operator-framework/operator-registry/cmd/opm/internal/util" + "github.com/operator-framework/operator-registry/pkg/containertools" + "github.com/operator-framework/operator-registry/pkg/lib/indexer" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +var deprecateLong = templates.LongDesc(` + Deprecate and truncate operator bundles from an index. + + Deprecated bundles will no longer be installable. Bundles that are replaced by deprecated bundles will be removed entirely from the index. + + For example: + + Given the update graph in quay.io/my/index:v1 + 1.4.0 -- replaces -> 1.3.0 -- replaces -> 1.2.0 -- replaces -> 1.1.0 + + Applying the command: + opm index deprecatetruncate --bundles "quay.io/my/bundle:1.3.0" --from-index "quay.io/my/index:v1" --tag "quay.io/my/index:v2" + + Produces the following update graph in quay.io/my/index:v2 + 1.4.0 -- replaces -> 1.3.0 [deprecated] + + Deprecating a bundle that removes the default channel is not allowed unless the head(s) of all channels are being deprecated (the package is subsequently removed from the index). + This behavior can be enabled via the allow-package-removal flag. + Changing the default channel prior to deprecation is possible by publishing a new bundle to the index. + `) + "\n\n" + sqlite.DeprecationMessage + +func newIndexDeprecateTruncateCmd() *cobra.Command { + indexCmd := &cobra.Command{ + Hidden: true, + Use: "deprecatetruncate", + Short: "Deprecate and truncate operator bundles from an index.", + Long: deprecateLong, + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + RunE: runIndexDeprecateTruncateCmdFunc, + Args: cobra.NoArgs, + } + + indexCmd.Flags().Bool("debug", false, "enable debug logging") + indexCmd.Flags().Bool("generate", false, "if enabled, just creates the dockerfile and saves it to local disk") + indexCmd.Flags().StringP("out-dockerfile", "d", "", "if generating the dockerfile, this flag is used to (optionally) specify a dockerfile name") + indexCmd.Flags().StringP("from-index", "f", "", "previous index to add to") + indexCmd.Flags().StringSliceP("bundles", "b", nil, "comma separated list of bundles to add") + if err := indexCmd.MarkFlagRequired("bundles"); err != nil { + logrus.Panic("Failed to set required `bundles` flag for `index add`") + } + indexCmd.Flags().StringP("binary-image", "i", "", "container image for on-image `opm` command") + indexCmd.Flags().StringP("container-tool", "c", "", "tool to interact with container images (save, build, etc.). One of: [docker, podman]") + indexCmd.Flags().StringP("build-tool", "u", "", "tool to build container images. One of: [docker, podman]. Defaults to podman. Overrides part of container-tool.") + indexCmd.Flags().StringP("pull-tool", "p", "", "tool to pull container images. One of: [none, docker, podman]. Defaults to none. Overrides part of container-tool.") + indexCmd.Flags().StringP("tag", "t", "", "custom tag for container image being built") + indexCmd.Flags().Bool("permissive", false, "allow registry load errors") + if err := indexCmd.Flags().MarkHidden("debug"); err != nil { + logrus.Panic(err.Error()) + } + indexCmd.Flags().Bool("allow-package-removal", false, "removes the entire package if the heads of all channels in the package are deprecated") + + return indexCmd +} + +func runIndexDeprecateTruncateCmdFunc(cmd *cobra.Command, _ []string) error { + generate, err := cmd.Flags().GetBool("generate") + if err != nil { + return err + } + + outDockerfile, err := cmd.Flags().GetString("out-dockerfile") + if err != nil { + return err + } + + fromIndex, err := cmd.Flags().GetString("from-index") + if err != nil { + return err + } + + bundles, err := cmd.Flags().GetStringSlice("bundles") + if err != nil { + return err + } + + binaryImage, err := cmd.Flags().GetString("binary-image") + if err != nil { + return err + } + + tag, err := cmd.Flags().GetString("tag") + if err != nil { + return err + } + + permissive, err := cmd.Flags().GetBool("permissive") + if err != nil { + return err + } + + pullTool, buildTool, err := getContainerTools(cmd) + if err != nil { + return err + } + + skipTLSVerify, useHTTP, err := util.GetTLSOptions(cmd) + if err != nil { + return err + } + + allowPackageRemoval, err := cmd.Flags().GetBool("allow-package-removal") + if err != nil { + return err + } + + logger := logrus.WithFields(logrus.Fields{"bundles": bundles}) + + logger.Info("deprecating bundles from the index") + + indexDeprecator := indexer.NewIndexDeprecator( + containertools.NewContainerTool(buildTool, containertools.PodmanTool), + containertools.NewContainerTool(pullTool, containertools.NoneTool), + logger) + + request := indexer.DeprecateFromIndexRequest{ + Generate: generate, + FromIndex: fromIndex, + BinarySourceImage: binaryImage, + OutDockerfile: outDockerfile, + Tag: tag, + Bundles: bundles, + Permissive: permissive, + SkipTLSVerify: skipTLSVerify, + PlainHTTP: useHTTP, + AllowPackageRemoval: allowPackageRemoval, + } + + err = indexDeprecator.DeprecateFromIndex(request) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/export.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/export.go new file mode 100644 index 0000000000..2541cbba69 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/export.go @@ -0,0 +1,130 @@ +package index + +import ( + "fmt" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "k8s.io/kubectl/pkg/util/templates" + + "github.com/operator-framework/operator-registry/cmd/opm/internal/util" + "github.com/operator-framework/operator-registry/pkg/containertools" + "github.com/operator-framework/operator-registry/pkg/lib/indexer" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +var exportLong = templates.LongDesc(` + Export an operator from an index image into the appregistry format. + + This command will take an index image (specified by the --index option), parse it for the given operator(s) (set by + the --package option) and export the operator metadata into an appregistry compliant format (a package.yaml file). + + Note: the appregistry format is being deprecated in favor of the new index image and image bundle format. + `) + "\n\n" + sqlite.DeprecationMessage + +func newIndexExportCmd() *cobra.Command { + indexCmd := &cobra.Command{ + Use: "export", + Short: "Export an operator from an index into the appregistry format", + Long: exportLong, + + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + + RunE: runIndexExportCmdFunc, + Args: cobra.NoArgs, + } + indexCmd.Flags().Bool("debug", false, "enable debug logging") + indexCmd.Flags().StringP("index", "i", "", "index to get package from") + if err := indexCmd.MarkFlagRequired("index"); err != nil { + logrus.Panic("Failed to set required `index` flag for `index export`") + } + indexCmd.Flags().StringSliceP("package", "p", nil, "comma separated list of packages to export") + indexCmd.Flags().StringP("download-folder", "f", "downloaded", "directory where downloaded operator bundle(s) will be stored") + indexCmd.Flags().StringP("container-tool", "c", "none", "tool to interact with container images (save, build, etc.). One of: [none, docker, podman]") + if err := indexCmd.Flags().MarkHidden("debug"); err != nil { + logrus.Panic(err.Error()) + } + + // Create hidden option so we can provide deprecated shorthand + indexCmd.Flags().StringSliceP("xpackage", "o", nil, "deprecated, please use --package option instead") + if err := indexCmd.Flags().MarkHidden("xpackage"); err != nil { + logrus.Panic(err.Error()) + } + + return indexCmd + +} + +func runIndexExportCmdFunc(cmd *cobra.Command, _ []string) error { + index, err := cmd.Flags().GetString("index") + if err != nil { + return err + } + + pkgFlag := cmd.Flag("package") + if pkgFlag == nil { + return fmt.Errorf("unable to get the package flag") + } + + xPkgFlag := cmd.Flag("xpackage") + if xPkgFlag == nil { + return fmt.Errorf("unable to get the package flag for deprecated shorthand '-o'") + } + + if xPkgFlag.Changed && pkgFlag.Changed { + return fmt.Errorf("cannot simultaneously set '-p' and '-o' flags, remove '-o'") + } + + packages, err := cmd.Flags().GetStringSlice("package") + if err != nil { + return err + } + if xPkgFlag.Changed { + // Use the deprecated shorthand + if packages, err = cmd.Flags().GetStringSlice("xpackage"); err != nil { + return err + } + } + + downloadPath, err := cmd.Flags().GetString("download-folder") + if err != nil { + return err + } + + containerTool, err := cmd.Flags().GetString("container-tool") + if err != nil { + return err + } + + skipTLSVerify, useHTTP, err := util.GetTLSOptions(cmd) + if err != nil { + return err + } + + logger := logrus.WithFields(logrus.Fields{"index": index, "package": packages}) + + logger.Info("export from the index") + + indexExporter := indexer.NewIndexExporter(containertools.NewContainerTool(containerTool, containertools.NoneTool), logger) + + request := indexer.ExportFromIndexRequest{ + Index: index, + Packages: packages, + DownloadPath: downloadPath, + ContainerTool: containertools.NewContainerTool(containerTool, containertools.NoneTool), + SkipTLSVerify: skipTLSVerify, + PlainHTTP: useHTTP, + } + + err = indexExporter.ExportFromIndex(request) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/prune.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/prune.go new file mode 100644 index 0000000000..ec57174bb8 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/prune.go @@ -0,0 +1,132 @@ +package index + +import ( + "fmt" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/cmd/opm/internal/util" + "github.com/operator-framework/operator-registry/pkg/containertools" + "github.com/operator-framework/operator-registry/pkg/lib/indexer" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +func newIndexPruneCmd() *cobra.Command { + indexCmd := &cobra.Command{ + Use: "prune", + Short: "prune an index of all but specified packages", + Long: `prune an index of all but specified packages + +` + sqlite.DeprecationMessage, + + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + + RunE: runIndexPruneCmdFunc, + Args: cobra.NoArgs, + } + + indexCmd.Flags().Bool("debug", false, "enable debug logging") + indexCmd.Flags().Bool("generate", false, "if enabled, just creates the dockerfile and saves it to local disk") + indexCmd.Flags().StringP("out-dockerfile", "d", "", "if generating the dockerfile, this flag is used to (optionally) specify a dockerfile name") + indexCmd.Flags().StringP("from-index", "f", "", "index to prune") + if err := indexCmd.MarkFlagRequired("from-index"); err != nil { + logrus.Panic("Failed to set required `from-index` flag for `index prune`") + } + indexCmd.Flags().StringSliceP("packages", "p", nil, "comma separated list of packages to keep") + if err := indexCmd.MarkFlagRequired("packages"); err != nil { + logrus.Panic("Failed to set required `packages` flag for `index prune`") + } + indexCmd.Flags().StringP("binary-image", "i", "", "container image for on-image `opm` command") + indexCmd.Flags().StringP("container-tool", "c", "podman", "tool to interact with container images (save, build, etc.). One of: [docker, podman]") + indexCmd.Flags().StringP("tag", "t", "", "custom tag for container image being built") + indexCmd.Flags().Bool("permissive", false, "allow registry load errors") + + if err := indexCmd.Flags().MarkHidden("debug"); err != nil { + logrus.Panic(err.Error()) + } + + return indexCmd + +} + +func runIndexPruneCmdFunc(cmd *cobra.Command, _ []string) error { + generate, err := cmd.Flags().GetBool("generate") + if err != nil { + return err + } + + outDockerfile, err := cmd.Flags().GetString("out-dockerfile") + if err != nil { + return err + } + + fromIndex, err := cmd.Flags().GetString("from-index") + if err != nil { + return err + } + + packages, err := cmd.Flags().GetStringSlice("packages") + if err != nil { + return err + } + + binaryImage, err := cmd.Flags().GetString("binary-image") + if err != nil { + return err + } + + containerTool, err := cmd.Flags().GetString("container-tool") + if err != nil { + return err + } + + if containerTool == "none" { + return fmt.Errorf("none is not a valid container-tool for index prune") + } + + tag, err := cmd.Flags().GetString("tag") + if err != nil { + return err + } + + permissive, err := cmd.Flags().GetBool("permissive") + if err != nil { + return err + } + + skipTLSVerify, useHTTP, err := util.GetTLSOptions(cmd) + if err != nil { + return err + } + + logger := logrus.WithFields(logrus.Fields{"packages": packages}) + + logger.Info("pruning the index") + + indexPruner := indexer.NewIndexPruner(containertools.NewContainerTool(containerTool, containertools.PodmanTool), logger) + + request := indexer.PruneFromIndexRequest{ + Generate: generate, + FromIndex: fromIndex, + BinarySourceImage: binaryImage, + OutDockerfile: outDockerfile, + Packages: packages, + Tag: tag, + Permissive: permissive, + SkipTLSVerify: skipTLSVerify, + PlainHTTP: useHTTP, + } + + err = indexPruner.PruneFromIndex(request) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/prunestranded.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/prunestranded.go new file mode 100644 index 0000000000..4ba306919f --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/index/prunestranded.go @@ -0,0 +1,115 @@ +package index + +import ( + "fmt" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/cmd/opm/internal/util" + "github.com/operator-framework/operator-registry/pkg/containertools" + "github.com/operator-framework/operator-registry/pkg/lib/indexer" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +func newIndexPruneStrandedCmd() *cobra.Command { + indexCmd := &cobra.Command{ + Use: "prune-stranded", + Short: "prune an index of stranded bundles", + Long: `prune an index of stranded bundles - bundles that are not associated with a particular package + +` + sqlite.DeprecationMessage, + + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + + RunE: runIndexPruneStrandedCmdFunc, + Args: cobra.NoArgs, + } + + indexCmd.Flags().Bool("debug", false, "enable debug logging") + indexCmd.Flags().Bool("generate", false, "if enabled, just creates the dockerfile and saves it to local disk") + indexCmd.Flags().StringP("out-dockerfile", "d", "", "if generating the dockerfile, this flag is used to (optionally) specify a dockerfile name") + indexCmd.Flags().StringP("from-index", "f", "", "index to prune") + if err := indexCmd.MarkFlagRequired("from-index"); err != nil { + logrus.Panic("Failed to set required `from-index` flag for `index prune-stranded`") + } + indexCmd.Flags().StringP("binary-image", "i", "", "container image for on-image `opm` command") + indexCmd.Flags().StringP("container-tool", "c", "podman", "tool to interact with container images (save, build, etc.). One of: [docker, podman]") + indexCmd.Flags().StringP("tag", "t", "", "custom tag for container image being built") + + if err := indexCmd.Flags().MarkHidden("debug"); err != nil { + logrus.Panic(err.Error()) + } + + return indexCmd + +} + +func runIndexPruneStrandedCmdFunc(cmd *cobra.Command, _ []string) error { + generate, err := cmd.Flags().GetBool("generate") + if err != nil { + return err + } + + outDockerfile, err := cmd.Flags().GetString("out-dockerfile") + if err != nil { + return err + } + + fromIndex, err := cmd.Flags().GetString("from-index") + if err != nil { + return err + } + + binaryImage, err := cmd.Flags().GetString("binary-image") + if err != nil { + return err + } + + containerTool, err := cmd.Flags().GetString("container-tool") + if err != nil { + return err + } + + if containerTool == "none" { + return fmt.Errorf("none is not a valid container-tool for index prune") + } + + tag, err := cmd.Flags().GetString("tag") + if err != nil { + return err + } + + skipTLSVerify, useHTTP, err := util.GetTLSOptions(cmd) + if err != nil { + return err + } + + logger := logrus.WithFields(logrus.Fields{}) + + logger.Info("pruning stranded bundles from the index") + + indexPruner := indexer.NewIndexStrandedPruner(containertools.NewContainerTool(containerTool, containertools.PodmanTool), logger) + + request := indexer.PruneStrandedFromIndexRequest{ + Generate: generate, + FromIndex: fromIndex, + BinarySourceImage: binaryImage, + OutDockerfile: outDockerfile, + Tag: tag, + SkipTLSVerify: skipTLSVerify, + PlainHTTP: useHTTP, + } + + err = indexPruner.PruneStrandedFromIndex(request) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/init/cmd.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/init/cmd.go new file mode 100644 index 0000000000..a4e7050b13 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/init/cmd.go @@ -0,0 +1,77 @@ +package init + +import ( + "io" + "os" + + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/alpha/action" + "github.com/operator-framework/operator-registry/alpha/declcfg" +) + +func NewCmd() *cobra.Command { + var ( + init action.Init + iconFile string + descriptionFile string + output string + ) + cmd := &cobra.Command{ + Use: "init ", + Short: "Generate an olm.package declarative config blob", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + init.Package = args[0] + + var write func(declcfg.DeclarativeConfig, io.Writer) error + switch output { + case "yaml": + write = declcfg.WriteYAML + case "json": + write = declcfg.WriteJSON + default: + log.Fatalf("invalid --output value %q, expected (json|yaml)", output) + } + + if iconFile != "" { + iconReader, err := os.Open(iconFile) + if err != nil { + log.Fatalf("open icon file: %v", err) + } + defer closeReader(iconReader) + init.IconReader = iconReader + } + + if descriptionFile != "" { + descriptionReader, err := os.Open(descriptionFile) + if err != nil { + log.Fatalf("open description file: %v", err) + } + defer closeReader(descriptionReader) + init.DescriptionReader = descriptionReader + } + + pkg, err := init.Run() + if err != nil { + log.Fatal(err) + } + cfg := declcfg.DeclarativeConfig{Packages: []declcfg.Package{*pkg}} + if err := write(cfg, os.Stdout); err != nil { + log.Fatal(err) + } + }, + } + cmd.Flags().StringVarP(&init.DefaultChannel, "default-channel", "c", "", "The channel that subscriptions will default to if unspecified") + cmd.Flags().StringVarP(&iconFile, "icon", "i", "", "Path to package's icon") + cmd.Flags().StringVarP(&descriptionFile, "description", "d", "", "Path to the operator's README.md (or other documentation)") + cmd.Flags().StringVarP(&output, "output", "o", "json", "Output format (json|yaml)") + return cmd +} + +func closeReader(closer io.ReadCloser) { + if err := closer.Close(); err != nil { + log.Warn(err) + } +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/internal/util/util.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/internal/util/util.go new file mode 100644 index 0000000000..a265ba7438 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/internal/util/util.go @@ -0,0 +1,68 @@ +package util + +import ( + "errors" + "os" + + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/pkg/image/containerdregistry" + "github.com/operator-framework/operator-registry/pkg/lib/log" +) + +// GetTLSOptions validates and returns TLS options set by opm flags +func GetTLSOptions(cmd *cobra.Command) (bool, bool, error) { + skipTLS, err := cmd.Flags().GetBool("skip-tls") + if err != nil { + return false, false, err + } + skipTLSVerify, err := cmd.Flags().GetBool("skip-tls-verify") + if err != nil { + return false, false, err + } + useHTTP, err := cmd.Flags().GetBool("use-http") + if err != nil { + return false, false, err + } + + switch { + case cmd.Flags().Changed("skip-tls") && cmd.Flags().Changed("use-http"): + return false, false, errors.New("invalid flag combination: cannot use --use-http with --skip-tls") + case cmd.Flags().Changed("skip-tls") && cmd.Flags().Changed("skip-tls-verify"): + return false, false, errors.New("invalid flag combination: cannot use --skip-tls-verify with --skip-tls") + case skipTLSVerify && useHTTP: + return false, false, errors.New("invalid flag combination: --use-http and --skip-tls-verify cannot both be true") + default: + // return use HTTP true if just skipTLS + // is set for functional parity with existing + if skipTLS { + return false, true, nil + } + return skipTLSVerify, useHTTP, nil + } +} + +// This works in tandem with opm/index/cmd, which adds the relevant flags as persistent +// as part of the root command (cmd/root/cmd) initialization +func CreateCLIRegistry(cmd *cobra.Command) (*containerdregistry.Registry, error) { + skipTlsVerify, useHTTP, err := GetTLSOptions(cmd) + if err != nil { + return nil, err + } + + cacheDir, err := os.MkdirTemp("", "opm-registry-") + if err != nil { + return nil, err + } + + reg, err := containerdregistry.NewRegistry( + containerdregistry.WithCacheDir(cacheDir), + containerdregistry.SkipTLSVerify(skipTlsVerify), + containerdregistry.WithPlainHTTP(useHTTP), + containerdregistry.WithLog(log.Null()), + ) + if err != nil { + return nil, err + } + return reg, nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/main.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/main.go new file mode 100644 index 0000000000..c88f521489 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "os" + + utilerrors "k8s.io/apimachinery/pkg/util/errors" + + "github.com/operator-framework/operator-registry/cmd/opm/root" + registrylib "github.com/operator-framework/operator-registry/pkg/registry" +) + +func main() { + showAlphaHelp := os.Getenv("HELP_ALPHA") == "true" + cmd := root.NewCmd(showAlphaHelp) + if err := cmd.Execute(); err != nil { + agg, ok := err.(utilerrors.Aggregate) + if !ok { + os.Exit(1) + } + for _, e := range agg.Errors() { + if _, ok := e.(registrylib.BundleImageAlreadyAddedErr); ok { + os.Exit(2) + } + if _, ok := e.(registrylib.PackageVersionAlreadyAddedErr); ok { + os.Exit(3) + } + } + os.Exit(1) + } +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/migrate/cmd.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/migrate/cmd.go new file mode 100644 index 0000000000..ca3126da28 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/migrate/cmd.go @@ -0,0 +1,55 @@ +package migrate + +import ( + "log" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/alpha/action" + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +func NewCmd() *cobra.Command { + var ( + migrate action.Migrate + output string + ) + cmd := &cobra.Command{ + Use: "migrate ", + Short: "Migrate a sqlite-based index image or database file to a file-based catalog", + Long: `Migrate a sqlite-based index image or database file to a file-based catalog. + +NOTE: the --output=json format produces streamable, concatenated JSON files. +These are suitable to opm and jq, but may not be supported by arbitrary JSON +parsers that assume that a file contains exactly one valid JSON object. + +` + sqlite.DeprecationMessage, + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + migrate.CatalogRef = args[0] + migrate.OutputDir = args[1] + + switch output { + case "yaml": + migrate.WriteFunc = declcfg.WriteYAML + migrate.FileExt = ".yaml" + case "json": + migrate.WriteFunc = declcfg.WriteJSON + migrate.FileExt = ".json" + default: + log.Fatalf("invalid --output value %q, expected (json|yaml)", output) + } + + logrus.Infof("rendering index %q as file-based catalog", migrate.CatalogRef) + if err := migrate.Run(cmd.Context()); err != nil { + logrus.New().Fatal(err) + } + logrus.Infof("wrote rendered file-based catalog to %q\n", migrate.OutputDir) + return nil + }, + } + cmd.Flags().StringVarP(&output, "output", "o", "json", "Output format (json|yaml)") + return cmd +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/add.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/add.go new file mode 100644 index 0000000000..12e1fa3088 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/add.go @@ -0,0 +1,149 @@ +package registry + +import ( + "errors" + "fmt" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/cmd/opm/internal/util" + "github.com/operator-framework/operator-registry/pkg/containertools" + "github.com/operator-framework/operator-registry/pkg/lib/registry" + reg "github.com/operator-framework/operator-registry/pkg/registry" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +func newRegistryAddCmd(showAlphaHelp bool) *cobra.Command { + rootCmd := &cobra.Command{ + Use: "add", + Short: "add operator bundle to operator registry DB", + Long: `add operator bundle to operator registry DB + +` + sqlite.DeprecationMessage, + + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + + RunE: addFunc, + Args: cobra.NoArgs, + } + + rootCmd.Flags().Bool("debug", false, "enable debug logging") + rootCmd.Flags().StringP("database", "d", "bundles.db", "relative path to database file") + rootCmd.Flags().StringSliceP("bundle-images", "b", []string{}, "comma separated list of links to bundle image") + rootCmd.Flags().Bool("permissive", false, "allow registry load errors") + rootCmd.Flags().Bool("skip-tls", false, "use Plain HTTP for container image registries while pulling bundles") + rootCmd.Flags().Bool("skip-tls-verify", false, "skip TLS certificate verification for container image registries while pulling bundles") + rootCmd.Flags().Bool("use-http", false, "use plain HTTP for container image registries while pulling bundles") + rootCmd.Flags().String("ca-file", "", "the root certificates to use when --container-tool=none; see docker/podman docs for certificate loading instructions") + rootCmd.Flags().StringP("mode", "", "replaces", "graph update mode that defines how channel graphs are updated. One of: [replaces, semver, semver-skippatch]") + rootCmd.Flags().StringP("container-tool", "c", "none", "tool to interact with container images (save, build, etc.). One of: [none, docker, podman]") + rootCmd.Flags().Bool("overwrite-latest", false, "overwrite the latest bundles (channel heads) with those of the same csv name given by --bundles") + if err := rootCmd.Flags().MarkHidden("overwrite-latest"); err != nil { + logrus.Panic(err.Error()) + } + rootCmd.Flags().Bool("enable-alpha", false, "enable unsupported alpha features of the OPM CLI") + if !showAlphaHelp { + if err := rootCmd.Flags().MarkHidden("enable-alpha"); err != nil { + logrus.Panic(err.Error()) + } + } + if err := rootCmd.Flags().MarkDeprecated("skip-tls", "use --use-http and --skip-tls-verify instead"); err != nil { + logrus.Panic(err.Error()) + } + return rootCmd +} + +func addFunc(cmd *cobra.Command, _ []string) error { + permissive, err := cmd.Flags().GetBool("permissive") + if err != nil { + return err + } + caFile, err := cmd.Flags().GetString("ca-file") + if err != nil { + return err + } + fromFilename, err := cmd.Flags().GetString("database") + if err != nil { + return err + } + bundleImages, err := cmd.Flags().GetStringSlice("bundle-images") + if err != nil { + return err + } + containerToolStr, err := cmd.Flags().GetString("container-tool") + if err != nil { + return err + } + containerTool := containertools.NewContainerTool(containerToolStr, containertools.NoneTool) + mode, err := cmd.Flags().GetString("mode") + if err != nil { + return err + } + modeEnum, err := reg.GetModeFromString(mode) + if err != nil { + return err + } + overwrite, err := cmd.Flags().GetBool("overwrite-latest") + if err != nil { + return err + } + + enableAlpha, err := cmd.Flags().GetBool("enable-alpha") + if err != nil { + return err + } + + skipTLSVerify, useHTTP, err := util.GetTLSOptions(cmd) + if err != nil { + return err + } + + if caFile != "" { + if skipTLSVerify { + return errors.New("--skip-tls-verify must be false when --ca-file is set") + } + if containerTool != containertools.NoneTool { + return fmt.Errorf("--ca-file cannot be set with --container-tool=%[1]s; "+ + "certificates must be configured specifically for %[1]s", containerTool) + } + } + + request := registry.AddToRegistryRequest{ + Permissive: permissive, + SkipTLSVerify: skipTLSVerify, + PlainHTTP: useHTTP, + CaFile: caFile, + InputDatabase: fromFilename, + Bundles: bundleImages, + Mode: modeEnum, + ContainerTool: containerTool, + Overwrite: overwrite, + EnableAlpha: enableAlpha, + } + + logger := logrus.WithFields(logrus.Fields{"bundles": bundleImages}) + + if skipTLSVerify { + logger.Warn("--skip-tls-verify flag is set: this mode is insecure and meant for development purposes only.") + } + + if useHTTP { + logger.Warn("--use-http flag is set: this mode is insecure and meant for development purposes only.") + } + + logger.Info("adding to the registry") + + registryAdder := registry.NewRegistryAdder(logger) + + err = registryAdder.AddToRegistry(request) + if err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/cmd.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/cmd.go new file mode 100644 index 0000000000..dde29cf0ad --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/cmd.go @@ -0,0 +1,38 @@ +package registry + +import ( + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +// NewOpmRegistryCmd returns the appregistry-server command +func NewOpmRegistryCmd(showAlphaHelp bool) *cobra.Command { + rootCmd := &cobra.Command{ + Use: "registry", + Short: "interact with operator-registry database", + Long: `interact with operator-registry database building, modifying and/or serving the operator-registry database + +` + sqlite.DeprecationMessage, + PersistentPreRun: func(_ *cobra.Command, _ []string) { + sqlite.LogSqliteDeprecation() + }, + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + Args: cobra.NoArgs, + } + + rootCmd.AddCommand(newRegistryServeCmd()) + rootCmd.AddCommand(newRegistryAddCmd(showAlphaHelp)) + rootCmd.AddCommand(newRegistryRmCmd()) + rootCmd.AddCommand(newRegistryPruneCmd()) + rootCmd.AddCommand(newRegistryPruneStrandedCmd()) + rootCmd.AddCommand(newRegistryDeprecateCmd()) + + return rootCmd +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/deprecatetruncate.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/deprecatetruncate.go new file mode 100644 index 0000000000..65eb66278c --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/deprecatetruncate.go @@ -0,0 +1,76 @@ +package registry + +import ( + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/pkg/lib/registry" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +func newRegistryDeprecateCmd() *cobra.Command { + cmd := &cobra.Command{ + Hidden: true, + Use: "deprecatetruncate", + Short: "deprecate operator bundle from registry DB", + Long: `deprecate operator bundle from registry DB + +` + sqlite.DeprecationMessage, + + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + + RunE: deprecateFunc, + Args: cobra.NoArgs, + } + + cmd.Flags().Bool("debug", false, "enable debug logging") + cmd.Flags().StringP("database", "d", "index.db", "relative path to database file") + cmd.Flags().StringSliceP("bundle-images", "b", []string{}, "comma separated list of links to bundle image") + cmd.Flags().Bool("permissive", false, "allow registry load errors") + cmd.Flags().Bool("allow-package-removal", false, "removes the entire package if the heads of all channels in the package are deprecated") + + return cmd +} + +func deprecateFunc(cmd *cobra.Command, _ []string) error { + permissive, err := cmd.Flags().GetBool("permissive") + if err != nil { + return err + } + fromFilename, err := cmd.Flags().GetString("database") + if err != nil { + return err + } + bundleImages, err := cmd.Flags().GetStringSlice("bundle-images") + if err != nil { + return err + } + allowPackageRemoval, err := cmd.Flags().GetBool("allow-package-removal") + if err != nil { + return err + } + + request := registry.DeprecateFromRegistryRequest{ + Permissive: permissive, + InputDatabase: fromFilename, + Bundles: bundleImages, + AllowPackageRemoval: allowPackageRemoval, + } + + logger := logrus.WithFields(logrus.Fields{"bundles": bundleImages}) + + logger.Info("deprecating from registry") + + registryDeprecator := registry.NewRegistryDeprecator(logger) + + err = registryDeprecator.DeprecateFromRegistry(request) + if err != nil { + logger.Fatal(err) + } + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/mirror.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/mirror.go new file mode 100644 index 0000000000..5beae77925 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/mirror.go @@ -0,0 +1,51 @@ +package registry + +import ( + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/pkg/mirror" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +func MirrorCmd() *cobra.Command { + // TODO(joelanford): MirrorCmd is unused. Delete it and any other code used only by it. + o := mirror.DefaultImageIndexMirrorerOptions() + cmd := &cobra.Command{ + Hidden: true, + Use: "mirror [src image] [dest image]", + Short: "mirror an operator-registry catalog", + Long: `mirror an operator-registry catalog image from one registry to another + +` + sqlite.DeprecationMessage, + + PreRunE: func(cmd *cobra.Command, args []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + + RunE: func(cmd *cobra.Command, args []string) error { + src := args[0] + dest := args[1] + + mirrorer, err := mirror.NewIndexImageMirror(o.ToOption(), mirror.WithSource(src), mirror.WithDest(dest)) + if err != nil { + return err + } + _, err = mirrorer.Mirror() + if err != nil { + return err + } + return nil + }, + Args: cobra.ExactArgs(2), + } + flags := cmd.Flags() + + cmd.Flags().Bool("debug", false, "Enable debug logging.") + flags.StringVar(&o.ManifestDir, "--to-manifests", "manifests", "Local path to store manifests.") + + return cmd +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/prune.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/prune.go new file mode 100644 index 0000000000..0160e6bd20 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/prune.go @@ -0,0 +1,73 @@ +package registry + +import ( + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/pkg/lib/registry" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +func newRegistryPruneCmd() *cobra.Command { + rootCmd := &cobra.Command{ + Use: "prune", + Short: "prune an operator registry DB of all but specified packages", + Long: `prune an operator registry DB of all but specified packages + +` + sqlite.DeprecationMessage, + + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + + RunE: runRegistryPruneCmdFunc, + Args: cobra.NoArgs, + } + + rootCmd.Flags().Bool("debug", false, "enable debug logging") + rootCmd.Flags().StringP("database", "d", "bundles.db", "relative path to database file") + rootCmd.Flags().StringSliceP("packages", "p", []string{}, "comma separated list of package names to be kept") + if err := rootCmd.MarkFlagRequired("packages"); err != nil { + logrus.Panic("Failed to set required `packages` flag for `registry rm`") + } + rootCmd.Flags().Bool("permissive", false, "allow registry load errors") + + return rootCmd +} + +func runRegistryPruneCmdFunc(cmd *cobra.Command, _ []string) error { + fromFilename, err := cmd.Flags().GetString("database") + if err != nil { + return err + } + packages, err := cmd.Flags().GetStringSlice("packages") + if err != nil { + return err + } + permissive, err := cmd.Flags().GetBool("permissive") + if err != nil { + return err + } + + request := registry.PruneFromRegistryRequest{ + Packages: packages, + InputDatabase: fromFilename, + Permissive: permissive, + } + + logger := logrus.WithFields(logrus.Fields{"packages": packages}) + + logger.Info("pruning from the registry") + + registryPruner := registry.NewRegistryPruner(logger) + + err = registryPruner.PruneFromRegistry(request) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/prunestranded.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/prunestranded.go new file mode 100644 index 0000000000..800272a2f2 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/prunestranded.go @@ -0,0 +1,58 @@ +package registry + +import ( + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/pkg/lib/registry" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +func newRegistryPruneStrandedCmd() *cobra.Command { + rootCmd := &cobra.Command{ + Use: "prune-stranded", + Short: "prune an operator registry DB of stranded bundles", + Long: `prune an operator registry DB of stranded bundles - bundles that are not associated with a particular package + +` + sqlite.DeprecationMessage, + + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + + RunE: runRegistryPruneStrandedCmdFunc, + Args: cobra.NoArgs, + } + + rootCmd.Flags().Bool("debug", false, "enable debug logging") + rootCmd.Flags().StringP("database", "d", "bundles.db", "relative path to database file") + + return rootCmd +} + +func runRegistryPruneStrandedCmdFunc(cmd *cobra.Command, _ []string) error { + fromFilename, err := cmd.Flags().GetString("database") + if err != nil { + return err + } + + request := registry.PruneStrandedFromRegistryRequest{ + InputDatabase: fromFilename, + } + + logger := logrus.WithFields(logrus.Fields{}) + + logger.Info("pruning from the registry") + + registryStrandedPruner := registry.NewRegistryStrandedPruner(logger) + + err = registryStrandedPruner.PruneStrandedFromRegistry(request) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/rm.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/rm.go new file mode 100644 index 0000000000..ba884ca8d9 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/rm.go @@ -0,0 +1,73 @@ +package registry + +import ( + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/pkg/lib/registry" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +func newRegistryRmCmd() *cobra.Command { + rootCmd := &cobra.Command{ + Use: "rm", + Short: "remove operator from operator registry DB", + Long: `Remove operator from operator registry DB + +` + sqlite.DeprecationMessage, + + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + + RunE: rmFunc, + Args: cobra.NoArgs, + } + + rootCmd.Flags().Bool("debug", false, "enable debug logging") + rootCmd.Flags().StringP("database", "d", "bundles.db", "relative path to database file") + rootCmd.Flags().StringSliceP("packages", "o", nil, "comma separated list of package names to be deleted") + if err := rootCmd.MarkFlagRequired("packages"); err != nil { + logrus.Panic("Failed to set required `packages` flag for `registry rm`") + } + rootCmd.Flags().Bool("permissive", false, "allow registry load errors") + + return rootCmd +} + +func rmFunc(cmd *cobra.Command, _ []string) error { + fromFilename, err := cmd.Flags().GetString("database") + if err != nil { + return err + } + packages, err := cmd.Flags().GetStringSlice("packages") + if err != nil { + return err + } + permissive, err := cmd.Flags().GetBool("permissive") + if err != nil { + return err + } + + request := registry.DeleteFromRegistryRequest{ + Packages: packages, + InputDatabase: fromFilename, + Permissive: permissive, + } + + logger := logrus.WithFields(logrus.Fields{"packages": packages}) + + logger.Info("removing from the registry") + + registryDeleter := registry.NewRegistryDeleter(logger) + + err = registryDeleter.DeleteFromRegistry(request) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/serve.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/serve.go new file mode 100644 index 0000000000..fcaf67e6f2 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/registry/serve.go @@ -0,0 +1,171 @@ +package registry + +import ( + "context" + "database/sql" + "fmt" + "net" + "os" + "strconv" + "time" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "google.golang.org/grpc" + health "google.golang.org/grpc/health/grpc_health_v1" + "google.golang.org/grpc/reflection" + + "github.com/operator-framework/operator-registry/pkg/api" + "github.com/operator-framework/operator-registry/pkg/lib/dns" + "github.com/operator-framework/operator-registry/pkg/lib/graceful" + "github.com/operator-framework/operator-registry/pkg/lib/log" + "github.com/operator-framework/operator-registry/pkg/lib/tmp" + "github.com/operator-framework/operator-registry/pkg/server" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +func newRegistryServeCmd() *cobra.Command { + rootCmd := &cobra.Command{ + Use: "serve", + Short: "serve an operator-registry database", + Long: `serve an operator-registry database that is queriable using grpc + +` + sqlite.DeprecationMessage, + + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + + RunE: serveFunc, + Args: cobra.NoArgs, + } + + rootCmd.Flags().Bool("debug", false, "enable debug logging") + rootCmd.Flags().StringP("database", "d", "bundles.db", "relative path to sqlite db") + rootCmd.Flags().StringP("port", "p", "50051", "port number to serve on") + rootCmd.Flags().StringP("termination-log", "t", "/dev/termination-log", "path to a container termination log file") + rootCmd.Flags().Bool("skip-migrate", false, "do not attempt to migrate to the latest db revision when starting") + rootCmd.Flags().String("timeout-seconds", "infinite", "Timeout in seconds. This flag will be removed later.") + + return rootCmd +} + +func serveFunc(cmd *cobra.Command, _ []string) error { + // Immediately set up termination log + terminationLogPath, err := cmd.Flags().GetString("termination-log") + if err != nil { + return err + } + err = log.AddDefaultWriterHooks(terminationLogPath) + if err != nil { + logrus.WithError(err).Warn("unable to set termination log path") + } + + // Ensure there is a default nsswitch config + if err := dns.EnsureNsswitch(); err != nil { + logrus.WithError(err).Warn("unable to write default nsswitch config") + } + + dbName, err := cmd.Flags().GetString("database") + if err != nil { + return err + } + + port, err := cmd.Flags().GetString("port") + if err != nil { + return err + } + + logger := logrus.WithFields(logrus.Fields{"database": dbName, "port": port}) + + // make a writable copy of the db for migrations + tmpdb, err := tmp.CopyTmpDB(dbName) + if err != nil { + return err + } + defer os.Remove(tmpdb) + + db, err := sqlite.Open(tmpdb) + if err != nil { + return err + } + + if _, err := db.ExecContext(context.TODO(), `PRAGMA soft_heap_limit=1`); err != nil { + logger.WithError(err).Warnf("error setting soft heap limit for sqlite") + } + + // migrate to the latest version + if err := migrate(cmd, db); err != nil { + logger.WithError(err).Warnf("couldn't migrate db") + } + + store := sqlite.NewSQLLiteQuerierFromDb(db, sqlite.OmitManifests(true)) + + // sanity check that the db is available + tables, err := store.ListTables(context.TODO()) + if err != nil { + logger.WithError(err).Warnf("couldn't list tables in db") + } + if len(tables) == 0 { + logger.Warn("no tables found in db") + } + + lis, err := net.Listen("tcp", ":"+port) + if err != nil { + return fmt.Errorf("failed to listen: %s", err) + } + + timeout, err := cmd.Flags().GetString("timeout-seconds") + if err != nil { + return err + } + + s := grpc.NewServer() + logger.Printf("Keeping server open for %s seconds", timeout) + if timeout != "infinite" { + timeoutSeconds, err := strconv.ParseUint(timeout, 10, 16) + if err != nil { + return err + } + + timeoutDuration := time.Duration(timeoutSeconds) * time.Second + timer := time.AfterFunc(timeoutDuration, func() { + logger.Info("Timeout expired. Gracefully stopping.") + s.GracefulStop() + }) + defer timer.Stop() + } + + api.RegisterRegistryServer(s, server.NewRegistryServer(store)) + health.RegisterHealthServer(s, server.NewHealthServer()) + reflection.Register(s) + logger.Info("serving registry") + return graceful.Shutdown(logger, func() error { + return s.Serve(lis) + }, func() { + s.GracefulStop() + }) +} + +func migrate(cmd *cobra.Command, db *sql.DB) error { + shouldSkipMigrate, err := cmd.Flags().GetBool("skip-migrate") + if err != nil { + return err + } + if shouldSkipMigrate { + return nil + } + + migrator, err := sqlite.NewSQLLiteMigrator(db) + if err != nil { + return err + } + if migrator == nil { + return fmt.Errorf("failed to load migrator") + } + + return migrator.Migrate(context.TODO()) +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/render/cmd.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/render/cmd.go new file mode 100644 index 0000000000..4cdd5e5840 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/render/cmd.go @@ -0,0 +1,96 @@ +package render + +import ( + "io" + "log" + "os" + "text/template" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/alpha/action" + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/cmd/opm/internal/util" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +func NewCmd(showAlphaHelp bool) *cobra.Command { + var ( + render action.Render + output string + imageRefTemplate string + ) + cmd := &cobra.Command{ + Use: "render [catalog-image | catalog-directory | bundle-image | bundle-directory | sqlite-file]...", + Short: "Generate a stream of file-based catalog objects from catalogs and bundles", + Long: `Generate a stream of file-based catalog objects to stdout from the provided +catalog images, file-based catalog directories, bundle images, and sqlite +database files. +`, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + render.Refs = args + + var write func(declcfg.DeclarativeConfig, io.Writer) error + switch output { + case "yaml": + write = declcfg.WriteYAML + case "json": + write = declcfg.WriteJSON + default: + log.Fatalf("invalid --output value %q, expected (json|yaml)", output) + } + + // The bundle loading impl is somewhat verbose, even on the happy path, + // so discard all logrus default logger logs. Any important failures will be + // returned from render.Run and logged as fatal errors. + logrus.SetOutput(io.Discard) + + reg, err := util.CreateCLIRegistry(cmd) + if err != nil { + log.Fatal(err) + } + defer reg.Destroy() + + render.Registry = reg + + if imageRefTemplate != "" { + tmpl, err := template.New("image-ref-template").Parse(imageRefTemplate) + if err != nil { + log.Fatalf("invalid image reference template: %v", err) + } + render.ImageRefTemplate = tmpl + } + + cfg, err := render.Run(cmd.Context()) + if err != nil { + log.Fatal(err) + } + + if err := write(*cfg, os.Stdout); err != nil { + log.Fatal(err) + } + }, + } + cmd.Flags().StringVarP(&output, "output", "o", "json", "Output format of the streamed file-based catalog objects (json|yaml)") + cmd.Flags().BoolVar(&render.Migrate, "migrate", false, "Perform migrations on the rendered FBC") + + // Alpha flags + cmd.Flags().StringVar(&imageRefTemplate, "alpha-image-ref-template", "", "When bundle image reference information is unavailable, populate it with this template") + + if showAlphaHelp { + cmd.Long += ` +If rendering sources that do not carry bundle image reference information +(e.g. bundle directories), the --alpha-image-ref-template flag can be used to +generate image references for the rendered file-based catalog objects. +This is useful when generating a catalog with image references prior to +those images actually existing. Available template variables are: + - {{.Package}} : the package name the bundle belongs to + - {{.Name}} : the name of the bundle (for registry+v1 bundles, this is the CSV name) + - {{.Version}} : the version of the bundle +` + } + cmd.Long += "\n" + sqlite.DeprecationMessage + return cmd +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/root/cmd.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/root/cmd.go new file mode 100644 index 0000000000..d23657aee9 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/root/cmd.go @@ -0,0 +1,74 @@ +package root + +import ( + "fmt" + "strings" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + + "github.com/operator-framework/operator-registry/cmd/opm/alpha" + "github.com/operator-framework/operator-registry/cmd/opm/generate" + "github.com/operator-framework/operator-registry/cmd/opm/index" + initcmd "github.com/operator-framework/operator-registry/cmd/opm/init" + "github.com/operator-framework/operator-registry/cmd/opm/migrate" + "github.com/operator-framework/operator-registry/cmd/opm/registry" + "github.com/operator-framework/operator-registry/cmd/opm/render" + "github.com/operator-framework/operator-registry/cmd/opm/serve" + "github.com/operator-framework/operator-registry/cmd/opm/validate" + "github.com/operator-framework/operator-registry/cmd/opm/version" +) + +func NewCmd(showAlphaHelp bool) *cobra.Command { + cmd := &cobra.Command{ + Use: "opm", + Short: "operator package manager", + Long: `CLI to interact with operator-registry and build indexes of operator content. + +To view help related to alpha features, set HELP_ALPHA=true in the environment.`, + PreRunE: func(cmd *cobra.Command, _ []string) error { + if debug, _ := cmd.Flags().GetBool("debug"); debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + }, + Args: cobra.NoArgs, + Run: func(_ *cobra.Command, _ []string) {}, // adding an empty function here to preserve non-zero exit status for misstated subcommands/flags for the command hierarchy + } + + cmd.PersistentFlags().Bool("skip-tls", false, "skip TLS certificate verification for container image registries while pulling bundles or index") + cmd.PersistentFlags().Bool("skip-tls-verify", false, "skip TLS certificate verification for container image registries while pulling bundles") + cmd.PersistentFlags().Bool("use-http", false, "use plain HTTP for container image registries while pulling bundles") + if err := cmd.PersistentFlags().MarkDeprecated("skip-tls", "use --use-http and --skip-tls-verify instead"); err != nil { + logrus.Panic(err.Error()) + } + + cmd.AddCommand(registry.NewOpmRegistryCmd(showAlphaHelp), alpha.NewCmd(showAlphaHelp), initcmd.NewCmd(), migrate.NewCmd(), serve.NewCmd(), render.NewCmd(showAlphaHelp), validate.NewCmd(), generate.NewCmd()) + index.AddCommand(cmd, showAlphaHelp) + version.AddCommand(cmd) + + cmd.Flags().Bool("debug", false, "enable debug logging") + if err := cmd.Flags().MarkHidden("debug"); err != nil { + logrus.Panic(err.Error()) + } + + // Mark all alpha flags as hidden and prepend their usage with an alpha warning + configureAlphaFlags(cmd, !showAlphaHelp) + + return cmd +} + +func configureAlphaFlags(cmd *cobra.Command, hideFlags bool) { + cmd.Flags().VisitAll(func(f *pflag.Flag) { + if strings.HasPrefix(f.Name, "alpha-") { + if hideFlags { + f.Hidden = true + } + f.Usage = fmt.Sprintf("(ALPHA: This flag will be removed or renamed in a future release, potentially without notice) %s", f.Usage) + } + }) + for _, subCmd := range cmd.Commands() { + configureAlphaFlags(subCmd, hideFlags) + } +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/serve/serve.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/serve/serve.go new file mode 100644 index 0000000000..234ea1a48b --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/serve/serve.go @@ -0,0 +1,295 @@ +package serve + +import ( + "bytes" + "context" + "errors" + "fmt" + "net" + "net/http" + endpoint "net/http/pprof" + "os" + "runtime/pprof" + "sync" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "google.golang.org/grpc" + health "google.golang.org/grpc/health/grpc_health_v1" + "google.golang.org/grpc/reflection" + + "github.com/operator-framework/operator-registry/pkg/api" + "github.com/operator-framework/operator-registry/pkg/cache" + "github.com/operator-framework/operator-registry/pkg/lib/dns" + "github.com/operator-framework/operator-registry/pkg/lib/graceful" + "github.com/operator-framework/operator-registry/pkg/lib/log" + "github.com/operator-framework/operator-registry/pkg/server" +) + +type serve struct { + configDir string + cacheDir string + cacheOnly bool + cacheEnforceIntegrity bool + + port string + terminationLog string + + debug bool + pprofAddr string + captureProfiles bool + + logger *logrus.Entry +} + +const ( + defaultCpuStartupPath string = "/debug/pprof/startup/cpu" +) + +func NewCmd() *cobra.Command { + logger := logrus.New() + s := serve{ + logger: logrus.NewEntry(logger), + } + cmd := &cobra.Command{ + Use: "serve ", + Short: "serve declarative configs", + Long: `This command serves declarative configs via a GRPC server. + +NOTE: The declarative config directory is loaded by the serve command at +startup. Changes made to the declarative config after the this command starts +will not be reflected in the served content. +`, + Args: cobra.ExactArgs(1), + PreRun: func(_ *cobra.Command, args []string) { + s.configDir = args[0] + if s.debug { + logger.SetLevel(logrus.DebugLevel) + } + }, + Run: func(cmd *cobra.Command, _ []string) { + if !cmd.Flags().Changed("cache-enforce-integrity") { + s.cacheEnforceIntegrity = s.cacheDir != "" && !s.cacheOnly + } + if err := s.run(cmd.Context()); err != nil { + logger.Fatal(err) + } + }, + } + + cmd.Flags().BoolVar(&s.debug, "debug", false, "enable debug logging") + cmd.Flags().StringVarP(&s.terminationLog, "termination-log", "t", "/dev/termination-log", "path to a container termination log file") + cmd.Flags().StringVarP(&s.port, "port", "p", "50051", "port number to serve on") + cmd.Flags().StringVar(&s.pprofAddr, "pprof-addr", "localhost:6060", "address of startup profiling endpoint (addr:port format)") + cmd.Flags().BoolVar(&s.captureProfiles, "pprof-capture-profiles", false, "capture pprof CPU profiles") + cmd.Flags().StringVar(&s.cacheDir, "cache-dir", "", "if set, sync and persist server cache directory") + cmd.Flags().BoolVar(&s.cacheOnly, "cache-only", false, "sync the serve cache and exit without serving") + cmd.Flags().BoolVar(&s.cacheEnforceIntegrity, "cache-enforce-integrity", false, "exit with error if cache is not present or has been invalidated. (default: true when --cache-dir is set and --cache-only is false, false otherwise), ") + return cmd +} + +func (s *serve) run(ctx context.Context) error { + p := newProfilerInterface(s.pprofAddr, s.logger) + if err := p.startEndpoint(); err != nil { + return fmt.Errorf("could not start pprof endpoint: %v", err) + } + if s.captureProfiles { + if err := p.startCpuProfileCache(); err != nil { + return fmt.Errorf("could not start CPU profile: %v", err) + } + } + + // Immediately set up termination log + err := log.AddDefaultWriterHooks(s.terminationLog) + if err != nil { + s.logger.WithError(err).Warn("unable to set termination log path") + } + + // Ensure there is a default nsswitch config + if err := dns.EnsureNsswitch(); err != nil { + s.logger.WithError(err).Warn("unable to write default nsswitch config") + } + + if s.cacheDir == "" && s.cacheEnforceIntegrity { + return fmt.Errorf("--cache-dir must be specified with --cache-enforce-integrity") + } + + if s.cacheDir == "" { + s.cacheDir, err = os.MkdirTemp("", "opm-serve-cache-") + if err != nil { + return err + } + defer os.RemoveAll(s.cacheDir) + } + s.logger = s.logger.WithFields(logrus.Fields{ + "configs": s.configDir, + "cache": s.cacheDir, + }) + + store, err := cache.New(s.cacheDir, cache.WithLog(s.logger)) + if err != nil { + return err + } + defer store.Close() + if s.cacheEnforceIntegrity { + if err := store.CheckIntegrity(ctx, os.DirFS(s.configDir)); err != nil { + return fmt.Errorf("integrity check failed: %v", err) + } + if err := store.Load(ctx); err != nil { + return fmt.Errorf("failed to load cache: %v", err) + } + } else { + if err := cache.LoadOrRebuild(ctx, store, os.DirFS(s.configDir)); err != nil { + return fmt.Errorf("failed to load or rebuild cache: %v", err) + } + } + + if s.cacheOnly { + return nil + } + + s.logger = s.logger.WithFields(logrus.Fields{"port": s.port}) + + lis, err := net.Listen("tcp", ":"+s.port) + if err != nil { + return fmt.Errorf("failed to listen: %s", err) + } + + grpcServer := grpc.NewServer() + api.RegisterRegistryServer(grpcServer, server.NewRegistryServer(store)) + health.RegisterHealthServer(grpcServer, server.NewHealthServer()) + reflection.Register(grpcServer) + s.logger.Info("serving registry") + p.stopCpuProfileCache() + + return graceful.Shutdown(s.logger, func() error { + return grpcServer.Serve(lis) + }, func() { + grpcServer.GracefulStop() + if err := p.stopEndpoint(ctx); err != nil { + s.logger.Warnf("error shutting down pprof server: %v", err) + } + }) + +} + +// manages an HTTP pprof endpoint served by `server`, +// including default pprof handlers and custom cpu pprof cache stored in `cache`. +// the cache is intended to sample CPU activity for a period and serve the data +// via a custom pprof path once collection is complete (e.g. over process initialization) +type profilerInterface struct { + addr string + cache bytes.Buffer + + server http.Server + + cacheReady bool + cacheLock sync.RWMutex + + logger *logrus.Entry + closeErr chan error +} + +func newProfilerInterface(a string, log *logrus.Entry) *profilerInterface { + return &profilerInterface{ + addr: a, + logger: log.WithFields(logrus.Fields{"address": a}), + cache: bytes.Buffer{}, + } +} + +func (p *profilerInterface) isEnabled() bool { + return p.addr != "" +} + +func (p *profilerInterface) startEndpoint() error { + // short-circuit if not enabled + if !p.isEnabled() { + return nil + } + + mux := http.NewServeMux() + mux.HandleFunc("/debug/pprof/", endpoint.Index) + mux.HandleFunc("/debug/pprof/cmdline", endpoint.Cmdline) + mux.HandleFunc("/debug/pprof/profile", endpoint.Profile) + mux.HandleFunc("/debug/pprof/symbol", endpoint.Symbol) + mux.HandleFunc("/debug/pprof/trace", endpoint.Trace) + mux.HandleFunc(defaultCpuStartupPath, p.httpHandler) + + p.server = http.Server{ + Addr: p.addr, + Handler: mux, + } + + lis, err := net.Listen("tcp", p.addr) + if err != nil { + return err + } + + p.closeErr = make(chan error) + go func() { + p.closeErr <- func() error { + p.logger.Info("starting pprof endpoint") + if err := p.server.Serve(lis); err != nil && !errors.Is(err, http.ErrServerClosed) { + return err + } + return nil + }() + }() + return nil +} + +func (p *profilerInterface) startCpuProfileCache() error { + // short-circuit if not enabled + if !p.isEnabled() { + return nil + } + + p.logger.Infof("start caching cpu profile data at %q", defaultCpuStartupPath) + if err := pprof.StartCPUProfile(&p.cache); err != nil { + return err + } + + return nil +} + +func (p *profilerInterface) stopCpuProfileCache() { + // short-circuit if not enabled + if !p.isEnabled() { + return + } + pprof.StopCPUProfile() + p.setCacheReady() + p.logger.Info("stopped caching cpu profile data") +} + +func (p *profilerInterface) httpHandler(w http.ResponseWriter, r *http.Request) { + if !p.isCacheReady() { + http.Error(w, "cpu profile cache is not yet ready", http.StatusServiceUnavailable) + } + w.Write(p.cache.Bytes()) +} + +func (p *profilerInterface) stopEndpoint(ctx context.Context) error { + if !p.isEnabled() { + return nil + } + if err := p.server.Shutdown(ctx); err != nil { + return err + } + return <-p.closeErr +} + +func (p *profilerInterface) isCacheReady() bool { + p.cacheLock.RLock() + isReady := p.cacheReady + p.cacheLock.RUnlock() + + return isReady +} + +func (p *profilerInterface) setCacheReady() { + p.cacheLock.Lock() + p.cacheReady = true + p.cacheLock.Unlock() +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/validate/validate.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/validate/validate.go new file mode 100644 index 0000000000..4579f5e120 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/validate/validate.go @@ -0,0 +1,38 @@ +package validate + +import ( + "fmt" + "os" + + "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "github.com/operator-framework/operator-registry/pkg/lib/config" +) + +func NewCmd() *cobra.Command { + logger := logrus.New() + validate := &cobra.Command{ + Use: "validate ", + Short: "Validate the declarative index config", + Long: "Validate the declarative config JSON file(s) in a given directory", + Args: cobra.ExactArgs(1), + RunE: func(c *cobra.Command, args []string) error { + directory := args[0] + s, err := os.Stat(directory) + if err != nil { + return err + } + if !s.IsDir() { + return fmt.Errorf("%q is not a directory", directory) + } + + if err := config.Validate(c.Context(), os.DirFS(directory)); err != nil { + logger.Fatal(err) + } + return nil + }, + } + + return validate +} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/version/version.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/version/version.go new file mode 100644 index 0000000000..8d91ba46f8 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/version/version.go @@ -0,0 +1,56 @@ +package version + +import ( + "fmt" + "runtime" + + "github.com/spf13/cobra" +) + +var ( + // opmVersion is the constant representing the version of the opm binary + opmVersion = "unknown" + // gitCommit is a constant representing the source version that + // generated this build. It should be set during build via -ldflags. + gitCommit string + // buildDate in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ') + buildDate string +) + +type Version struct { + OpmVersion string `json:"opmVersion"` + GitCommit string `json:"gitCommit"` + BuildDate string `json:"buildDate"` + GoOs string `json:"goOs"` + GoArch string `json:"goArch"` +} + +func getVersion() Version { + return Version{ + OpmVersion: opmVersion, + GitCommit: gitCommit, + BuildDate: buildDate, + GoOs: runtime.GOOS, + GoArch: runtime.GOARCH, + } +} + +func (v Version) Print() { + fmt.Printf("Version: %#v\n", v) +} + +func AddCommand(parent *cobra.Command) { + cmd := &cobra.Command{ + Use: "version", + Short: "Print the opm version", + Long: `Print the opm version`, + Example: `kubebuilder version`, + Run: runVersion, + } + + parent.AddCommand(cmd) +} + +func runVersion(_ *cobra.Command, _ []string) { + getVersion().Print() +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/cache/bundle_key.go b/vendor/github.com/operator-framework/operator-registry/pkg/cache/bundle_key.go new file mode 100644 index 0000000000..dba87c2668 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/cache/bundle_key.go @@ -0,0 +1,47 @@ +package cache + +import ( + "github.com/tidwall/btree" +) + +type bundleKey struct { + PackageName string + ChannelName string + Name string +} + +func bundleKeyComparator(a, b bundleKey) bool { + if a.ChannelName != b.ChannelName { + return a.ChannelName < b.ChannelName + } + if a.PackageName != b.PackageName { + return a.PackageName < b.PackageName + } + return a.Name < b.Name +} + +type bundleKeys struct { + t *btree.BTreeG[bundleKey] +} + +func newBundleKeys() bundleKeys { + return bundleKeys{btree.NewBTreeG[bundleKey](bundleKeyComparator)} +} + +func (b bundleKeys) Set(k bundleKey) { + b.t.Set(k) +} + +func (b bundleKeys) Len() int { + return b.t.Len() +} + +func (b bundleKeys) Walk(f func(k bundleKey) error) error { + it := b.t.Iter() + for it.Next() { + if err := f(it.Item()); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/cache/cache.go b/vendor/github.com/operator-framework/operator-registry/pkg/cache/cache.go new file mode 100644 index 0000000000..7ea1f3fd59 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/cache/cache.go @@ -0,0 +1,431 @@ +package cache + +import ( + "context" + "errors" + "fmt" + "io" + "io/fs" + "os" + "path/filepath" + "runtime" + "strings" + "sync" + + "github.com/sirupsen/logrus" + "golang.org/x/sync/errgroup" + + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/pkg/api" + "github.com/operator-framework/operator-registry/pkg/lib/log" + "github.com/operator-framework/operator-registry/pkg/registry" +) + +type Cache interface { + registry.GRPCQuery + + CheckIntegrity(ctx context.Context, fbc fs.FS) error + Build(ctx context.Context, fbc fs.FS) error + Load(ctc context.Context) error + Close() error +} + +type backend interface { + Name() string + IsCachePresent() bool + + Init() error + Open() error + Close() error + + GetPackageIndex(context.Context) (packageIndex, error) + PutPackageIndex(context.Context, packageIndex) error + + SendBundles(context.Context, registry.BundleSender) error + GetBundle(context.Context, bundleKey) (*api.Bundle, error) + PutBundle(context.Context, bundleKey, *api.Bundle) error + + GetDigest(context.Context) (string, error) + ComputeDigest(context.Context, fs.FS) (string, error) + PutDigest(context.Context, string) error +} + +type CacheOptions struct { + Log *logrus.Entry +} + +func WithLog(log *logrus.Entry) CacheOption { + return func(o *CacheOptions) { + o.Log = log + } +} + +type CacheOption func(*CacheOptions) + +// New creates a new Cache. It chooses a cache implementation based +// on the files it finds in the cache directory, with a preference for the +// latest iteration of the cache implementation. If the cache directory +// is non-empty and a supported cache format is not found, an error is returned. +func New(cacheDir string, cacheOpts ...CacheOption) (Cache, error) { + opts := &CacheOptions{ + Log: log.Null(), + } + for _, opt := range cacheOpts { + opt(opts) + } + cacheBackend, err := getDefaultBackend(cacheDir, opts.Log) + if err != nil { + return nil, err + } + + if err := cacheBackend.Open(); err != nil { + return nil, fmt.Errorf("open cache: %v", err) + } + return &cache{backend: cacheBackend, log: opts.Log}, nil +} + +func getDefaultBackend(cacheDir string, log *logrus.Entry) (backend, error) { + entries, err := os.ReadDir(cacheDir) + if err != nil && !errors.Is(err, os.ErrNotExist) { + return nil, fmt.Errorf("detect cache format: read cache directory: %v", err) + } + + backends := []backend{ + newPogrebV1Backend(cacheDir), + newJSONBackend(cacheDir), + } + + if len(entries) == 0 { + log.WithField("backend", backends[0].Name()).Info("cache directory is empty, using preferred backend") + return backends[0], nil + } + + for _, backend := range backends { + if backend.IsCachePresent() { + log.WithField("backend", backend.Name()).Info("found existing cache contents") + return backend, nil + } + } + + // Anything else is unexpected. + entryNames := make([]string, 0, len(entries)) + for _, entry := range entries { + if entry.Name() == "." { + continue + } + entryNames = append(entryNames, entry.Name()) + } + return nil, fmt.Errorf("cache directory has unexpected contents: %v", strings.Join(entryNames, ",")) +} + +func LoadOrRebuild(ctx context.Context, c Cache, fbc fs.FS) error { + if err := c.CheckIntegrity(ctx, fbc); err != nil { + if err := c.Build(ctx, fbc); err != nil { + return fmt.Errorf("failed to rebuild cache: %v", err) + } + } + return c.Load(ctx) +} + +var _ Cache = &cache{} + +type cache struct { + backend backend + log *logrus.Entry + packageIndex +} + +type bundleStreamTransformer func(*api.Bundle) +type transformingBundleSender struct { + stream registry.BundleSender + transformer bundleStreamTransformer +} + +func (t *transformingBundleSender) Send(b *api.Bundle) error { + t.transformer(b) + return t.stream.Send(b) +} + +type sliceBundleSender []*api.Bundle + +func (s *sliceBundleSender) Send(b *api.Bundle) error { + *s = append(*s, b) + return nil +} + +func (c *cache) SendBundles(ctx context.Context, stream registry.BundleSender) error { + transform := func(bundle *api.Bundle) { + if bundle.BundlePath != "" { + // The SQLite-based server + // configures its querier to + // omit these fields when + // key path is set. + bundle.CsvJson = "" + bundle.Object = nil + } + } + return c.backend.SendBundles(ctx, &transformingBundleSender{stream, transform}) +} + +func (c *cache) ListBundles(ctx context.Context) ([]*api.Bundle, error) { + var bundleSender sliceBundleSender + if err := c.SendBundles(ctx, &bundleSender); err != nil { + return nil, err + } + return bundleSender, nil +} + +func (c *cache) getTrimmedBundle(ctx context.Context, key bundleKey) (*api.Bundle, error) { + apiBundle, err := c.backend.GetBundle(ctx, key) + if err != nil { + return nil, err + } + apiBundle.Replaces = "" + apiBundle.Skips = nil + return apiBundle, nil +} + +func (c *cache) GetBundle(ctx context.Context, pkgName, channelName, csvName string) (*api.Bundle, error) { + pkg, ok := c.packageIndex[pkgName] + if !ok { + return nil, fmt.Errorf("package %q not found", pkgName) + } + ch, ok := pkg.Channels[channelName] + if !ok { + return nil, fmt.Errorf("package %q, channel %q not found", pkgName, channelName) + } + b, ok := ch.Bundles[csvName] + if !ok { + return nil, fmt.Errorf("package %q, channel %q, bundle %q not found", pkgName, channelName, csvName) + } + return c.getTrimmedBundle(ctx, bundleKey{pkg.Name, ch.Name, b.Name}) +} + +func (c *cache) GetBundleForChannel(ctx context.Context, pkgName string, channelName string) (*api.Bundle, error) { + return c.packageIndex.GetBundleForChannel(ctx, c.getTrimmedBundle, pkgName, channelName) +} + +func (c *cache) GetBundleThatReplaces(ctx context.Context, name, pkgName, channelName string) (*api.Bundle, error) { + return c.packageIndex.GetBundleThatReplaces(ctx, c.getTrimmedBundle, name, pkgName, channelName) +} + +func (c *cache) GetChannelEntriesThatProvide(ctx context.Context, group, version, kind string) ([]*registry.ChannelEntry, error) { + return c.packageIndex.GetChannelEntriesThatProvide(ctx, c.backend.GetBundle, group, version, kind) +} + +func (c *cache) GetLatestChannelEntriesThatProvide(ctx context.Context, group, version, kind string) ([]*registry.ChannelEntry, error) { + return c.packageIndex.GetLatestChannelEntriesThatProvide(ctx, c.backend.GetBundle, group, version, kind) +} + +func (c *cache) GetBundleThatProvides(ctx context.Context, group, version, kind string) (*api.Bundle, error) { + return c.packageIndex.GetBundleThatProvides(ctx, c, group, version, kind) +} + +func (c *cache) CheckIntegrity(ctx context.Context, fbc fs.FS) error { + existingDigest, err := c.backend.GetDigest(ctx) + if err != nil { + return fmt.Errorf("read existing cache digest: %v", err) + } + computedDigest, err := c.backend.ComputeDigest(ctx, fbc) + if err != nil { + return fmt.Errorf("compute digest: %v", err) + } + if existingDigest != computedDigest { + c.log.WithField("existingDigest", existingDigest).WithField("computedDigest", computedDigest).Warn("cache requires rebuild") + return fmt.Errorf("cache requires rebuild: cache reports digest as %q, but computed digest is %q", existingDigest, computedDigest) + } + return nil +} + +func (c *cache) Build(ctx context.Context, fbcFsys fs.FS) error { + // ensure that generated cache is available to all future users + oldUmask := umask(000) + defer umask(oldUmask) + + c.log.Info("building cache") + + if err := c.backend.Init(); err != nil { + return fmt.Errorf("init cache: %v", err) + } + + tmpFile, err := os.CreateTemp("", "opm-cache-build-*.json") + if err != nil { + return err + } + defer func() { + tmpFile.Close() + os.Remove(tmpFile.Name()) + }() + + var ( + concurrency = runtime.NumCPU() + byPackageReaders = map[string][]io.Reader{} + walkMu sync.Mutex + offset int64 + ) + if err := declcfg.WalkMetasFS(ctx, fbcFsys, func(path string, meta *declcfg.Meta, err error) error { + if err != nil { + return err + } + packageName := meta.Package + if meta.Schema == declcfg.SchemaPackage { + packageName = meta.Name + } + + walkMu.Lock() + defer walkMu.Unlock() + if _, err := tmpFile.Write(meta.Blob); err != nil { + return err + } + sr := io.NewSectionReader(tmpFile, offset, int64(len(meta.Blob))) + byPackageReaders[packageName] = append(byPackageReaders[packageName], sr) + offset += int64(len(meta.Blob)) + return nil + }, declcfg.WithConcurrency(concurrency)); err != nil { + return err + } + if err := tmpFile.Sync(); err != nil { + return err + } + + eg, egCtx := errgroup.WithContext(ctx) + pkgNameChan := make(chan string, concurrency) + eg.Go(func() error { + defer close(pkgNameChan) + for pkgName := range byPackageReaders { + select { + case <-egCtx.Done(): + return egCtx.Err() + case pkgNameChan <- pkgName: + } + } + return nil + }) + + var ( + pkgs = packageIndex{} + pkgsMu sync.Mutex + ) + for i := 0; i < concurrency; i++ { + eg.Go(func() error { + for { + select { + case <-egCtx.Done(): + return egCtx.Err() + case pkgName, ok := <-pkgNameChan: + if !ok { + return nil + } + pkgIndex, err := c.processPackage(egCtx, io.MultiReader(byPackageReaders[pkgName]...)) + if err != nil { + return fmt.Errorf("process package %q: %v", pkgName, err) + } + + pkgsMu.Lock() + pkgs[pkgName] = pkgIndex[pkgName] + pkgsMu.Unlock() + } + } + return nil + }) + } + if err := eg.Wait(); err != nil { + return fmt.Errorf("build package index: %v", err) + } + + if err := c.backend.PutPackageIndex(ctx, pkgs); err != nil { + return fmt.Errorf("store package index: %v", err) + } + + digest, err := c.backend.ComputeDigest(ctx, fbcFsys) + if err != nil { + return fmt.Errorf("compute digest: %v", err) + } + if err := c.backend.PutDigest(ctx, digest); err != nil { + return fmt.Errorf("store digest: %v", err) + } + return nil +} + +func (c *cache) processPackage(ctx context.Context, reader io.Reader) (packageIndex, error) { + pkgFbc, err := declcfg.LoadReader(reader) + if err != nil { + return nil, err + } + pkgModel, err := declcfg.ConvertToModel(*pkgFbc) + if err != nil { + return nil, err + } + pkgIndex, err := packagesFromModel(pkgModel) + if err != nil { + return nil, err + } + for _, p := range pkgModel { + for _, ch := range p.Channels { + for _, b := range ch.Bundles { + apiBundle, err := api.ConvertModelBundleToAPIBundle(*b) + if err != nil { + return nil, err + } + if err := c.backend.PutBundle(ctx, bundleKey{p.Name, ch.Name, b.Name}, apiBundle); err != nil { + return nil, fmt.Errorf("store bundle %q: %v", b.Name, err) + } + } + } + } + return pkgIndex, nil +} + +func (c *cache) Load(ctx context.Context) error { + pi, err := c.backend.GetPackageIndex(ctx) + if err != nil { + return fmt.Errorf("get package index: %v", err) + } + c.packageIndex = pi + return nil +} + +func (c *cache) Close() error { + return c.backend.Close() +} + +func ensureEmptyDir(dir string, mode os.FileMode) error { + if err := os.MkdirAll(dir, mode); err != nil { + return err + } + entries, err := os.ReadDir(dir) + if err != nil { + return err + } + for _, entry := range entries { + if err := os.RemoveAll(filepath.Join(dir, entry.Name())); err != nil { + return err + } + } + return nil +} + +func readDigestFile(digestFile string) (string, error) { + existingDigestBytes, err := os.ReadFile(digestFile) + if err != nil { + return "", err + } + return strings.TrimSpace(string(existingDigestBytes)), nil +} + +func writeDigestFile(file string, digest string, mode os.FileMode) error { + return os.WriteFile(file, []byte(digest), mode) +} + +func doesBundleProvide(ctx context.Context, getBundle getBundleFunc, pkgName, chName, bundleName, group, version, kind string) (bool, error) { + apiBundle, err := getBundle(ctx, bundleKey{pkgName, chName, bundleName}) + if err != nil { + return false, fmt.Errorf("get bundle %q: %v", bundleName, err) + } + for _, gvk := range apiBundle.ProvidedApis { + if gvk.Group == group && gvk.Version == version && gvk.Kind == kind { + return true, nil + } + } + return false, nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/cache/json.go b/vendor/github.com/operator-framework/operator-registry/pkg/cache/json.go new file mode 100644 index 0000000000..7ea5992187 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/cache/json.go @@ -0,0 +1,205 @@ +package cache + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "hash/fnv" + "io" + "io/fs" + "os" + "path/filepath" + + "github.com/sirupsen/logrus" + + "github.com/operator-framework/operator-registry/pkg/api" + "github.com/operator-framework/operator-registry/pkg/registry" +) + +var _ backend = &jsonBackend{} + +func newJSONBackend(baseDir string) *jsonBackend { + return &jsonBackend{ + baseDir: baseDir, + bundles: newBundleKeys(), + } +} + +const ( + jsonCacheModeDir = 0750 + jsonCacheModeFile = 0640 + + jsonDigestFile = "digest" + jsonDir = "cache" + jsonPackagesFile = jsonDir + string(filepath.Separator) + "packages.json" +) + +type jsonBackend struct { + baseDir string + bundles bundleKeys +} + +func (q *jsonBackend) Name() string { + return "json" +} + +func (q *jsonBackend) IsCachePresent() bool { + entries, err := os.ReadDir(q.baseDir) + if err != nil && !errors.Is(err, os.ErrNotExist) { + return false + } + var hasDir, hasDigest bool + for _, entry := range entries { + if entry.IsDir() && entry.Name() == jsonDir { + hasDir = true + } + if entry.Name() == jsonDigestFile { + hasDigest = true + } + } + return hasDir && hasDigest +} + +func (q *jsonBackend) Init() error { + if err := ensureEmptyDir(filepath.Join(q.baseDir, jsonDir), jsonCacheModeDir); err != nil { + return fmt.Errorf("failed to ensure JSON cache directory: %v", err) + } + if err := os.RemoveAll(filepath.Join(q.baseDir, jsonDigestFile)); err != nil { + return fmt.Errorf("failed to remove existing JSON digest file: %v", err) + } + q.bundles = newBundleKeys() + return nil +} + +func (q *jsonBackend) Open() error { + return nil +} + +func (q *jsonBackend) Close() error { + return nil +} + +func (q *jsonBackend) GetPackageIndex(_ context.Context) (packageIndex, error) { + packagesData, err := os.ReadFile(filepath.Join(q.baseDir, jsonPackagesFile)) + if err != nil { + return nil, err + } + var pi packageIndex + if err := json.Unmarshal(packagesData, &pi); err != nil { + return nil, err + } + for _, pkg := range pi { + for _, ch := range pkg.Channels { + for _, b := range ch.Bundles { + q.bundles.Set(bundleKey{PackageName: pkg.Name, ChannelName: ch.Name, Name: b.Name}) + } + } + } + return pi, nil +} + +func (q *jsonBackend) PutPackageIndex(_ context.Context, pi packageIndex) error { + packageJson, err := json.Marshal(pi) + if err != nil { + return err + } + if err := os.WriteFile(filepath.Join(q.baseDir, jsonPackagesFile), packageJson, jsonCacheModeFile); err != nil { + return err + } + return nil +} + +func (q *jsonBackend) bundleFile(in bundleKey) string { + return filepath.Join(q.baseDir, jsonDir, fmt.Sprintf("%s_%s_%s.json", in.PackageName, in.ChannelName, in.Name)) +} + +func (q *jsonBackend) GetBundle(_ context.Context, key bundleKey) (*api.Bundle, error) { + d, err := os.ReadFile(q.bundleFile(key)) + if err != nil { + return nil, err + } + var b api.Bundle + if err := json.Unmarshal(d, &b); err != nil { + return nil, err + } + return &b, nil +} + +func (q *jsonBackend) PutBundle(_ context.Context, key bundleKey, bundle *api.Bundle) error { + d, err := json.Marshal(bundle) + if err != nil { + return err + } + if err := os.WriteFile(q.bundleFile(key), d, jsonCacheModeFile); err != nil { + return err + } + q.bundles.Set(key) + return nil +} + +func (q *jsonBackend) GetDigest(_ context.Context) (string, error) { + return readDigestFile(filepath.Join(q.baseDir, jsonDigestFile)) +} + +func (q *jsonBackend) ComputeDigest(_ context.Context, fbcFsys fs.FS) (string, error) { + // We are not sensitive to the size of this buffer, we just need it to be shared. + // For simplicity, do the same as io.Copy() would. + buf := make([]byte, 32*1024) + computedHasher := fnv.New64a() + if err := fsToTar(computedHasher, fbcFsys, buf); err != nil { + return "", err + } + + if cacheFS, err := fs.Sub(os.DirFS(q.baseDir), jsonDir); err == nil { + if err := fsToTar(computedHasher, cacheFS, buf); err != nil && !errors.Is(err, os.ErrNotExist) { + return "", fmt.Errorf("compute hash: %v", err) + } + } + return fmt.Sprintf("%x", computedHasher.Sum(nil)), nil +} + +func (q *jsonBackend) PutDigest(_ context.Context, digest string) error { + return writeDigestFile(filepath.Join(q.baseDir, jsonDigestFile), digest, jsonCacheModeFile) +} + +func (q *jsonBackend) SendBundles(_ context.Context, s registry.BundleSender) error { + keys := make([]bundleKey, 0, q.bundles.Len()) + files := make([]*os.File, 0, q.bundles.Len()) + readers := make([]io.Reader, 0, q.bundles.Len()) + if err := q.bundles.Walk(func(key bundleKey) error { + file, err := os.Open(q.bundleFile(key)) + if err != nil { + return fmt.Errorf("failed to open file for package %q, channel %q, key %q: %w", key.PackageName, key.ChannelName, key.Name, err) + } + keys = append(keys, key) + files = append(files, file) + readers = append(readers, file) + return nil + }); err != nil { + return err + } + defer func() { + for _, file := range files { + if err := file.Close(); err != nil { + logrus.WithError(err).WithField("file", file.Name()).Warn("could not close file") + } + } + }() + multiReader := io.MultiReader(readers...) + decoder := json.NewDecoder(multiReader) + index := 0 + for { + var bundle api.Bundle + if err := decoder.Decode(&bundle); err == io.EOF { + break + } else if err != nil { + return fmt.Errorf("failed to decode file for package %q, channel %q, key %q: %w", keys[index].PackageName, keys[index].ChannelName, keys[index].Name, err) + } + if err := s.Send(&bundle); err != nil { + return err + } + index += 1 + } + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/cache/pkgs.go b/vendor/github.com/operator-framework/operator-registry/pkg/cache/pkgs.go new file mode 100644 index 0000000000..e590823b43 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/cache/pkgs.go @@ -0,0 +1,308 @@ +package cache + +import ( + "context" + "fmt" + "sort" + "strings" + + "github.com/operator-framework/operator-registry/alpha/model" + "github.com/operator-framework/operator-registry/pkg/api" + "github.com/operator-framework/operator-registry/pkg/registry" +) + +type packageIndex map[string]cPkg + +func (pkgs packageIndex) ListPackages(_ context.Context) ([]string, error) { + var packages []string + for pkgName := range pkgs { + packages = append(packages, pkgName) + } + return packages, nil +} + +func (pkgs packageIndex) GetPackage(_ context.Context, name string) (*registry.PackageManifest, error) { + pkg, ok := pkgs[name] + if !ok { + return nil, fmt.Errorf("package %q not found", name) + } + + var channels []registry.PackageChannel + for _, ch := range pkg.Channels { + var deprecation *registry.Deprecation + if ch.Deprecation != nil { + deprecation = ®istry.Deprecation{Message: ch.Deprecation.Message} + } + channels = append(channels, registry.PackageChannel{ + Name: ch.Name, + CurrentCSVName: ch.Head, + Deprecation: deprecation, + }) + } + sort.Slice(channels, func(i, j int) bool { return strings.Compare(channels[i].Name, channels[j].Name) < 0 }) + registryPackage := ®istry.PackageManifest{ + PackageName: pkg.Name, + Channels: channels, + DefaultChannelName: pkg.DefaultChannel, + } + if pkg.Deprecation != nil { + registryPackage.Deprecation = ®istry.Deprecation{Message: pkg.Deprecation.Message} + } + return registryPackage, nil +} + +func (pkgs packageIndex) GetChannelEntriesThatReplace(_ context.Context, name string) ([]*registry.ChannelEntry, error) { + var entries []*registry.ChannelEntry + + for _, pkg := range pkgs { + for _, ch := range pkg.Channels { + for _, b := range ch.Bundles { + entries = append(entries, channelEntriesThatReplace(b, name)...) + } + } + } + if len(entries) == 0 { + return nil, fmt.Errorf("no channel entries found that replace %s", name) + } + return entries, nil +} + +type getBundleFunc func(context.Context, bundleKey) (*api.Bundle, error) + +func (pkgs packageIndex) GetBundleForChannel(ctx context.Context, getBundle getBundleFunc, pkgName string, channelName string) (*api.Bundle, error) { + pkg, ok := pkgs[pkgName] + if !ok { + return nil, fmt.Errorf("package %q not found", pkgName) + } + ch, ok := pkg.Channels[channelName] + if !ok { + return nil, fmt.Errorf("package %q, channel %q not found", pkgName, channelName) + } + return getBundle(ctx, bundleKey{pkg.Name, ch.Name, ch.Head}) +} + +func (pkgs packageIndex) GetBundleThatReplaces(ctx context.Context, getBundle getBundleFunc, name, pkgName, channelName string) (*api.Bundle, error) { + pkg, ok := pkgs[pkgName] + if !ok { + return nil, fmt.Errorf("package %s not found", pkgName) + } + ch, ok := pkg.Channels[channelName] + if !ok { + return nil, fmt.Errorf("package %q, channel %q not found", pkgName, channelName) + } + + // NOTE: iterating over a map is non-deterministic in Go, so if multiple bundles replace this one, + // the bundle returned by this function is also non-deterministic. The sqlite implementation + // is ALSO non-deterministic because it doesn't use ORDER BY, so its probably okay for this + // implementation to be non-deterministic as well. + for _, b := range ch.Bundles { + if bundleReplaces(b, name) { + return getBundle(ctx, bundleKey{pkg.Name, ch.Name, b.Name}) + } + } + return nil, fmt.Errorf("no entry found for package %q, channel %q", pkgName, channelName) +} + +func (pkgs packageIndex) GetChannelEntriesThatProvide(ctx context.Context, getBundle getBundleFunc, group, version, kind string) ([]*registry.ChannelEntry, error) { + var entries []*registry.ChannelEntry + + for _, pkg := range pkgs { + for _, ch := range pkg.Channels { + for _, b := range ch.Bundles { + provides, err := doesBundleProvide(ctx, getBundle, b.Package, b.Channel, b.Name, group, version, kind) + if err != nil { + return nil, err + } + if provides { + // TODO(joelanford): It seems like the SQLite query returns + // invalid entries (i.e. where bundle `Replaces` isn't actually + // in channel `ChannelName`). Is that a bug? For now, this mimics + // the sqlite server and returns seemingly invalid channel entries. + // Don't worry about this. Not used anymore. + + entries = append(entries, pkgs.channelEntriesForBundle(b, true)...) + } + } + } + } + if len(entries) == 0 { + return nil, fmt.Errorf("no channel entries found that provide group:%q version:%q kind:%q", group, version, kind) + } + return entries, nil +} + +// TODO(joelanford): Need to review the expected functionality of this function. I ran +// +// some experiments with the sqlite version of this function and it seems to only return +// channel heads that provide the GVK (rather than searching down the graph if parent bundles +// don't provide the API). Based on that, this function currently looks at channel heads only. +// --- +// Separate, but possibly related, I noticed there are several channels in the channel entry +// table who's minimum depth is 1. What causes 1 to be minimum depth in some cases and 0 in others? +func (pkgs packageIndex) GetLatestChannelEntriesThatProvide(ctx context.Context, getBundle getBundleFunc, group, version, kind string) ([]*registry.ChannelEntry, error) { + var entries []*registry.ChannelEntry + + for _, pkg := range pkgs { + for _, ch := range pkg.Channels { + b := ch.Bundles[ch.Head] + provides, err := doesBundleProvide(ctx, getBundle, b.Package, b.Channel, b.Name, group, version, kind) + if err != nil { + return nil, err + } + if provides { + entries = append(entries, pkgs.channelEntriesForBundle(b, false)...) + } + } + } + if len(entries) == 0 { + return nil, fmt.Errorf("no channel entries found that provide group:%q version:%q kind:%q", group, version, kind) + } + return entries, nil +} + +func (pkgs packageIndex) GetBundleThatProvides(ctx context.Context, c Cache, group, version, kind string) (*api.Bundle, error) { + latestEntries, err := c.GetLatestChannelEntriesThatProvide(ctx, group, version, kind) + if err != nil { + return nil, err + } + + // It's possible for multiple packages to provide an API, but this function is forced to choose one. + // To do that deterministically, we'll pick the the bundle based on a lexicographical sort of its + // package name. + sort.Slice(latestEntries, func(i, j int) bool { + return latestEntries[i].PackageName < latestEntries[j].PackageName + }) + + for _, entry := range latestEntries { + pkg, ok := pkgs[entry.PackageName] + if !ok { + // This should never happen because the latest entries were + // collected based on iterating over the packages in q.packageIndex. + continue + } + if entry.ChannelName == pkg.DefaultChannel { + return c.GetBundle(ctx, entry.PackageName, entry.ChannelName, entry.BundleName) + } + } + return nil, fmt.Errorf("no entry found that provides group:%q version:%q kind:%q", group, version, kind) +} + +type cPkg struct { + Name string `json:"name"` + Description string `json:"description"` + Icon *model.Icon `json:"icon"` + DefaultChannel string `json:"defaultChannel"` + Channels map[string]cChannel + Deprecation *model.Deprecation `json:"deprecation,omitempty"` +} + +type cChannel struct { + Name string + Head string + Bundles map[string]cBundle + Deprecation *model.Deprecation `json:"deprecation,omitempty"` +} + +type cBundle struct { + Package string `json:"package"` + Channel string `json:"channel"` + Name string `json:"name"` + Replaces string `json:"replaces"` + Skips []string `json:"skips"` +} + +func packagesFromModel(m model.Model) (map[string]cPkg, error) { + pkgs := map[string]cPkg{} + for _, p := range m { + newP := cPkg{ + Name: p.Name, + Icon: p.Icon, + Description: p.Description, + DefaultChannel: p.DefaultChannel.Name, + Channels: map[string]cChannel{}, + Deprecation: p.Deprecation, + } + for _, ch := range p.Channels { + head, err := ch.Head() + if err != nil { + return nil, err + } + newCh := cChannel{ + Name: ch.Name, + Head: head.Name, + Bundles: map[string]cBundle{}, + Deprecation: ch.Deprecation, + } + for _, b := range ch.Bundles { + newB := cBundle{ + Package: b.Package.Name, + Channel: b.Channel.Name, + Name: b.Name, + Replaces: b.Replaces, + Skips: b.Skips, + } + newCh.Bundles[b.Name] = newB + } + newP.Channels[ch.Name] = newCh + } + pkgs[p.Name] = newP + } + return pkgs, nil +} + +func bundleReplaces(b cBundle, name string) bool { + if b.Replaces == name { + return true + } + for _, s := range b.Skips { + if s == name { + return true + } + } + return false +} + +func channelEntriesThatReplace(b cBundle, name string) []*registry.ChannelEntry { + var entries []*registry.ChannelEntry + if b.Replaces == name { + entries = append(entries, ®istry.ChannelEntry{ + PackageName: b.Package, + ChannelName: b.Channel, + BundleName: b.Name, + Replaces: b.Replaces, + }) + } + for _, s := range b.Skips { + if s == name && s != b.Replaces { + entries = append(entries, ®istry.ChannelEntry{ + PackageName: b.Package, + ChannelName: b.Channel, + BundleName: b.Name, + Replaces: b.Replaces, + }) + } + } + return entries +} + +func (pkgs packageIndex) channelEntriesForBundle(b cBundle, ignoreChannel bool) []*registry.ChannelEntry { + entries := []*registry.ChannelEntry{{ + PackageName: b.Package, + ChannelName: b.Channel, + BundleName: b.Name, + Replaces: b.Replaces, + }} + for _, s := range b.Skips { + // Ignore skips that duplicate b.Replaces. Also, only add it if its + // in the same channel as b (or we're ignoring channel presence). + if _, inChannel := pkgs[b.Package].Channels[b.Channel].Bundles[s]; s != b.Replaces && (ignoreChannel || inChannel) { + entries = append(entries, ®istry.ChannelEntry{ + PackageName: b.Package, + ChannelName: b.Channel, + BundleName: b.Name, + Replaces: s, + }) + } + } + return entries +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/cache/pogrebv1.go b/vendor/github.com/operator-framework/operator-registry/pkg/cache/pogrebv1.go new file mode 100644 index 0000000000..af5b35ddf5 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/cache/pogrebv1.go @@ -0,0 +1,244 @@ +package cache + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "hash/fnv" + "io" + "io/fs" + "os" + "path/filepath" + "sort" + + "github.com/akrylysov/pogreb" + pogrebfs "github.com/akrylysov/pogreb/fs" + "github.com/golang/protobuf/proto" + + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/pkg/api" + "github.com/operator-framework/operator-registry/pkg/registry" +) + +var _ backend = &pogrebV1Backend{} + +func newPogrebV1Backend(baseDir string) *pogrebV1Backend { + return &pogrebV1Backend{ + baseDir: baseDir, + bundles: newBundleKeys(), + } +} + +const ( + pogrebV1CacheModeDir = 0770 + pogrebV1CacheModeFile = 0660 + + pograbV1CacheDir = "pogreb.v1" + pogrebDigestFile = pograbV1CacheDir + "/digest" + pogrebDbDir = pograbV1CacheDir + "/db" +) + +type pogrebV1Backend struct { + baseDir string + db *pogreb.DB + bundles bundleKeys +} + +func (q *pogrebV1Backend) Name() string { + return pograbV1CacheDir +} + +func (q *pogrebV1Backend) IsCachePresent() bool { + entries, err := os.ReadDir(q.baseDir) + if err != nil && !errors.Is(err, os.ErrNotExist) { + return false + } + for _, entry := range entries { + if entry.IsDir() && entry.Name() == pograbV1CacheDir { + return true + } + } + return false +} + +func (q *pogrebV1Backend) Init() error { + if err := q.Close(); err != nil { + return fmt.Errorf("failed to close existing DB: %v", err) + } + if err := ensureEmptyDir(filepath.Join(q.baseDir, pograbV1CacheDir), pogrebV1CacheModeDir); err != nil { + return fmt.Errorf("ensure empty cache directory: %v", err) + } + q.bundles = newBundleKeys() + return q.Open() +} + +func (q *pogrebV1Backend) Open() error { + db, err := pogreb.Open(filepath.Join(q.baseDir, pogrebDbDir), &pogreb.Options{FileSystem: pogrebfs.OSMMap}) + if err != nil { + return err + } + q.db = db + return nil +} + +func (q *pogrebV1Backend) Close() error { + if q.db == nil { + return nil + } + if err := q.db.Close(); err != nil { + return err + } + + // Recursively fixup permissions on the DB directory. + return filepath.Walk(filepath.Join(q.baseDir, pogrebDbDir), func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + switch info.Mode().Type() { + case os.ModeDir: + return os.Chmod(path, pogrebV1CacheModeDir) + case 0: + return os.Chmod(path, pogrebV1CacheModeFile) + default: + return nil + } + }) +} + +func (q *pogrebV1Backend) GetPackageIndex(_ context.Context) (packageIndex, error) { + packagesData, err := q.db.Get([]byte("packages.json")) + if err != nil { + return nil, err + } + var pi packageIndex + if err := json.Unmarshal(packagesData, &pi); err != nil { + return nil, err + } + for _, pkg := range pi { + for _, ch := range pkg.Channels { + for _, b := range ch.Bundles { + q.bundles.Set(bundleKey{PackageName: pkg.Name, ChannelName: ch.Name, Name: b.Name}) + } + } + } + return pi, nil +} + +func (q *pogrebV1Backend) PutPackageIndex(_ context.Context, index packageIndex) error { + packageJson, err := json.Marshal(index) + if err != nil { + return err + } + return q.db.Put([]byte("packages.json"), packageJson) +} + +func (q *pogrebV1Backend) dbKey(in bundleKey) []byte { + return []byte(fmt.Sprintf("bundles/%s/%s/%s", in.PackageName, in.ChannelName, in.Name)) +} + +func (q *pogrebV1Backend) GetBundle(_ context.Context, key bundleKey) (*api.Bundle, error) { + d, err := q.db.Get(q.dbKey(key)) + if err != nil { + return nil, err + } + var b api.Bundle + if err := proto.Unmarshal(d, &b); err != nil { + return nil, err + } + return &b, nil +} + +func (q *pogrebV1Backend) PutBundle(_ context.Context, key bundleKey, bundle *api.Bundle) error { + d, err := proto.Marshal(bundle) + if err != nil { + return err + } + if err := q.db.Put(q.dbKey(key), d); err != nil { + return err + } + q.bundles.Set(key) + return nil +} + +func (q *pogrebV1Backend) GetDigest(_ context.Context) (string, error) { + return readDigestFile(filepath.Join(q.baseDir, pogrebDigestFile)) +} + +func (q *pogrebV1Backend) orderedKeys() ([]string, error) { + it := q.db.Items() + keys := make([]string, 0, q.db.Count()) + for { + k, _, err := it.Next() + if errors.Is(err, pogreb.ErrIterationDone) { + break + } + if err != nil { + return nil, err + } + keys = append(keys, string(k)) + } + sort.Strings(keys) + return keys, nil +} + +func (q *pogrebV1Backend) writeKeyValue(w io.Writer, k []byte) error { + v, err := q.db.Get(k) + if err != nil { + return err + } + if _, err := w.Write(k); err != nil { + return err + } + if _, err := w.Write(v); err != nil { + return err + } + return nil +} + +func (q *pogrebV1Backend) ComputeDigest(ctx context.Context, fbcFsys fs.FS) (string, error) { + computedHasher := fnv.New64a() + + // Use concurrency=1 to ensure deterministic ordering of meta blobs. + loadOpts := []declcfg.LoadOption{declcfg.WithConcurrency(1)} + if err := declcfg.WalkMetasFS(ctx, fbcFsys, func(path string, meta *declcfg.Meta, err error) error { + if err != nil { + return err + } + if _, err := computedHasher.Write(meta.Blob); err != nil { + return err + } + return nil + }, loadOpts...); err != nil { + return "", err + } + + orderedKeys, err := q.orderedKeys() + if err != nil { + return "", err + } + for _, dbKey := range orderedKeys { + if err := q.writeKeyValue(computedHasher, []byte(dbKey)); err != nil { + return "", err + } + } + return fmt.Sprintf("%x", computedHasher.Sum(nil)), nil +} + +func (q *pogrebV1Backend) PutDigest(_ context.Context, digest string) error { + return writeDigestFile(filepath.Join(q.baseDir, pogrebDigestFile), digest, pogrebV1CacheModeFile) +} + +func (q *pogrebV1Backend) SendBundles(_ context.Context, s registry.BundleSender) error { + return q.bundles.Walk(func(key bundleKey) error { + bundleData, err := q.db.Get(q.dbKey(key)) + if err != nil { + return fmt.Errorf("failed to get data for package %q, channel %q, key %q: %w", key.PackageName, key.ChannelName, key.Name, err) + } + var bundle api.Bundle + if err := proto.Unmarshal(bundleData, &bundle); err != nil { + return fmt.Errorf("failed to decode data for package %q, channel %q, key %q: %w", key.PackageName, key.ChannelName, key.Name, err) + } + return s.Send(&bundle) + }) +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/cache/syscall_unix.go b/vendor/github.com/operator-framework/operator-registry/pkg/cache/syscall_unix.go new file mode 100644 index 0000000000..93372adb4e --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/cache/syscall_unix.go @@ -0,0 +1,8 @@ +//go:build !windows +// +build !windows + +package cache + +import "golang.org/x/sys/unix" + +var umask = unix.Umask diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/cache/syscall_windows.go b/vendor/github.com/operator-framework/operator-registry/pkg/cache/syscall_windows.go new file mode 100644 index 0000000000..7ff5ad8e86 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/cache/syscall_windows.go @@ -0,0 +1,6 @@ +//go:build windows +// +build windows + +package cache + +var umask = func(i int) int { return 0 } diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/cache/tar.go b/vendor/github.com/operator-framework/operator-registry/pkg/cache/tar.go new file mode 100644 index 0000000000..92e83c1817 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/cache/tar.go @@ -0,0 +1,71 @@ +package cache + +import ( + "archive/tar" + "fmt" + "io" + "io/fs" + "os" + "time" +) + +// fsToTar writes the filesystem represented by fsys to w as a tar archive. +// This function unsets user and group information in the tar archive so that readers +// of archives produced by this function do not need to account for differences in +// permissions between source and destination filesystems. +func fsToTar(w io.Writer, fsys fs.FS, buf []byte) error { + if buf == nil || len(buf) == 0 { + // We are not sensitive to the size of this buffer, we just need it to be shared. + // For simplicity, do the same as io.Copy() would. + buf = make([]byte, 32*1024) + } + tw := tar.NewWriter(w) + if err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.Type()&os.ModeSymlink != 0 { + return nil + } + info, err := d.Info() + if err != nil { + return fmt.Errorf("get file info for %q: %v", path, err) + } + + h, err := tar.FileInfoHeader(info, "") + if err != nil { + return fmt.Errorf("build tar file info header for %q: %v", path, err) + } + h.Uid = 0 + h.Gid = 0 + h.Uname = "" + h.Gname = "" + h.AccessTime = time.Time{} + h.ChangeTime = time.Time{} + h.ModTime = time.Time{} + h.Name = path + + if err := tw.WriteHeader(h); err != nil { + return fmt.Errorf("write tar header for %q: %v", path, err) + } + if d.IsDir() { + return nil + } + f, err := fsys.Open(path) + if err != nil { + return fmt.Errorf("open file %q: %v", path, err) + } + defer f.Close() + if _, err := io.CopyBuffer(tw, f, buf); err != nil { + return fmt.Errorf("write tar data for %q: %v", path, err) + } + return nil + }); err != nil { + return fmt.Errorf("write tar: %w", err) + } + if err := tw.Close(); err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/lib/certs/certs.go b/vendor/github.com/operator-framework/operator-registry/pkg/lib/certs/certs.go new file mode 100644 index 0000000000..3317d57661 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/lib/certs/certs.go @@ -0,0 +1,25 @@ +package certs + +import ( + "crypto/x509" + "fmt" + "os" +) + +// RootCAs gets root CAs from system store and the given file +func RootCAs(CaFile string) (*x509.CertPool, error) { + rootCAs, err := x509.SystemCertPool() + if err != nil || rootCAs == nil { + rootCAs = x509.NewCertPool() + } + if len(CaFile) > 0 { + certs, err := os.ReadFile(CaFile) + if err != nil { + return nil, fmt.Errorf("failed to append %q to RootCAs: %v", certs, err) + } + if ok := rootCAs.AppendCertsFromPEM(certs); !ok { + return nil, fmt.Errorf("unable to add certs specified in %s", CaFile) + } + } + return rootCAs, nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/lib/config/validate.go b/vendor/github.com/operator-framework/operator-registry/pkg/lib/config/validate.go new file mode 100644 index 0000000000..34f2bf0411 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/lib/config/validate.go @@ -0,0 +1,32 @@ +package config + +import ( + "context" + "io/fs" + + "github.com/operator-framework/operator-registry/alpha/declcfg" +) + +// Validate takes a filesystem containing the declarative config file(s) +// 1. Validate if declarative config file(s) are valid based on specified schema +// 2. Validate the `replaces` chains of the upgrade graph +// Inputs: +// directory: a filesystem where declarative config file(s) exist +// Outputs: +// error: a wrapped error that contains a tree of error strings +func Validate(ctx context.Context, root fs.FS) error { + // Load config files and convert them to declcfg objects + cfg, err := declcfg.LoadFS(ctx, root) + if err != nil { + return err + } + // Validate the config using model validation: + // This will convert declcfg objects to intermediate model objects that are + // also used for serve and add commands. The conversion process will run + // validation for the model objects and ensure they are valid. + _, err = declcfg.ConvertToModel(*cfg) + if err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/lib/dns/nsswitch.go b/vendor/github.com/operator-framework/operator-registry/pkg/lib/dns/nsswitch.go new file mode 100644 index 0000000000..1693272fd6 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/lib/dns/nsswitch.go @@ -0,0 +1,27 @@ +package dns + +import ( + "os" + "runtime" +) + +var ( + GOOS = runtime.GOOS + NsswitchContents = []byte("hosts: files dns") + NsswitchFilename = "/etc/nsswitch.conf" +) + +func EnsureNsswitch() error { + // only linux supports nsswitch + if GOOS != "linux" { + return nil + } + + // if the file already exists, don't overwrite it + _, err := os.Stat(NsswitchFilename) + if !os.IsNotExist(err) { + return nil + } + + return os.WriteFile(NsswitchFilename, NsswitchContents, 0644) +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/lib/graceful/shutdown.go b/vendor/github.com/operator-framework/operator-registry/pkg/lib/graceful/shutdown.go new file mode 100644 index 0000000000..34c72d414e --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/lib/graceful/shutdown.go @@ -0,0 +1,33 @@ +package graceful + +import ( + "context" + "os" + "os/signal" + "syscall" + + "github.com/sirupsen/logrus" + "golang.org/x/sync/errgroup" +) + +func Shutdown(logger logrus.FieldLogger, run func() error, cleanup func()) error { + interrupt := make(chan os.Signal, 1) + signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM) + defer signal.Stop(interrupt) + + g, ctx := errgroup.WithContext(context.Background()) + g.Go(run) + + select { + case <-interrupt: + break + case <-ctx.Done(): + break + } + + logger.Info("shutting down...") + + cleanup() + + return g.Wait() +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/lib/indexer/indexer.go b/vendor/github.com/operator-framework/operator-registry/pkg/lib/indexer/indexer.go new file mode 100644 index 0000000000..b3e5c18481 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/lib/indexer/indexer.go @@ -0,0 +1,719 @@ +package indexer + +import ( + "context" + "errors" + "fmt" + "io" + "math/rand" + "os" + "path" + "path/filepath" + "strconv" + "sync" + + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v2" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + + "github.com/operator-framework/operator-registry/pkg/containertools" + "github.com/operator-framework/operator-registry/pkg/image" + "github.com/operator-framework/operator-registry/pkg/image/containerdregistry" + "github.com/operator-framework/operator-registry/pkg/image/execregistry" + "github.com/operator-framework/operator-registry/pkg/lib/bundle" + "github.com/operator-framework/operator-registry/pkg/lib/certs" + "github.com/operator-framework/operator-registry/pkg/lib/registry" + pregistry "github.com/operator-framework/operator-registry/pkg/registry" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +const ( + defaultDockerfileName = "index.Dockerfile" + defaultImageTag = "operator-registry-index:latest" + defaultDatabaseFolder = "database" + defaultDatabaseFile = "index.db" + tmpDirPrefix = "index_tmp_" + tmpBuildDirPrefix = "index_build_tmp" + concurrencyLimitForExport = 10 +) + +var ErrFileBasedCatalogPrune = errors.New("`opm index prune` only supports sqlite-based catalogs. See https://github.com/redhat-openshift-ecosystem/community-operators-prod/issues/793 for instructions on pruning a plaintext files backed catalog.") + +// ImageIndexer is a struct implementation of the Indexer interface +type ImageIndexer struct { + DockerfileGenerator containertools.DockerfileGenerator + CommandRunner containertools.CommandRunner + LabelReader containertools.LabelReader + RegistryAdder registry.RegistryAdder + RegistryDeleter registry.RegistryDeleter + RegistryPruner registry.RegistryPruner + RegistryStrandedPruner registry.RegistryStrandedPruner + RegistryDeprecator registry.RegistryDeprecator + BuildTool containertools.ContainerTool + PullTool containertools.ContainerTool + Logger *logrus.Entry +} + +// AddToIndexRequest defines the parameters to send to the AddToIndex API +type AddToIndexRequest struct { + Generate bool + Permissive bool + BinarySourceImage string + FromIndex string + OutDockerfile string + Bundles []string + Tag string + Mode pregistry.Mode + CaFile string + SkipTLSVerify bool + PlainHTTP bool + Overwrite bool + EnableAlpha bool +} + +// AddToIndex is an aggregate API used to generate a registry index image with additional bundles +func (i ImageIndexer) AddToIndex(request AddToIndexRequest) error { + buildDir, outDockerfile, cleanup, err := buildContext(request.Generate, request.OutDockerfile) + defer cleanup() + if err != nil { + return err + } + + databasePath, err := i.ExtractDatabase(buildDir, request.FromIndex, request.CaFile, request.SkipTLSVerify, request.PlainHTTP) + if err != nil { + return err + } + + // Run opm registry add on the database + addToRegistryReq := registry.AddToRegistryRequest{ + Bundles: request.Bundles, + InputDatabase: databasePath, + Permissive: request.Permissive, + Mode: request.Mode, + SkipTLSVerify: request.SkipTLSVerify, + PlainHTTP: request.PlainHTTP, + ContainerTool: i.PullTool, + Overwrite: request.Overwrite, + EnableAlpha: request.EnableAlpha, + } + + // Add the bundles to the registry + err = i.RegistryAdder.AddToRegistry(addToRegistryReq) + if err != nil { + i.Logger.WithError(err).Debugf("unable to add bundle to registry") + return err + } + + // generate the dockerfile + dockerfile := i.DockerfileGenerator.GenerateIndexDockerfile(request.BinarySourceImage, databasePath) + err = write(dockerfile, outDockerfile, i.Logger) + if err != nil { + return err + } + + if request.Generate { + return nil + } + + // build the dockerfile + err = build(outDockerfile, request.Tag, i.CommandRunner, i.Logger) + if err != nil { + return err + } + + return nil +} + +// DeleteFromIndexRequest defines the parameters to send to the DeleteFromIndex API +type DeleteFromIndexRequest struct { + Generate bool + Permissive bool + BinarySourceImage string + FromIndex string + OutDockerfile string + Tag string + Operators []string + SkipTLSVerify bool + PlainHTTP bool + CaFile string +} + +// DeleteFromIndex is an aggregate API used to generate a registry index image +// without specific operators +func (i ImageIndexer) DeleteFromIndex(request DeleteFromIndexRequest) error { + buildDir, outDockerfile, cleanup, err := buildContext(request.Generate, request.OutDockerfile) + defer cleanup() + if err != nil { + return err + } + + databasePath, err := i.ExtractDatabase(buildDir, request.FromIndex, request.CaFile, request.SkipTLSVerify, request.PlainHTTP) + if err != nil { + return err + } + + // Run opm registry delete on the database + deleteFromRegistryReq := registry.DeleteFromRegistryRequest{ + Packages: request.Operators, + InputDatabase: databasePath, + Permissive: request.Permissive, + } + + // Delete the bundles from the registry + err = i.RegistryDeleter.DeleteFromRegistry(deleteFromRegistryReq) + if err != nil { + return err + } + + // generate the dockerfile + dockerfile := i.DockerfileGenerator.GenerateIndexDockerfile(request.BinarySourceImage, databasePath) + err = write(dockerfile, outDockerfile, i.Logger) + if err != nil { + return err + } + + if request.Generate { + return nil + } + + // build the dockerfile + err = build(outDockerfile, request.Tag, i.CommandRunner, i.Logger) + if err != nil { + return err + } + + return nil +} + +// PruneStrandedFromIndexRequest defines the parameters to send to the PruneStrandedFromIndex API +type PruneStrandedFromIndexRequest struct { + Generate bool + BinarySourceImage string + FromIndex string + OutDockerfile string + Tag string + CaFile string + SkipTLSVerify bool + PlainHTTP bool +} + +// PruneStrandedFromIndex is an aggregate API used to generate a registry index image +// that has removed stranded bundles from the index +func (i ImageIndexer) PruneStrandedFromIndex(request PruneStrandedFromIndexRequest) error { + buildDir, outDockerfile, cleanup, err := buildContext(request.Generate, request.OutDockerfile) + defer cleanup() + if err != nil { + return err + } + + databasePath, err := i.ExtractDatabase(buildDir, request.FromIndex, request.CaFile, request.SkipTLSVerify, request.PlainHTTP) + if err != nil { + return err + } + + // Run opm registry prune-stranded on the database + pruneStrandedFromRegistryReq := registry.PruneStrandedFromRegistryRequest{ + InputDatabase: databasePath, + } + + // Delete the stranded bundles from the registry + err = i.RegistryStrandedPruner.PruneStrandedFromRegistry(pruneStrandedFromRegistryReq) + if err != nil { + return err + } + + // generate the dockerfile + dockerfile := i.DockerfileGenerator.GenerateIndexDockerfile(request.BinarySourceImage, databasePath) + err = write(dockerfile, outDockerfile, i.Logger) + if err != nil { + return err + } + + if request.Generate { + return nil + } + + // build the dockerfile + err = build(outDockerfile, request.Tag, i.CommandRunner, i.Logger) + if err != nil { + return err + } + return nil +} + +// PruneFromIndexRequest defines the parameters to send to the PruneFromIndex API +type PruneFromIndexRequest struct { + Generate bool + Permissive bool + BinarySourceImage string + FromIndex string + OutDockerfile string + Tag string + Packages []string + CaFile string + SkipTLSVerify bool + PlainHTTP bool +} + +func (i ImageIndexer) PruneFromIndex(request PruneFromIndexRequest) error { + buildDir, outDockerfile, cleanup, err := buildContext(request.Generate, request.OutDockerfile) + defer cleanup() + if err != nil { + return err + } + + databasePath, err := i.ExtractDatabase(buildDir, request.FromIndex, request.CaFile, request.SkipTLSVerify, request.PlainHTTP) + if err != nil { + return err + } + + // Run opm registry prune on the database + pruneFromRegistryReq := registry.PruneFromRegistryRequest{ + Packages: request.Packages, + InputDatabase: databasePath, + Permissive: request.Permissive, + } + + // Prune the bundles from the registry + err = i.RegistryPruner.PruneFromRegistry(pruneFromRegistryReq) + if err != nil { + return err + } + + // generate the dockerfile + dockerfile := i.DockerfileGenerator.GenerateIndexDockerfile(request.BinarySourceImage, databasePath) + err = write(dockerfile, outDockerfile, i.Logger) + if err != nil { + return err + } + + if request.Generate { + return nil + } + + // build the dockerfile + err = build(outDockerfile, request.Tag, i.CommandRunner, i.Logger) + if err != nil { + return err + } + + return nil +} + +// ExtractDatabase sets a temp directory for unpacking an image +func (i ImageIndexer) ExtractDatabase(buildDir, fromIndex, caFile string, skipTLSVerify, plainHTTP bool) (string, error) { + tmpDir, err := os.MkdirTemp("./", tmpDirPrefix) + if err != nil { + return "", err + } + defer os.RemoveAll(tmpDir) + + databaseFile, err := i.getDatabaseFile(tmpDir, fromIndex, caFile, skipTLSVerify, plainHTTP) + if err != nil { + return "", err + } + // copy the index to the database folder in the build directory + return copyDatabaseTo(databaseFile, filepath.Join(buildDir, defaultDatabaseFolder)) +} + +func (i ImageIndexer) getDatabaseFile(workingDir, fromIndex, caFile string, skipTLSVerify, plainHTTP bool) (string, error) { + if fromIndex == "" { + return path.Join(workingDir, defaultDatabaseFile), nil + } + + // Pull the fromIndex + i.Logger.Infof("Pulling previous image %s to get metadata", fromIndex) + + var reg image.Registry + var rerr error + switch i.PullTool { + case containertools.NoneTool: + rootCAs, err := certs.RootCAs(caFile) + if err != nil { + return "", fmt.Errorf("failed to get RootCAs: %v", err) + } + reg, rerr = containerdregistry.NewRegistry( + containerdregistry.SkipTLSVerify(skipTLSVerify), + containerdregistry.WithPlainHTTP(plainHTTP), + containerdregistry.WithLog(i.Logger), + containerdregistry.WithRootCAs(rootCAs)) + case containertools.PodmanTool: + fallthrough + case containertools.DockerTool: + reg, rerr = execregistry.NewRegistry(i.PullTool, i.Logger, containertools.SkipTLS(plainHTTP)) + } + if rerr != nil { + return "", rerr + } + defer func() { + if err := reg.Destroy(); err != nil { + i.Logger.WithError(err).Warn("error destroying local cache") + } + }() + + imageRef := image.SimpleReference(fromIndex) + + if err := reg.Pull(context.TODO(), imageRef); err != nil { + return "", err + } + + // Get the old index image's dbLocationLabel to find this path + labels, err := reg.Labels(context.TODO(), imageRef) + if err != nil { + return "", err + } + + dbLocation, ok := labels[containertools.DbLocationLabel] + if !ok { + if _, ok := labels[containertools.ConfigsLocationLabel]; ok { + return "", ErrFileBasedCatalogPrune + } + return "", fmt.Errorf("index image %s missing label %s", fromIndex, containertools.DbLocationLabel) + } + + if err := reg.Unpack(context.TODO(), imageRef, workingDir); err != nil { + return "", err + } + + return path.Join(workingDir, dbLocation), nil +} + +func copyDatabaseTo(databaseFile, targetDir string) (string, error) { + // create the containing folder if it doesn't exist + if _, err := os.Stat(targetDir); os.IsNotExist(err) { + if err := os.MkdirAll(targetDir, 0777); err != nil { + return "", err + } + } else if err != nil { + return "", err + } + + // Open the database file in the working dir + from, err := os.OpenFile(databaseFile, os.O_RDWR|os.O_CREATE, 0666) + if err != nil { + return "", err + } + defer from.Close() + + dbFile := path.Join(targetDir, defaultDatabaseFile) + + // define the path to copy to the database/index.db file + to, err := os.OpenFile(dbFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) + if err != nil { + return "", err + } + defer to.Close() + + // copy to the destination directory + _, err = io.Copy(to, from) + return to.Name(), err +} + +func buildContext(generate bool, requestedDockerfile string) (buildDir, outDockerfile string, cleanup func(), err error) { + // set cleanup to a no-op until explicitly set + cleanup = func() {} + + if generate { + buildDir = "./" + if len(requestedDockerfile) == 0 { + outDockerfile = defaultDockerfileName + } else { + outDockerfile = requestedDockerfile + } + cleanup = func() {} + return + } + + // set a temp directory for building the new image + buildDir, err = os.MkdirTemp(".", tmpBuildDirPrefix) + if err != nil { + return + } + cleanup = func() { + os.RemoveAll(buildDir) + } + + if len(requestedDockerfile) > 0 { + outDockerfile = requestedDockerfile + return + } + + // generate a temp dockerfile if needed + tempDockerfile, err := os.CreateTemp(".", defaultDockerfileName) + if err != nil { + defer cleanup() + return + } + outDockerfile = tempDockerfile.Name() + cleanup = func() { + os.RemoveAll(buildDir) + os.Remove(outDockerfile) + } + + return +} + +func build(dockerfilePath, imageTag string, commandRunner containertools.CommandRunner, logger *logrus.Entry) error { + if imageTag == "" { + imageTag = defaultImageTag + } + + logger.Debugf("building container image: %s", imageTag) + + err := commandRunner.Build(dockerfilePath, imageTag) + if err != nil { + return err + } + + return nil +} + +func write(dockerfileText, outDockerfile string, logger *logrus.Entry) error { + if outDockerfile == "" { + outDockerfile = defaultDockerfileName + } + + logger.Infof("writing dockerfile: %s", outDockerfile) + + f, err := os.Create(outDockerfile) + if err != nil { + return err + } + + _, err = f.WriteString(dockerfileText) + if err != nil { + return err + } + + return nil +} + +// ExportFromIndexRequest defines the parameters to send to the ExportFromIndex API +type ExportFromIndexRequest struct { + Index string + Packages []string + DownloadPath string + ContainerTool containertools.ContainerTool + CaFile string + SkipTLSVerify bool + PlainHTTP bool +} + +// ExportFromIndex is an aggregate API used to specify operators from +// an index image +func (i ImageIndexer) ExportFromIndex(request ExportFromIndexRequest) error { + // set a temp directory + workingDir, err := os.MkdirTemp("./", tmpDirPrefix) + if err != nil { + return err + } + defer os.RemoveAll(workingDir) + + // extract the index database to the file + databaseFile, err := i.getDatabaseFile(workingDir, request.Index, request.CaFile, request.SkipTLSVerify, request.PlainHTTP) + if err != nil { + return err + } + + db, err := sqlite.Open(databaseFile) + if err != nil { + return err + } + defer db.Close() + + dbQuerier := sqlite.NewSQLLiteQuerierFromDb(db) + + // fetch all packages from the index image if packages is empty + if len(request.Packages) == 0 { + request.Packages, err = dbQuerier.ListPackages(context.TODO()) + if err != nil { + return err + } + } + + bundles, err := getBundlesToExport(dbQuerier, request.Packages) + if err != nil { + return err + } + + i.Logger.Infof("Preparing to pull bundles %+q", bundles) + + // Creating downloadPath dir + if err := os.MkdirAll(request.DownloadPath, 0777); err != nil { + return err + } + + var errs []error + var wg sync.WaitGroup + wg.Add(len(bundles)) + var mu = &sync.Mutex{} + + sem := make(chan struct{}, concurrencyLimitForExport) + + for bundleImage, bundleDir := range bundles { + go func(bundleImage string, bundleDir bundleDirPrefix) { + defer wg.Done() + + sem <- struct{}{} + defer func() { + <-sem + }() + + // generate a random folder name if bundle version is empty + if bundleDir.bundleVersion == "" { + bundleDir.bundleVersion = strconv.Itoa(rand.Intn(10000)) + } + exporter := bundle.NewExporterForBundle(bundleImage, filepath.Join(request.DownloadPath, bundleDir.pkgName, bundleDir.bundleVersion), request.ContainerTool) + if err := exporter.Export(request.SkipTLSVerify, request.PlainHTTP); err != nil { + err = fmt.Errorf("exporting bundle image:%s failed with %s", bundleImage, err) + mu.Lock() + errs = append(errs, err) + mu.Unlock() + } + }(bundleImage, bundleDir) + } + // Wait for all the go routines to finish export + wg.Wait() + + if errs != nil { + return utilerrors.NewAggregate(errs) + } + + for _, packageName := range request.Packages { + err := generatePackageYaml(dbQuerier, packageName, filepath.Join(request.DownloadPath, packageName)) + if err != nil { + errs = append(errs, err) + } + } + return utilerrors.NewAggregate(errs) +} + +type bundleDirPrefix struct { + pkgName, bundleVersion string +} + +func getBundlesToExport(dbQuerier pregistry.Query, packages []string) (map[string]bundleDirPrefix, error) { + bundleMap := make(map[string]bundleDirPrefix) + + for _, packageName := range packages { + bundlesForPackage, err := dbQuerier.GetBundlesForPackage(context.TODO(), packageName) + if err != nil { + return nil, err + } + for k, _ := range bundlesForPackage { + bundleMap[k.BundlePath] = bundleDirPrefix{pkgName: packageName, bundleVersion: k.Version} + } + } + + return bundleMap, nil +} + +func generatePackageYaml(dbQuerier pregistry.Query, packageName, downloadPath string) error { + var errs []error + + defaultChannel, err := dbQuerier.GetDefaultChannelForPackage(context.TODO(), packageName) + if err != nil { + return err + } + + channelList, err := dbQuerier.ListChannels(context.TODO(), packageName) + if err != nil { + return err + } + + channels := []pregistry.PackageChannel{} + for _, ch := range channelList { + csvName, err := dbQuerier.GetCurrentCSVNameForChannel(context.TODO(), packageName, ch) + if err != nil { + err = fmt.Errorf("error exporting bundle from image: %s", err) + errs = append(errs, err) + continue + } + channels = append(channels, + pregistry.PackageChannel{ + Name: ch, + CurrentCSVName: csvName, + }) + } + + manifest := pregistry.PackageManifest{ + PackageName: packageName, + DefaultChannelName: defaultChannel, + Channels: channels, + } + + manifestBytes, err := yaml.Marshal(&manifest) + if err != nil { + errs = append(errs, err) + return utilerrors.NewAggregate(errs) + } + + err = bundle.WriteFile("package.yaml", downloadPath, manifestBytes) + if err != nil { + errs = append(errs, err) + } + + return utilerrors.NewAggregate(errs) +} + +// DeprecateFromIndexRequest defines the parameters to send to the PruneFromIndex API +type DeprecateFromIndexRequest struct { + Generate bool + Permissive bool + BinarySourceImage string + FromIndex string + OutDockerfile string + Bundles []string + Tag string + CaFile string + SkipTLSVerify bool + PlainHTTP bool + AllowPackageRemoval bool +} + +// DeprecateFromIndex takes a DeprecateFromIndexRequest and deprecates the requested +// bundles. +func (i ImageIndexer) DeprecateFromIndex(request DeprecateFromIndexRequest) error { + buildDir, outDockerfile, cleanup, err := buildContext(request.Generate, request.OutDockerfile) + defer cleanup() + if err != nil { + return err + } + + databasePath, err := i.ExtractDatabase(buildDir, request.FromIndex, request.CaFile, request.SkipTLSVerify, request.PlainHTTP) + if err != nil { + return err + } + + deprecateFromRegistryReq := registry.DeprecateFromRegistryRequest{ + Bundles: request.Bundles, + InputDatabase: databasePath, + Permissive: request.Permissive, + AllowPackageRemoval: request.AllowPackageRemoval, + } + + // Deprecate the bundles from the registry + err = i.RegistryDeprecator.DeprecateFromRegistry(deprecateFromRegistryReq) + if err != nil { + return err + } + + // generate the dockerfile + dockerfile := i.DockerfileGenerator.GenerateIndexDockerfile(request.BinarySourceImage, databasePath) + err = write(dockerfile, outDockerfile, i.Logger) + if err != nil { + return err + } + + if request.Generate { + return nil + } + + // build the dockerfile with requested tooling + err = build(outDockerfile, request.Tag, i.CommandRunner, i.Logger) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/lib/indexer/interfaces.go b/vendor/github.com/operator-framework/operator-registry/pkg/lib/indexer/interfaces.go new file mode 100644 index 0000000000..5ebefdd1e3 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/lib/indexer/interfaces.go @@ -0,0 +1,118 @@ +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate +package indexer + +import ( + "github.com/operator-framework/operator-registry/pkg/containertools" + "github.com/operator-framework/operator-registry/pkg/lib/registry" + "github.com/sirupsen/logrus" +) + +// IndexAdder allows the creation of index container images from scratch or +// based on previous index images +// +//counterfeiter:generate . IndexAdder +type IndexAdder interface { + AddToIndex(AddToIndexRequest) error +} + +// NewIndexAdder is a constructor that returns an IndexAdder +func NewIndexAdder(buildTool, pullTool containertools.ContainerTool, logger *logrus.Entry) IndexAdder { + return ImageIndexer{ + DockerfileGenerator: containertools.NewDockerfileGenerator(logger), + CommandRunner: containertools.NewCommandRunner(buildTool, logger), + LabelReader: containertools.NewLabelReader(pullTool, logger), + RegistryAdder: registry.NewRegistryAdder(logger), + BuildTool: buildTool, + PullTool: pullTool, + Logger: logger, + } +} + +// IndexDeleter takes indexes and deletes all references to an operator +// from them +// +//counterfeiter:generate . IndexDeleter +type IndexDeleter interface { + DeleteFromIndex(DeleteFromIndexRequest) error +} + +// NewIndexDeleter is a constructor that returns an IndexDeleter +func NewIndexDeleter(buildTool, pullTool containertools.ContainerTool, logger *logrus.Entry) IndexDeleter { + return ImageIndexer{ + DockerfileGenerator: containertools.NewDockerfileGenerator(logger), + CommandRunner: containertools.NewCommandRunner(buildTool, logger), + LabelReader: containertools.NewLabelReader(pullTool, logger), + RegistryDeleter: registry.NewRegistryDeleter(logger), + BuildTool: buildTool, + PullTool: pullTool, + Logger: logger, + } +} + +//counterfeiter:generate . IndexExporter +type IndexExporter interface { + ExportFromIndex(ExportFromIndexRequest) error +} + +// NewIndexExporter is a constructor that returns an IndexExporter +func NewIndexExporter(containerTool containertools.ContainerTool, logger *logrus.Entry) IndexExporter { + return ImageIndexer{ + DockerfileGenerator: containertools.NewDockerfileGenerator(logger), + CommandRunner: containertools.NewCommandRunner(containerTool, logger), + LabelReader: containertools.NewLabelReader(containerTool, logger), + BuildTool: containerTool, + PullTool: containerTool, + Logger: logger, + } +} + +// IndexStrandedPruner prunes operators out of an index +type IndexStrandedPruner interface { + PruneStrandedFromIndex(PruneStrandedFromIndexRequest) error +} + +func NewIndexStrandedPruner(containerTool containertools.ContainerTool, logger *logrus.Entry) IndexStrandedPruner { + return ImageIndexer{ + DockerfileGenerator: containertools.NewDockerfileGenerator(logger), + CommandRunner: containertools.NewCommandRunner(containerTool, logger), + LabelReader: containertools.NewLabelReader(containerTool, logger), + RegistryStrandedPruner: registry.NewRegistryStrandedPruner(logger), + BuildTool: containerTool, + PullTool: containerTool, + Logger: logger, + } +} + +// IndexPruner prunes operators out of an index +type IndexPruner interface { + PruneFromIndex(PruneFromIndexRequest) error +} + +func NewIndexPruner(containerTool containertools.ContainerTool, logger *logrus.Entry) IndexPruner { + return ImageIndexer{ + DockerfileGenerator: containertools.NewDockerfileGenerator(logger), + CommandRunner: containertools.NewCommandRunner(containerTool, logger), + LabelReader: containertools.NewLabelReader(containerTool, logger), + RegistryPruner: registry.NewRegistryPruner(logger), + BuildTool: containerTool, + PullTool: containerTool, + Logger: logger, + } +} + +// IndexDeprecator prunes operators out of an index +type IndexDeprecator interface { + DeprecateFromIndex(DeprecateFromIndexRequest) error +} + +func NewIndexDeprecator(buildTool, pullTool containertools.ContainerTool, logger *logrus.Entry) IndexDeprecator { + return ImageIndexer{ + DockerfileGenerator: containertools.NewDockerfileGenerator(logger), + CommandRunner: containertools.NewCommandRunner(buildTool, logger), + LabelReader: containertools.NewLabelReader(pullTool, logger), + RegistryDeprecator: registry.NewRegistryDeprecator(logger), + BuildTool: buildTool, + PullTool: pullTool, + Logger: logger, + } +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/lib/log/null.go b/vendor/github.com/operator-framework/operator-registry/pkg/lib/log/null.go new file mode 100644 index 0000000000..9b7886c0c7 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/lib/log/null.go @@ -0,0 +1,13 @@ +package log + +import ( + "io" + + "github.com/sirupsen/logrus" +) + +func Null() *logrus.Entry { + l := logrus.New() + l.SetOutput(io.Discard) + return logrus.NewEntry(l) +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/lib/log/writerhook.go b/vendor/github.com/operator-framework/operator-registry/pkg/lib/log/writerhook.go new file mode 100644 index 0000000000..a67dc675f2 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/lib/log/writerhook.go @@ -0,0 +1,76 @@ +package log + +import ( + "io" + "os" + + "github.com/sirupsen/logrus" +) + +// Taken from https://github.com/sirupsen/logrus/issues/678 +// Used to split log level output until this is implemented internally by logrus + +// WriterHook is a hook that writes logs of specified LogLevels to specified Writer +type WriterHook struct { + Writer io.Writer + LogLevels []logrus.Level +} + +// Fire will be called when some logging function is called with current hook +// It will format log entry to string and write it to appropriate writer +func (hook *WriterHook) Fire(entry *logrus.Entry) error { + line, err := entry.String() + if err != nil { + return err + } + _, err = hook.Writer.Write([]byte(line)) + return err +} + +// Levels define on which log levels this hook would trigger +func (hook *WriterHook) Levels() []logrus.Level { + return hook.LogLevels +} + +// AddHooks adds hooks to send logs to different destinations depending on level +func AddHooks(hooks ...*WriterHook) { + // Send all logs to nowhere by default + logrus.SetOutput(io.Discard) + + for _, hook := range hooks { + logrus.AddHook(hook) + } +} + +func AddDefaultWriterHooks(terminationLogPath string) error { + terminationLogFile, err := os.OpenFile(terminationLogPath, os.O_WRONLY|os.O_CREATE, 0644) + if err != nil { + return err + } + AddHooks( + &WriterHook{ + Writer: terminationLogFile, + LogLevels: []logrus.Level{ + logrus.PanicLevel, + logrus.FatalLevel, + }, + }, + &WriterHook{ + Writer: os.Stderr, + LogLevels: []logrus.Level{ + logrus.PanicLevel, + logrus.FatalLevel, + logrus.ErrorLevel, + logrus.WarnLevel, + }, + }, + &WriterHook{ + Writer: os.Stdout, + LogLevels: []logrus.Level{ + logrus.InfoLevel, + logrus.DebugLevel, + }, + }) + + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/lib/registry/interfaces.go b/vendor/github.com/operator-framework/operator-registry/pkg/lib/registry/interfaces.go new file mode 100644 index 0000000000..f392d16e3a --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/lib/registry/interfaces.go @@ -0,0 +1,58 @@ +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate +package registry + +import ( + "github.com/sirupsen/logrus" +) + +//counterfeiter:generate . RegistryAdder +type RegistryAdder interface { + AddToRegistry(AddToRegistryRequest) error +} + +func NewRegistryAdder(logger *logrus.Entry) RegistryAdder { + return RegistryUpdater{ + Logger: logger, + } +} + +//counterfeiter:generate . RegistryDeleter +type RegistryDeleter interface { + DeleteFromRegistry(DeleteFromRegistryRequest) error +} + +func NewRegistryDeleter(logger *logrus.Entry) RegistryDeleter { + return RegistryUpdater{ + Logger: logger, + } +} + +type RegistryStrandedPruner interface { + PruneStrandedFromRegistry(PruneStrandedFromRegistryRequest) error +} + +func NewRegistryStrandedPruner(logger *logrus.Entry) RegistryStrandedPruner { + return RegistryUpdater{ + Logger: logger, + } +} + +type RegistryPruner interface { + PruneFromRegistry(PruneFromRegistryRequest) error +} + +func NewRegistryPruner(logger *logrus.Entry) RegistryPruner { + return RegistryUpdater{ + Logger: logger, + } +} + +type RegistryDeprecator interface { + DeprecateFromRegistry(DeprecateFromRegistryRequest) error +} + +func NewRegistryDeprecator(logger *logrus.Entry) RegistryDeprecator { + return RegistryUpdater{ + Logger: logger, + } +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/lib/registry/registry.go b/vendor/github.com/operator-framework/operator-registry/pkg/lib/registry/registry.go new file mode 100644 index 0000000000..a4174197b9 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/lib/registry/registry.go @@ -0,0 +1,459 @@ +package registry + +import ( + "context" + "fmt" + "os" + + "github.com/sirupsen/logrus" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + + "github.com/operator-framework/operator-registry/pkg/containertools" + "github.com/operator-framework/operator-registry/pkg/image" + "github.com/operator-framework/operator-registry/pkg/image/containerdregistry" + "github.com/operator-framework/operator-registry/pkg/image/execregistry" + "github.com/operator-framework/operator-registry/pkg/lib/certs" + "github.com/operator-framework/operator-registry/pkg/registry" + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +type RegistryUpdater struct { + Logger *logrus.Entry +} + +type AddToRegistryRequest struct { + Permissive bool + SkipTLSVerify bool + PlainHTTP bool + CaFile string + InputDatabase string + Bundles []string + Mode registry.Mode + ContainerTool containertools.ContainerTool + Overwrite bool + EnableAlpha bool +} + +func (r RegistryUpdater) AddToRegistry(request AddToRegistryRequest) error { + db, err := sqlite.Open(request.InputDatabase) + if err != nil { + return err + } + defer db.Close() + + dbLoader, err := sqlite.NewSQLLiteLoader(db, sqlite.WithEnableAlpha(request.EnableAlpha)) + if err != nil { + return err + } + + if err := dbLoader.Migrate(context.TODO()); err != nil { + return err + } + + graphLoader, err := sqlite.NewSQLGraphLoaderFromDB(db) + if err != nil { + return err + } + dbQuerier := sqlite.NewSQLLiteQuerierFromDb(db) + + // add custom ca certs to resolver + + var reg image.Registry + var rerr error + switch request.ContainerTool { + case containertools.NoneTool: + rootCAs, err := certs.RootCAs(request.CaFile) + if err != nil { + return fmt.Errorf("failed to get RootCAs: %v", err) + } + reg, rerr = containerdregistry.NewRegistry( + containerdregistry.SkipTLSVerify(request.SkipTLSVerify), + containerdregistry.WithPlainHTTP(request.PlainHTTP), + containerdregistry.WithRootCAs(rootCAs), + ) + case containertools.PodmanTool: + fallthrough + case containertools.DockerTool: + reg, rerr = execregistry.NewRegistry(request.ContainerTool, r.Logger, containertools.SkipTLS(request.PlainHTTP)) + } + if rerr != nil { + return rerr + } + defer func() { + if err := reg.Destroy(); err != nil { + r.Logger.WithError(err).Warn("error destroying local cache") + } + }() + + simpleRefs := make([]image.Reference, 0) + for _, ref := range request.Bundles { + simpleRefs = append(simpleRefs, image.SimpleReference(ref)) + } + + if err := populate(context.TODO(), dbLoader, graphLoader, dbQuerier, reg, simpleRefs, request.Mode, request.Overwrite); err != nil { + r.Logger.Debugf("unable to populate database: %s", err) + + if !request.Permissive { + r.Logger.WithError(err).Error("permissive mode disabled") + return err + } + r.Logger.WithError(err).Warn("permissive mode enabled") + } + + return nil +} + +func unpackImage(ctx context.Context, reg image.Registry, ref image.Reference) (image.Reference, string, func(), error) { + var errs []error + workingDir, err := os.MkdirTemp("./", "bundle_tmp") + if err != nil { + errs = append(errs, err) + } + + if err = reg.Pull(ctx, ref); err != nil { + errs = append(errs, err) + } + + if err = reg.Unpack(ctx, ref, workingDir); err != nil { + errs = append(errs, err) + } + + cleanup := func() { + if err := os.RemoveAll(workingDir); err != nil { + logrus.Error(err) + } + } + + if len(errs) > 0 { + return nil, "", cleanup, utilerrors.NewAggregate(errs) + } + return ref, workingDir, cleanup, nil +} + +func populate(ctx context.Context, loader registry.Load, graphLoader registry.GraphLoader, querier registry.Query, reg image.Registry, refs []image.Reference, mode registry.Mode, overwrite bool) error { + unpackedImageMap := make(map[image.Reference]string, 0) + overwrittenBundles := map[string][]string{} + var imagesToAdd []*registry.Bundle + for _, ref := range refs { + to, from, cleanup, err := unpackImage(ctx, reg, ref) + if err != nil { + return err + } + unpackedImageMap[to] = from + defer cleanup() + + img, err := registry.NewImageInput(to, from) + if err != nil { + return err + } + imagesToAdd = append(imagesToAdd, img.Bundle) + + if overwrite { + overwritten, err := querier.GetBundlePathIfExists(ctx, img.Bundle.Name) + if err != nil { + if err == registry.ErrBundleImageNotInDatabase { + continue + } + return err + } + if overwritten == "" { + return fmt.Errorf("index add --overwrite-latest is only supported when using bundle images") + } + overwrittenBundles[img.Bundle.Package] = append(overwrittenBundles[img.Bundle.Package], img.Bundle.Name) + } + } + + populator := registry.NewDirectoryPopulator(loader, graphLoader, querier, unpackedImageMap, overwrittenBundles) + + if err := populator.Populate(mode); err != nil { + + return err + + } + return checkForBundles(ctx, querier.(*sqlite.SQLQuerier), graphLoader, imagesToAdd) +} + +type DeleteFromRegistryRequest struct { + Permissive bool + InputDatabase string + Packages []string +} + +func (r RegistryUpdater) DeleteFromRegistry(request DeleteFromRegistryRequest) error { + db, err := sqlite.Open(request.InputDatabase) + if err != nil { + return err + } + defer db.Close() + + dbLoader, err := sqlite.NewDeprecationAwareLoader(db) + if err != nil { + return err + } + if err := dbLoader.Migrate(context.TODO()); err != nil { + return err + } + + for _, pkg := range request.Packages { + remover := sqlite.NewSQLRemoverForPackages(dbLoader, pkg) + if err := remover.Remove(); err != nil { + err = fmt.Errorf("error deleting packages from database: %s", err) + if !request.Permissive { + logrus.WithError(err).Fatal("permissive mode disabled") + return err + } + logrus.WithError(err).Warn("permissive mode enabled") + } + } + + // remove any stranded bundles from the database + // TODO: This is unnecessary if the db schema can prevent this orphaned data from existing + remover := sqlite.NewSQLStrandedBundleRemover(dbLoader) + if err := remover.Remove(); err != nil { + return fmt.Errorf("error removing stranded packages from database: %s", err) + } + + if _, err := db.Exec("VACUUM"); err != nil { + return err + } + return nil +} + +type PruneStrandedFromRegistryRequest struct { + InputDatabase string +} + +func (r RegistryUpdater) PruneStrandedFromRegistry(request PruneStrandedFromRegistryRequest) error { + db, err := sqlite.Open(request.InputDatabase) + if err != nil { + return err + } + defer db.Close() + + dbLoader, err := sqlite.NewSQLLiteLoader(db) + if err != nil { + return err + } + if err := dbLoader.Migrate(context.TODO()); err != nil { + return err + } + + remover := sqlite.NewSQLStrandedBundleRemover(dbLoader) + if err := remover.Remove(); err != nil { + return fmt.Errorf("error removing stranded packages from database: %s", err) + } + + if _, err := db.Exec("VACUUM"); err != nil { + return err + } + return nil +} + +type PruneFromRegistryRequest struct { + Permissive bool + InputDatabase string + Packages []string +} + +func (r RegistryUpdater) PruneFromRegistry(request PruneFromRegistryRequest) error { + db, err := sqlite.Open(request.InputDatabase) + if err != nil { + return err + } + defer db.Close() + + dbLoader, err := sqlite.NewDeprecationAwareLoader(db) + if err != nil { + return err + } + if err := dbLoader.Migrate(context.TODO()); err != nil { + return err + } + + // get all the packages + lister := sqlite.NewSQLLiteQuerierFromDb(db) + packages, err := lister.ListPackages(context.TODO()) + if err != nil { + return err + } + + // make it inexpensive to find packages + pkgMap := make(map[string]bool) + for _, pkg := range request.Packages { + pkgMap[pkg] = true + } + + // prune packages from registry + for _, pkg := range packages { + if _, found := pkgMap[pkg]; !found { + remover := sqlite.NewSQLRemoverForPackages(dbLoader, pkg) + if err := remover.Remove(); err != nil { + err = fmt.Errorf("error deleting packages from database: %s", err) + if !request.Permissive { + logrus.WithError(err).Fatal("permissive mode disabled") + return err + } + logrus.WithError(err).Warn("permissive mode enabled") + } + } + } + + if _, err := db.Exec("VACUUM"); err != nil { + return err + } + return nil +} + +type DeprecateFromRegistryRequest struct { + Permissive bool + InputDatabase string + Bundles []string + AllowPackageRemoval bool +} + +func (r RegistryUpdater) DeprecateFromRegistry(request DeprecateFromRegistryRequest) error { + db, err := sqlite.Open(request.InputDatabase) + if err != nil { + return err + } + defer db.Close() + + dbLoader, err := sqlite.NewDeprecationAwareLoader(db) + if err != nil { + return err + } + if err := dbLoader.Migrate(context.TODO()); err != nil { + return fmt.Errorf("unable to migrate database: %s", err) + } + + // Check if all bundlepaths are valid + var toDeprecate []string + + dbQuerier := sqlite.NewSQLLiteQuerierFromDb(db) + + toDeprecate, _, err = checkForBundlePaths(dbQuerier, request.Bundles) + if err != nil { + if !request.Permissive { + r.Logger.WithError(err).Error("permissive mode disabled") + return err + } + r.Logger.WithError(err).Warn("permissive mode enabled") + } + + deprecator := sqlite.NewSQLDeprecatorForBundles(dbLoader, toDeprecate) + + // Check for deprecation of head of default channel. If deprecation request includes heads of all other channels, + // then remove the package entirely. Otherwise, deprecate provided bundles. This enables deprecating an entire package. + // By default deprecating the head of default channel is not permitted. + if request.AllowPackageRemoval { + packageDeprecator := sqlite.NewSQLDeprecatorForBundlesAndPackages(deprecator, dbQuerier) + if err := packageDeprecator.MaybeRemovePackages(); err != nil { + r.Logger.Debugf("unable to deprecate package from database: %s", err) + if !request.Permissive { + r.Logger.WithError(err).Error("permissive mode disabled") + return err + } + r.Logger.WithError(err).Warn("permissive mode enabled") + } + } + + // Any bundles associated with removed packages are now removed from the list of bundles to deprecate. + if err := deprecator.Deprecate(); err != nil { + r.Logger.Debugf("unable to deprecate bundles from database: %s", err) + if !request.Permissive { + r.Logger.WithError(err).Error("permissive mode disabled") + return err + } + r.Logger.WithError(err).Warn("permissive mode enabled") + } + + if _, err := db.Exec("VACUUM"); err != nil { + return err + } + return nil +} + +// checkForBundlePaths verifies presence of a list of bundle paths in the registry. +func checkForBundlePaths(querier registry.GRPCQuery, bundlePaths []string) ([]string, []string, error) { + if len(bundlePaths) == 0 { + return bundlePaths, nil, nil + } + + registryBundles, err := querier.ListBundles(context.TODO()) + if err != nil { + return bundlePaths, nil, err + } + + if len(registryBundles) == 0 { + return nil, bundlePaths, nil + } + + registryBundlePaths := map[string]struct{}{} + for _, b := range registryBundles { + registryBundlePaths[b.BundlePath] = struct{}{} + } + + var found, missing []string + for _, b := range bundlePaths { + if _, ok := registryBundlePaths[b]; ok { + found = append(found, b) + continue + } + missing = append(missing, b) + } + if len(missing) > 0 { + return found, missing, fmt.Errorf("target bundlepaths for deprecation missing from registry: %v", missing) + } + return found, missing, nil +} + +// replaces mode selects highest version as channel head and +// prunes any bundles in the upgrade chain after the channel head. +// check for the presence of newly added bundles after a replaces-mode add. +func checkForBundles(ctx context.Context, q *sqlite.SQLQuerier, g registry.GraphLoader, required []*registry.Bundle) error { + var errs []error + for _, bundle := range required { + graph, err := g.Generate(bundle.Package) + if err != nil { + errs = append(errs, fmt.Errorf("unable to verify added bundles for package %s: %v", bundle.Package, err)) + continue + } + + for _, channel := range bundle.Channels { + var foundImage bool + for next := []registry.BundleKey{graph.Channels[channel].Head}; len(next) > 0; next = next[1:] { + if next[0].BundlePath == bundle.BundleImage { + foundImage = true + break + } + for edge := range graph.Channels[channel].Nodes[next[0]] { + next = append(next, edge) + } + } + + if foundImage { + continue + } + + var headSkips []string + for b := range graph.Channels[channel].Nodes[graph.Channels[channel].Head] { + headSkips = append(headSkips, b.CsvName) + } + errs = append(errs, fmt.Errorf("add prunes bundle %s (%s) from package %s, channel %s: this may be "+ + "due to incorrect channel head (%s, skips/replaces %v). "+ + "Be aware that the head of the channel %s where you are trying to add the %s is %s. "+ + "Upgrade graphs follows the Semantic Versioning 2.0.0 (https://semver.org/) which means that "+ + "is not possible add new versions lower then the head of the channel", + bundle.Name, + bundle.BundleImage, + bundle.Package, + channel, + graph.Channels[channel].Head.CsvName, + headSkips, + channel, + bundle.Name, + graph.Channels[channel].Head.CsvName)) + } + } + return utilerrors.NewAggregate(errs) +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/lib/tmp/copy.go b/vendor/github.com/operator-framework/operator-registry/pkg/lib/tmp/copy.go new file mode 100644 index 0000000000..a48a3e219b --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/lib/tmp/copy.go @@ -0,0 +1,53 @@ +package tmp + +import ( + "fmt" + "io" + "os" +) + +// CopyTmpDB reads the file at the given path and copies it to a tmp directory, returning the copied file path or an err +func CopyTmpDB(original string) (path string, err error) { + dst, err := os.CreateTemp("", "db-") + if err != nil { + return "", err + } + defer func() { + if cerr := dst.Close(); cerr != nil && err == nil { + err = cerr + } + }() + + src, err := OpenRegularFile(original) + if err != nil { + return "", err + } + defer func() { + if cerr := src.Close(); cerr != nil && err == nil { + err = cerr + } + }() + + _, err = io.Copy(dst, src) + if err != nil { + return "", err + } + + return dst.Name(), nil +} + +// OpenRegularFile opens the file at path and returns an error if it is not regular, does not exist, or cannot be opened +func OpenRegularFile(path string) (*os.File, error) { + fd, err := os.Open(path) + if err != nil { + return nil, err + } + fi, err := fd.Stat() + if err != nil { + return nil, err + } + if !fi.Mode().IsRegular() { + return nil, fmt.Errorf("%s is not a regular file", path) + } + return fd, nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/mirror/mirror.go b/vendor/github.com/operator-framework/operator-registry/pkg/mirror/mirror.go new file mode 100644 index 0000000000..7d539aa1ec --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/mirror/mirror.go @@ -0,0 +1,111 @@ +package mirror + +import ( + "context" + "fmt" + "strings" + + "github.com/distribution/reference" + "k8s.io/apimachinery/pkg/util/errors" + + "github.com/operator-framework/operator-registry/pkg/sqlite" +) + +type Mirrorer interface { + Mirror() (map[string]string, error) +} + +// DatabaseExtractor knows how to pull an index image and extract its database +type DatabaseExtractor interface { + Extract(from string) (string, error) +} + +type DatabaseExtractorFunc func(from string) (string, error) + +func (f DatabaseExtractorFunc) Extract(from string) (string, error) { + return f(from) +} + +// ImageMirrorer knows how to mirror an image from one registry to another +type ImageMirrorer interface { + Mirror(mapping map[string]string) error +} + +type ImageMirrorerFunc func(mapping map[string]string) error + +func (f ImageMirrorerFunc) Mirror(mapping map[string]string) error { + return f(mapping) +} + +type IndexImageMirrorer struct { + ImageMirrorer ImageMirrorer + DatabaseExtractor DatabaseExtractor + + // options + Source, Dest string +} + +var _ Mirrorer = &IndexImageMirrorer{} + +func NewIndexImageMirror(options ...ImageIndexMirrorOption) (*IndexImageMirrorer, error) { + config := DefaultImageIndexMirrorerOptions() + config.Apply(options) + if err := config.Complete(); err != nil { + return nil, err + } + if err := config.Validate(); err != nil { + return nil, err + } + return &IndexImageMirrorer{ + ImageMirrorer: config.ImageMirrorer, + DatabaseExtractor: config.DatabaseExtractor, + Source: config.Source, + Dest: config.Dest, + }, nil +} + +func (b *IndexImageMirrorer) Mirror() (map[string]string, error) { + dbPath, err := b.DatabaseExtractor.Extract(b.Source) + if err != nil { + return nil, err + } + + db, err := sqlite.Open(dbPath) + if err != nil { + return nil, err + } + defer db.Close() + + migrator, err := sqlite.NewSQLLiteMigrator(db) + if err != nil { + return nil, err + } + if err := migrator.Migrate(context.TODO()); err != nil { + return nil, err + } + + querier := sqlite.NewSQLLiteQuerierFromDb(db) + images, err := querier.ListImages(context.TODO()) + if err != nil { + return nil, err + } + + mapping := map[string]string{} + + var errs []error + for _, img := range images { + ref, err := reference.ParseNormalizedNamed(img) + if err != nil { + errs = append(errs, fmt.Errorf("couldn't parse image for mirroring (%s), skipping mirror: %s", img, err.Error())) + continue + } + domain := reference.Domain(ref) + mapping[ref.String()] = b.Dest + strings.TrimPrefix(ref.String(), domain) + } + + if err := b.ImageMirrorer.Mirror(mapping); err != nil { + errs = append(errs, fmt.Errorf("mirroring failed: %s", err.Error())) + } + + return mapping, errors.NewAggregate(errs) +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/mirror/options.go b/vendor/github.com/operator-framework/operator-registry/pkg/mirror/options.go new file mode 100644 index 0000000000..c9d3b3d9e8 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/mirror/options.go @@ -0,0 +1,111 @@ +package mirror + +import ( + "fmt" +) + +type IndexImageMirrorerOptions struct { + ImageMirrorer ImageMirrorer + DatabaseExtractor DatabaseExtractor + + Source, Dest string + ManifestDir string +} + +func (o *IndexImageMirrorerOptions) Validate() error { + // TODO: better validation + + if o.ImageMirrorer == nil { + return fmt.Errorf("can't mirror without a mirrorer configured") + } + if o.DatabaseExtractor == nil { + return fmt.Errorf("can't mirror without a database extractor configured") + } + if o.Source == "" { + return fmt.Errorf("source image required") + } + + if o.Dest == "" { + return fmt.Errorf("destination registry required") + } + + if o.ManifestDir == "" { + return fmt.Errorf("must have directory to write manifests to") + } + + return nil +} + +func (o *IndexImageMirrorerOptions) Complete() error { + if o.ManifestDir == "" { + o.ManifestDir = "./manifests" + } + return nil +} + +// Apply sequentially applies the given options to the config. +func (c *IndexImageMirrorerOptions) Apply(options []ImageIndexMirrorOption) { + for _, option := range options { + option(c) + } +} + +// ToOption converts an IndexImageMirrorerOptions object into a function that applies +// its current configuration to another IndexImageMirrorerOptions instance +func (c *IndexImageMirrorerOptions) ToOption() ImageIndexMirrorOption { + return func(o *IndexImageMirrorerOptions) { + if c.ImageMirrorer != nil { + o.ImageMirrorer = c.ImageMirrorer + } + if c.DatabaseExtractor != nil { + o.DatabaseExtractor = c.DatabaseExtractor + } + if c.Source != "" { + o.Source = c.Source + } + if c.Dest != "" { + o.Dest = c.Dest + } + if c.ManifestDir != "" { + o.ManifestDir = c.ManifestDir + } + } +} + +type ImageIndexMirrorOption func(*IndexImageMirrorerOptions) + +func DefaultImageIndexMirrorerOptions() *IndexImageMirrorerOptions { + return &IndexImageMirrorerOptions{ + ManifestDir: "./manifests", + } +} + +func WithMirrorer(i ImageMirrorer) ImageIndexMirrorOption { + return func(o *IndexImageMirrorerOptions) { + o.ImageMirrorer = i + } +} + +func WithExtractor(e DatabaseExtractor) ImageIndexMirrorOption { + return func(o *IndexImageMirrorerOptions) { + o.DatabaseExtractor = e + } +} + +func WithSource(s string) ImageIndexMirrorOption { + return func(o *IndexImageMirrorerOptions) { + o.Source = s + } +} + +func WithDest(d string) ImageIndexMirrorOption { + return func(o *IndexImageMirrorerOptions) { + o.Dest = d + } +} + +func WithManifestDir(d string) ImageIndexMirrorOption { + return func(o *IndexImageMirrorerOptions) { + o.ManifestDir = d + } +} diff --git a/vendor/github.com/russross/blackfriday/v2/.gitignore b/vendor/github.com/russross/blackfriday/v2/.gitignore new file mode 100644 index 0000000000..75623dcccb --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/.gitignore @@ -0,0 +1,8 @@ +*.out +*.swp +*.8 +*.6 +_obj +_test* +markdown +tags diff --git a/vendor/github.com/russross/blackfriday/v2/.travis.yml b/vendor/github.com/russross/blackfriday/v2/.travis.yml new file mode 100644 index 0000000000..b0b525a5a8 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/.travis.yml @@ -0,0 +1,17 @@ +sudo: false +language: go +go: + - "1.10.x" + - "1.11.x" + - tip +matrix: + fast_finish: true + allow_failures: + - go: tip +install: + - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step). +script: + - go get -t -v ./... + - diff -u <(echo -n) <(gofmt -d -s .) + - go tool vet . + - go test -v ./... diff --git a/vendor/github.com/russross/blackfriday/v2/LICENSE.txt b/vendor/github.com/russross/blackfriday/v2/LICENSE.txt new file mode 100644 index 0000000000..2885af3602 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/LICENSE.txt @@ -0,0 +1,29 @@ +Blackfriday is distributed under the Simplified BSD License: + +> Copyright © 2011 Russ Ross +> All rights reserved. +> +> Redistribution and use in source and binary forms, with or without +> modification, are permitted provided that the following conditions +> are met: +> +> 1. Redistributions of source code must retain the above copyright +> notice, this list of conditions and the following disclaimer. +> +> 2. Redistributions in binary form must reproduce the above +> copyright notice, this list of conditions and the following +> disclaimer in the documentation and/or other materials provided with +> the distribution. +> +> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +> "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +> LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +> FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +> COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +> INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +> BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +> LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +> LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +> ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +> POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/russross/blackfriday/v2/README.md b/vendor/github.com/russross/blackfriday/v2/README.md new file mode 100644 index 0000000000..d9c08a22fc --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/README.md @@ -0,0 +1,335 @@ +Blackfriday +[![Build Status][BuildV2SVG]][BuildV2URL] +[![PkgGoDev][PkgGoDevV2SVG]][PkgGoDevV2URL] +=========== + +Blackfriday is a [Markdown][1] processor implemented in [Go][2]. It +is paranoid about its input (so you can safely feed it user-supplied +data), it is fast, it supports common extensions (tables, smart +punctuation substitutions, etc.), and it is safe for all utf-8 +(unicode) input. + +HTML output is currently supported, along with Smartypants +extensions. + +It started as a translation from C of [Sundown][3]. + + +Installation +------------ + +Blackfriday is compatible with modern Go releases in module mode. +With Go installed: + + go get github.com/russross/blackfriday/v2 + +will resolve and add the package to the current development module, +then build and install it. Alternatively, you can achieve the same +if you import it in a package: + + import "github.com/russross/blackfriday/v2" + +and `go get` without parameters. + +Legacy GOPATH mode is unsupported. + + +Versions +-------- + +Currently maintained and recommended version of Blackfriday is `v2`. It's being +developed on its own branch: https://github.com/russross/blackfriday/tree/v2 and the +documentation is available at +https://pkg.go.dev/github.com/russross/blackfriday/v2. + +It is `go get`-able in module mode at `github.com/russross/blackfriday/v2`. + +Version 2 offers a number of improvements over v1: + +* Cleaned up API +* A separate call to [`Parse`][4], which produces an abstract syntax tree for + the document +* Latest bug fixes +* Flexibility to easily add your own rendering extensions + +Potential drawbacks: + +* Our benchmarks show v2 to be slightly slower than v1. Currently in the + ballpark of around 15%. +* API breakage. If you can't afford modifying your code to adhere to the new API + and don't care too much about the new features, v2 is probably not for you. +* Several bug fixes are trailing behind and still need to be forward-ported to + v2. See issue [#348](https://github.com/russross/blackfriday/issues/348) for + tracking. + +If you are still interested in the legacy `v1`, you can import it from +`github.com/russross/blackfriday`. Documentation for the legacy v1 can be found +here: https://pkg.go.dev/github.com/russross/blackfriday. + + +Usage +----- + +For the most sensible markdown processing, it is as simple as getting your input +into a byte slice and calling: + +```go +output := blackfriday.Run(input) +``` + +Your input will be parsed and the output rendered with a set of most popular +extensions enabled. If you want the most basic feature set, corresponding with +the bare Markdown specification, use: + +```go +output := blackfriday.Run(input, blackfriday.WithNoExtensions()) +``` + +### Sanitize untrusted content + +Blackfriday itself does nothing to protect against malicious content. If you are +dealing with user-supplied markdown, we recommend running Blackfriday's output +through HTML sanitizer such as [Bluemonday][5]. + +Here's an example of simple usage of Blackfriday together with Bluemonday: + +```go +import ( + "github.com/microcosm-cc/bluemonday" + "github.com/russross/blackfriday/v2" +) + +// ... +unsafe := blackfriday.Run(input) +html := bluemonday.UGCPolicy().SanitizeBytes(unsafe) +``` + +### Custom options + +If you want to customize the set of options, use `blackfriday.WithExtensions`, +`blackfriday.WithRenderer` and `blackfriday.WithRefOverride`. + +### `blackfriday-tool` + +You can also check out `blackfriday-tool` for a more complete example +of how to use it. Download and install it using: + + go get github.com/russross/blackfriday-tool + +This is a simple command-line tool that allows you to process a +markdown file using a standalone program. You can also browse the +source directly on github if you are just looking for some example +code: + +* + +Note that if you have not already done so, installing +`blackfriday-tool` will be sufficient to download and install +blackfriday in addition to the tool itself. The tool binary will be +installed in `$GOPATH/bin`. This is a statically-linked binary that +can be copied to wherever you need it without worrying about +dependencies and library versions. + +### Sanitized anchor names + +Blackfriday includes an algorithm for creating sanitized anchor names +corresponding to a given input text. This algorithm is used to create +anchors for headings when `AutoHeadingIDs` extension is enabled. The +algorithm has a specification, so that other packages can create +compatible anchor names and links to those anchors. + +The specification is located at https://pkg.go.dev/github.com/russross/blackfriday/v2#hdr-Sanitized_Anchor_Names. + +[`SanitizedAnchorName`](https://pkg.go.dev/github.com/russross/blackfriday/v2#SanitizedAnchorName) exposes this functionality, and can be used to +create compatible links to the anchor names generated by blackfriday. +This algorithm is also implemented in a small standalone package at +[`github.com/shurcooL/sanitized_anchor_name`](https://pkg.go.dev/github.com/shurcooL/sanitized_anchor_name). It can be useful for clients +that want a small package and don't need full functionality of blackfriday. + + +Features +-------- + +All features of Sundown are supported, including: + +* **Compatibility**. The Markdown v1.0.3 test suite passes with + the `--tidy` option. Without `--tidy`, the differences are + mostly in whitespace and entity escaping, where blackfriday is + more consistent and cleaner. + +* **Common extensions**, including table support, fenced code + blocks, autolinks, strikethroughs, non-strict emphasis, etc. + +* **Safety**. Blackfriday is paranoid when parsing, making it safe + to feed untrusted user input without fear of bad things + happening. The test suite stress tests this and there are no + known inputs that make it crash. If you find one, please let me + know and send me the input that does it. + + NOTE: "safety" in this context means *runtime safety only*. In order to + protect yourself against JavaScript injection in untrusted content, see + [this example](https://github.com/russross/blackfriday#sanitize-untrusted-content). + +* **Fast processing**. It is fast enough to render on-demand in + most web applications without having to cache the output. + +* **Thread safety**. You can run multiple parsers in different + goroutines without ill effect. There is no dependence on global + shared state. + +* **Minimal dependencies**. Blackfriday only depends on standard + library packages in Go. The source code is pretty + self-contained, so it is easy to add to any project, including + Google App Engine projects. + +* **Standards compliant**. Output successfully validates using the + W3C validation tool for HTML 4.01 and XHTML 1.0 Transitional. + + +Extensions +---------- + +In addition to the standard markdown syntax, this package +implements the following extensions: + +* **Intra-word emphasis supression**. The `_` character is + commonly used inside words when discussing code, so having + markdown interpret it as an emphasis command is usually the + wrong thing. Blackfriday lets you treat all emphasis markers as + normal characters when they occur inside a word. + +* **Tables**. Tables can be created by drawing them in the input + using a simple syntax: + + ``` + Name | Age + --------|------ + Bob | 27 + Alice | 23 + ``` + +* **Fenced code blocks**. In addition to the normal 4-space + indentation to mark code blocks, you can explicitly mark them + and supply a language (to make syntax highlighting simple). Just + mark it like this: + + ```go + func getTrue() bool { + return true + } + ``` + + You can use 3 or more backticks to mark the beginning of the + block, and the same number to mark the end of the block. + + To preserve classes of fenced code blocks while using the bluemonday + HTML sanitizer, use the following policy: + + ```go + p := bluemonday.UGCPolicy() + p.AllowAttrs("class").Matching(regexp.MustCompile("^language-[a-zA-Z0-9]+$")).OnElements("code") + html := p.SanitizeBytes(unsafe) + ``` + +* **Definition lists**. A simple definition list is made of a single-line + term followed by a colon and the definition for that term. + + Cat + : Fluffy animal everyone likes + + Internet + : Vector of transmission for pictures of cats + + Terms must be separated from the previous definition by a blank line. + +* **Footnotes**. A marker in the text that will become a superscript number; + a footnote definition that will be placed in a list of footnotes at the + end of the document. A footnote looks like this: + + This is a footnote.[^1] + + [^1]: the footnote text. + +* **Autolinking**. Blackfriday can find URLs that have not been + explicitly marked as links and turn them into links. + +* **Strikethrough**. Use two tildes (`~~`) to mark text that + should be crossed out. + +* **Hard line breaks**. With this extension enabled newlines in the input + translate into line breaks in the output. This extension is off by default. + +* **Smart quotes**. Smartypants-style punctuation substitution is + supported, turning normal double- and single-quote marks into + curly quotes, etc. + +* **LaTeX-style dash parsing** is an additional option, where `--` + is translated into `–`, and `---` is translated into + `—`. This differs from most smartypants processors, which + turn a single hyphen into an ndash and a double hyphen into an + mdash. + +* **Smart fractions**, where anything that looks like a fraction + is translated into suitable HTML (instead of just a few special + cases like most smartypant processors). For example, `4/5` + becomes `45`, which renders as + 45. + + +Other renderers +--------------- + +Blackfriday is structured to allow alternative rendering engines. Here +are a few of note: + +* [github_flavored_markdown](https://pkg.go.dev/github.com/shurcooL/github_flavored_markdown): + provides a GitHub Flavored Markdown renderer with fenced code block + highlighting, clickable heading anchor links. + + It's not customizable, and its goal is to produce HTML output + equivalent to the [GitHub Markdown API endpoint](https://developer.github.com/v3/markdown/#render-a-markdown-document-in-raw-mode), + except the rendering is performed locally. + +* [markdownfmt](https://github.com/shurcooL/markdownfmt): like gofmt, + but for markdown. + +* [LaTeX output](https://gitlab.com/ambrevar/blackfriday-latex): + renders output as LaTeX. + +* [bfchroma](https://github.com/Depado/bfchroma/): provides convenience + integration with the [Chroma](https://github.com/alecthomas/chroma) code + highlighting library. bfchroma is only compatible with v2 of Blackfriday and + provides a drop-in renderer ready to use with Blackfriday, as well as + options and means for further customization. + +* [Blackfriday-Confluence](https://github.com/kentaro-m/blackfriday-confluence): provides a [Confluence Wiki Markup](https://confluence.atlassian.com/doc/confluence-wiki-markup-251003035.html) renderer. + +* [Blackfriday-Slack](https://github.com/karriereat/blackfriday-slack): converts markdown to slack message style + + +TODO +---- + +* More unit testing +* Improve Unicode support. It does not understand all Unicode + rules (about what constitutes a letter, a punctuation symbol, + etc.), so it may fail to detect word boundaries correctly in + some instances. It is safe on all UTF-8 input. + + +License +------- + +[Blackfriday is distributed under the Simplified BSD License](LICENSE.txt) + + + [1]: https://daringfireball.net/projects/markdown/ "Markdown" + [2]: https://golang.org/ "Go Language" + [3]: https://github.com/vmg/sundown "Sundown" + [4]: https://pkg.go.dev/github.com/russross/blackfriday/v2#Parse "Parse func" + [5]: https://github.com/microcosm-cc/bluemonday "Bluemonday" + + [BuildV2SVG]: https://travis-ci.org/russross/blackfriday.svg?branch=v2 + [BuildV2URL]: https://travis-ci.org/russross/blackfriday + [PkgGoDevV2SVG]: https://pkg.go.dev/badge/github.com/russross/blackfriday/v2 + [PkgGoDevV2URL]: https://pkg.go.dev/github.com/russross/blackfriday/v2 diff --git a/vendor/github.com/russross/blackfriday/v2/block.go b/vendor/github.com/russross/blackfriday/v2/block.go new file mode 100644 index 0000000000..dcd61e6e35 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/block.go @@ -0,0 +1,1612 @@ +// +// Blackfriday Markdown Processor +// Available at http://github.com/russross/blackfriday +// +// Copyright © 2011 Russ Ross . +// Distributed under the Simplified BSD License. +// See README.md for details. +// + +// +// Functions to parse block-level elements. +// + +package blackfriday + +import ( + "bytes" + "html" + "regexp" + "strings" + "unicode" +) + +const ( + charEntity = "&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});" + escapable = "[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]" +) + +var ( + reBackslashOrAmp = regexp.MustCompile("[\\&]") + reEntityOrEscapedChar = regexp.MustCompile("(?i)\\\\" + escapable + "|" + charEntity) +) + +// Parse block-level data. +// Note: this function and many that it calls assume that +// the input buffer ends with a newline. +func (p *Markdown) block(data []byte) { + // this is called recursively: enforce a maximum depth + if p.nesting >= p.maxNesting { + return + } + p.nesting++ + + // parse out one block-level construct at a time + for len(data) > 0 { + // prefixed heading: + // + // # Heading 1 + // ## Heading 2 + // ... + // ###### Heading 6 + if p.isPrefixHeading(data) { + data = data[p.prefixHeading(data):] + continue + } + + // block of preformatted HTML: + // + //

      + // ... + //
      + if data[0] == '<' { + if i := p.html(data, true); i > 0 { + data = data[i:] + continue + } + } + + // title block + // + // % stuff + // % more stuff + // % even more stuff + if p.extensions&Titleblock != 0 { + if data[0] == '%' { + if i := p.titleBlock(data, true); i > 0 { + data = data[i:] + continue + } + } + } + + // blank lines. note: returns the # of bytes to skip + if i := p.isEmpty(data); i > 0 { + data = data[i:] + continue + } + + // indented code block: + // + // func max(a, b int) int { + // if a > b { + // return a + // } + // return b + // } + if p.codePrefix(data) > 0 { + data = data[p.code(data):] + continue + } + + // fenced code block: + // + // ``` go + // func fact(n int) int { + // if n <= 1 { + // return n + // } + // return n * fact(n-1) + // } + // ``` + if p.extensions&FencedCode != 0 { + if i := p.fencedCodeBlock(data, true); i > 0 { + data = data[i:] + continue + } + } + + // horizontal rule: + // + // ------ + // or + // ****** + // or + // ______ + if p.isHRule(data) { + p.addBlock(HorizontalRule, nil) + var i int + for i = 0; i < len(data) && data[i] != '\n'; i++ { + } + data = data[i:] + continue + } + + // block quote: + // + // > A big quote I found somewhere + // > on the web + if p.quotePrefix(data) > 0 { + data = data[p.quote(data):] + continue + } + + // table: + // + // Name | Age | Phone + // ------|-----|--------- + // Bob | 31 | 555-1234 + // Alice | 27 | 555-4321 + if p.extensions&Tables != 0 { + if i := p.table(data); i > 0 { + data = data[i:] + continue + } + } + + // an itemized/unordered list: + // + // * Item 1 + // * Item 2 + // + // also works with + or - + if p.uliPrefix(data) > 0 { + data = data[p.list(data, 0):] + continue + } + + // a numbered/ordered list: + // + // 1. Item 1 + // 2. Item 2 + if p.oliPrefix(data) > 0 { + data = data[p.list(data, ListTypeOrdered):] + continue + } + + // definition lists: + // + // Term 1 + // : Definition a + // : Definition b + // + // Term 2 + // : Definition c + if p.extensions&DefinitionLists != 0 { + if p.dliPrefix(data) > 0 { + data = data[p.list(data, ListTypeDefinition):] + continue + } + } + + // anything else must look like a normal paragraph + // note: this finds underlined headings, too + data = data[p.paragraph(data):] + } + + p.nesting-- +} + +func (p *Markdown) addBlock(typ NodeType, content []byte) *Node { + p.closeUnmatchedBlocks() + container := p.addChild(typ, 0) + container.content = content + return container +} + +func (p *Markdown) isPrefixHeading(data []byte) bool { + if data[0] != '#' { + return false + } + + if p.extensions&SpaceHeadings != 0 { + level := 0 + for level < 6 && level < len(data) && data[level] == '#' { + level++ + } + if level == len(data) || data[level] != ' ' { + return false + } + } + return true +} + +func (p *Markdown) prefixHeading(data []byte) int { + level := 0 + for level < 6 && level < len(data) && data[level] == '#' { + level++ + } + i := skipChar(data, level, ' ') + end := skipUntilChar(data, i, '\n') + skip := end + id := "" + if p.extensions&HeadingIDs != 0 { + j, k := 0, 0 + // find start/end of heading id + for j = i; j < end-1 && (data[j] != '{' || data[j+1] != '#'); j++ { + } + for k = j + 1; k < end && data[k] != '}'; k++ { + } + // extract heading id iff found + if j < end && k < end { + id = string(data[j+2 : k]) + end = j + skip = k + 1 + for end > 0 && data[end-1] == ' ' { + end-- + } + } + } + for end > 0 && data[end-1] == '#' { + if isBackslashEscaped(data, end-1) { + break + } + end-- + } + for end > 0 && data[end-1] == ' ' { + end-- + } + if end > i { + if id == "" && p.extensions&AutoHeadingIDs != 0 { + id = SanitizedAnchorName(string(data[i:end])) + } + block := p.addBlock(Heading, data[i:end]) + block.HeadingID = id + block.Level = level + } + return skip +} + +func (p *Markdown) isUnderlinedHeading(data []byte) int { + // test of level 1 heading + if data[0] == '=' { + i := skipChar(data, 1, '=') + i = skipChar(data, i, ' ') + if i < len(data) && data[i] == '\n' { + return 1 + } + return 0 + } + + // test of level 2 heading + if data[0] == '-' { + i := skipChar(data, 1, '-') + i = skipChar(data, i, ' ') + if i < len(data) && data[i] == '\n' { + return 2 + } + return 0 + } + + return 0 +} + +func (p *Markdown) titleBlock(data []byte, doRender bool) int { + if data[0] != '%' { + return 0 + } + splitData := bytes.Split(data, []byte("\n")) + var i int + for idx, b := range splitData { + if !bytes.HasPrefix(b, []byte("%")) { + i = idx // - 1 + break + } + } + + data = bytes.Join(splitData[0:i], []byte("\n")) + consumed := len(data) + data = bytes.TrimPrefix(data, []byte("% ")) + data = bytes.Replace(data, []byte("\n% "), []byte("\n"), -1) + block := p.addBlock(Heading, data) + block.Level = 1 + block.IsTitleblock = true + + return consumed +} + +func (p *Markdown) html(data []byte, doRender bool) int { + var i, j int + + // identify the opening tag + if data[0] != '<' { + return 0 + } + curtag, tagfound := p.htmlFindTag(data[1:]) + + // handle special cases + if !tagfound { + // check for an HTML comment + if size := p.htmlComment(data, doRender); size > 0 { + return size + } + + // check for an
      tag + if size := p.htmlHr(data, doRender); size > 0 { + return size + } + + // no special case recognized + return 0 + } + + // look for an unindented matching closing tag + // followed by a blank line + found := false + /* + closetag := []byte("\n") + j = len(curtag) + 1 + for !found { + // scan for a closing tag at the beginning of a line + if skip := bytes.Index(data[j:], closetag); skip >= 0 { + j += skip + len(closetag) + } else { + break + } + + // see if it is the only thing on the line + if skip := p.isEmpty(data[j:]); skip > 0 { + // see if it is followed by a blank line/eof + j += skip + if j >= len(data) { + found = true + i = j + } else { + if skip := p.isEmpty(data[j:]); skip > 0 { + j += skip + found = true + i = j + } + } + } + } + */ + + // if not found, try a second pass looking for indented match + // but not if tag is "ins" or "del" (following original Markdown.pl) + if !found && curtag != "ins" && curtag != "del" { + i = 1 + for i < len(data) { + i++ + for i < len(data) && !(data[i-1] == '<' && data[i] == '/') { + i++ + } + + if i+2+len(curtag) >= len(data) { + break + } + + j = p.htmlFindEnd(curtag, data[i-1:]) + + if j > 0 { + i += j - 1 + found = true + break + } + } + } + + if !found { + return 0 + } + + // the end of the block has been found + if doRender { + // trim newlines + end := i + for end > 0 && data[end-1] == '\n' { + end-- + } + finalizeHTMLBlock(p.addBlock(HTMLBlock, data[:end])) + } + + return i +} + +func finalizeHTMLBlock(block *Node) { + block.Literal = block.content + block.content = nil +} + +// HTML comment, lax form +func (p *Markdown) htmlComment(data []byte, doRender bool) int { + i := p.inlineHTMLComment(data) + // needs to end with a blank line + if j := p.isEmpty(data[i:]); j > 0 { + size := i + j + if doRender { + // trim trailing newlines + end := size + for end > 0 && data[end-1] == '\n' { + end-- + } + block := p.addBlock(HTMLBlock, data[:end]) + finalizeHTMLBlock(block) + } + return size + } + return 0 +} + +// HR, which is the only self-closing block tag considered +func (p *Markdown) htmlHr(data []byte, doRender bool) int { + if len(data) < 4 { + return 0 + } + if data[0] != '<' || (data[1] != 'h' && data[1] != 'H') || (data[2] != 'r' && data[2] != 'R') { + return 0 + } + if data[3] != ' ' && data[3] != '/' && data[3] != '>' { + // not an
      tag after all; at least not a valid one + return 0 + } + i := 3 + for i < len(data) && data[i] != '>' && data[i] != '\n' { + i++ + } + if i < len(data) && data[i] == '>' { + i++ + if j := p.isEmpty(data[i:]); j > 0 { + size := i + j + if doRender { + // trim newlines + end := size + for end > 0 && data[end-1] == '\n' { + end-- + } + finalizeHTMLBlock(p.addBlock(HTMLBlock, data[:end])) + } + return size + } + } + return 0 +} + +func (p *Markdown) htmlFindTag(data []byte) (string, bool) { + i := 0 + for i < len(data) && isalnum(data[i]) { + i++ + } + key := string(data[:i]) + if _, ok := blockTags[key]; ok { + return key, true + } + return "", false +} + +func (p *Markdown) htmlFindEnd(tag string, data []byte) int { + // assume data[0] == '<' && data[1] == '/' already tested + if tag == "hr" { + return 2 + } + // check if tag is a match + closetag := []byte("") + if !bytes.HasPrefix(data, closetag) { + return 0 + } + i := len(closetag) + + // check that the rest of the line is blank + skip := 0 + if skip = p.isEmpty(data[i:]); skip == 0 { + return 0 + } + i += skip + skip = 0 + + if i >= len(data) { + return i + } + + if p.extensions&LaxHTMLBlocks != 0 { + return i + } + if skip = p.isEmpty(data[i:]); skip == 0 { + // following line must be blank + return 0 + } + + return i + skip +} + +func (*Markdown) isEmpty(data []byte) int { + // it is okay to call isEmpty on an empty buffer + if len(data) == 0 { + return 0 + } + + var i int + for i = 0; i < len(data) && data[i] != '\n'; i++ { + if data[i] != ' ' && data[i] != '\t' { + return 0 + } + } + if i < len(data) && data[i] == '\n' { + i++ + } + return i +} + +func (*Markdown) isHRule(data []byte) bool { + i := 0 + + // skip up to three spaces + for i < 3 && data[i] == ' ' { + i++ + } + + // look at the hrule char + if data[i] != '*' && data[i] != '-' && data[i] != '_' { + return false + } + c := data[i] + + // the whole line must be the char or whitespace + n := 0 + for i < len(data) && data[i] != '\n' { + switch { + case data[i] == c: + n++ + case data[i] != ' ': + return false + } + i++ + } + + return n >= 3 +} + +// isFenceLine checks if there's a fence line (e.g., ``` or ``` go) at the beginning of data, +// and returns the end index if so, or 0 otherwise. It also returns the marker found. +// If info is not nil, it gets set to the syntax specified in the fence line. +func isFenceLine(data []byte, info *string, oldmarker string) (end int, marker string) { + i, size := 0, 0 + + // skip up to three spaces + for i < len(data) && i < 3 && data[i] == ' ' { + i++ + } + + // check for the marker characters: ~ or ` + if i >= len(data) { + return 0, "" + } + if data[i] != '~' && data[i] != '`' { + return 0, "" + } + + c := data[i] + + // the whole line must be the same char or whitespace + for i < len(data) && data[i] == c { + size++ + i++ + } + + // the marker char must occur at least 3 times + if size < 3 { + return 0, "" + } + marker = string(data[i-size : i]) + + // if this is the end marker, it must match the beginning marker + if oldmarker != "" && marker != oldmarker { + return 0, "" + } + + // TODO(shurcooL): It's probably a good idea to simplify the 2 code paths here + // into one, always get the info string, and discard it if the caller doesn't care. + if info != nil { + infoLength := 0 + i = skipChar(data, i, ' ') + + if i >= len(data) { + if i == len(data) { + return i, marker + } + return 0, "" + } + + infoStart := i + + if data[i] == '{' { + i++ + infoStart++ + + for i < len(data) && data[i] != '}' && data[i] != '\n' { + infoLength++ + i++ + } + + if i >= len(data) || data[i] != '}' { + return 0, "" + } + + // strip all whitespace at the beginning and the end + // of the {} block + for infoLength > 0 && isspace(data[infoStart]) { + infoStart++ + infoLength-- + } + + for infoLength > 0 && isspace(data[infoStart+infoLength-1]) { + infoLength-- + } + i++ + i = skipChar(data, i, ' ') + } else { + for i < len(data) && !isverticalspace(data[i]) { + infoLength++ + i++ + } + } + + *info = strings.TrimSpace(string(data[infoStart : infoStart+infoLength])) + } + + if i == len(data) { + return i, marker + } + if i > len(data) || data[i] != '\n' { + return 0, "" + } + return i + 1, marker // Take newline into account. +} + +// fencedCodeBlock returns the end index if data contains a fenced code block at the beginning, +// or 0 otherwise. It writes to out if doRender is true, otherwise it has no side effects. +// If doRender is true, a final newline is mandatory to recognize the fenced code block. +func (p *Markdown) fencedCodeBlock(data []byte, doRender bool) int { + var info string + beg, marker := isFenceLine(data, &info, "") + if beg == 0 || beg >= len(data) { + return 0 + } + fenceLength := beg - 1 + + var work bytes.Buffer + work.Write([]byte(info)) + work.WriteByte('\n') + + for { + // safe to assume beg < len(data) + + // check for the end of the code block + fenceEnd, _ := isFenceLine(data[beg:], nil, marker) + if fenceEnd != 0 { + beg += fenceEnd + break + } + + // copy the current line + end := skipUntilChar(data, beg, '\n') + 1 + + // did we reach the end of the buffer without a closing marker? + if end >= len(data) { + return 0 + } + + // verbatim copy to the working buffer + if doRender { + work.Write(data[beg:end]) + } + beg = end + } + + if doRender { + block := p.addBlock(CodeBlock, work.Bytes()) // TODO: get rid of temp buffer + block.IsFenced = true + block.FenceLength = fenceLength + finalizeCodeBlock(block) + } + + return beg +} + +func unescapeChar(str []byte) []byte { + if str[0] == '\\' { + return []byte{str[1]} + } + return []byte(html.UnescapeString(string(str))) +} + +func unescapeString(str []byte) []byte { + if reBackslashOrAmp.Match(str) { + return reEntityOrEscapedChar.ReplaceAllFunc(str, unescapeChar) + } + return str +} + +func finalizeCodeBlock(block *Node) { + if block.IsFenced { + newlinePos := bytes.IndexByte(block.content, '\n') + firstLine := block.content[:newlinePos] + rest := block.content[newlinePos+1:] + block.Info = unescapeString(bytes.Trim(firstLine, "\n")) + block.Literal = rest + } else { + block.Literal = block.content + } + block.content = nil +} + +func (p *Markdown) table(data []byte) int { + table := p.addBlock(Table, nil) + i, columns := p.tableHeader(data) + if i == 0 { + p.tip = table.Parent + table.Unlink() + return 0 + } + + p.addBlock(TableBody, nil) + + for i < len(data) { + pipes, rowStart := 0, i + for ; i < len(data) && data[i] != '\n'; i++ { + if data[i] == '|' { + pipes++ + } + } + + if pipes == 0 { + i = rowStart + break + } + + // include the newline in data sent to tableRow + if i < len(data) && data[i] == '\n' { + i++ + } + p.tableRow(data[rowStart:i], columns, false) + } + + return i +} + +// check if the specified position is preceded by an odd number of backslashes +func isBackslashEscaped(data []byte, i int) bool { + backslashes := 0 + for i-backslashes-1 >= 0 && data[i-backslashes-1] == '\\' { + backslashes++ + } + return backslashes&1 == 1 +} + +func (p *Markdown) tableHeader(data []byte) (size int, columns []CellAlignFlags) { + i := 0 + colCount := 1 + for i = 0; i < len(data) && data[i] != '\n'; i++ { + if data[i] == '|' && !isBackslashEscaped(data, i) { + colCount++ + } + } + + // doesn't look like a table header + if colCount == 1 { + return + } + + // include the newline in the data sent to tableRow + j := i + if j < len(data) && data[j] == '\n' { + j++ + } + header := data[:j] + + // column count ignores pipes at beginning or end of line + if data[0] == '|' { + colCount-- + } + if i > 2 && data[i-1] == '|' && !isBackslashEscaped(data, i-1) { + colCount-- + } + + columns = make([]CellAlignFlags, colCount) + + // move on to the header underline + i++ + if i >= len(data) { + return + } + + if data[i] == '|' && !isBackslashEscaped(data, i) { + i++ + } + i = skipChar(data, i, ' ') + + // each column header is of form: / *:?-+:? *|/ with # dashes + # colons >= 3 + // and trailing | optional on last column + col := 0 + for i < len(data) && data[i] != '\n' { + dashes := 0 + + if data[i] == ':' { + i++ + columns[col] |= TableAlignmentLeft + dashes++ + } + for i < len(data) && data[i] == '-' { + i++ + dashes++ + } + if i < len(data) && data[i] == ':' { + i++ + columns[col] |= TableAlignmentRight + dashes++ + } + for i < len(data) && data[i] == ' ' { + i++ + } + if i == len(data) { + return + } + // end of column test is messy + switch { + case dashes < 3: + // not a valid column + return + + case data[i] == '|' && !isBackslashEscaped(data, i): + // marker found, now skip past trailing whitespace + col++ + i++ + for i < len(data) && data[i] == ' ' { + i++ + } + + // trailing junk found after last column + if col >= colCount && i < len(data) && data[i] != '\n' { + return + } + + case (data[i] != '|' || isBackslashEscaped(data, i)) && col+1 < colCount: + // something else found where marker was required + return + + case data[i] == '\n': + // marker is optional for the last column + col++ + + default: + // trailing junk found after last column + return + } + } + if col != colCount { + return + } + + p.addBlock(TableHead, nil) + p.tableRow(header, columns, true) + size = i + if size < len(data) && data[size] == '\n' { + size++ + } + return +} + +func (p *Markdown) tableRow(data []byte, columns []CellAlignFlags, header bool) { + p.addBlock(TableRow, nil) + i, col := 0, 0 + + if data[i] == '|' && !isBackslashEscaped(data, i) { + i++ + } + + for col = 0; col < len(columns) && i < len(data); col++ { + for i < len(data) && data[i] == ' ' { + i++ + } + + cellStart := i + + for i < len(data) && (data[i] != '|' || isBackslashEscaped(data, i)) && data[i] != '\n' { + i++ + } + + cellEnd := i + + // skip the end-of-cell marker, possibly taking us past end of buffer + i++ + + for cellEnd > cellStart && cellEnd-1 < len(data) && data[cellEnd-1] == ' ' { + cellEnd-- + } + + cell := p.addBlock(TableCell, data[cellStart:cellEnd]) + cell.IsHeader = header + cell.Align = columns[col] + } + + // pad it out with empty columns to get the right number + for ; col < len(columns); col++ { + cell := p.addBlock(TableCell, nil) + cell.IsHeader = header + cell.Align = columns[col] + } + + // silently ignore rows with too many cells +} + +// returns blockquote prefix length +func (p *Markdown) quotePrefix(data []byte) int { + i := 0 + for i < 3 && i < len(data) && data[i] == ' ' { + i++ + } + if i < len(data) && data[i] == '>' { + if i+1 < len(data) && data[i+1] == ' ' { + return i + 2 + } + return i + 1 + } + return 0 +} + +// blockquote ends with at least one blank line +// followed by something without a blockquote prefix +func (p *Markdown) terminateBlockquote(data []byte, beg, end int) bool { + if p.isEmpty(data[beg:]) <= 0 { + return false + } + if end >= len(data) { + return true + } + return p.quotePrefix(data[end:]) == 0 && p.isEmpty(data[end:]) == 0 +} + +// parse a blockquote fragment +func (p *Markdown) quote(data []byte) int { + block := p.addBlock(BlockQuote, nil) + var raw bytes.Buffer + beg, end := 0, 0 + for beg < len(data) { + end = beg + // Step over whole lines, collecting them. While doing that, check for + // fenced code and if one's found, incorporate it altogether, + // irregardless of any contents inside it + for end < len(data) && data[end] != '\n' { + if p.extensions&FencedCode != 0 { + if i := p.fencedCodeBlock(data[end:], false); i > 0 { + // -1 to compensate for the extra end++ after the loop: + end += i - 1 + break + } + } + end++ + } + if end < len(data) && data[end] == '\n' { + end++ + } + if pre := p.quotePrefix(data[beg:]); pre > 0 { + // skip the prefix + beg += pre + } else if p.terminateBlockquote(data, beg, end) { + break + } + // this line is part of the blockquote + raw.Write(data[beg:end]) + beg = end + } + p.block(raw.Bytes()) + p.finalize(block) + return end +} + +// returns prefix length for block code +func (p *Markdown) codePrefix(data []byte) int { + if len(data) >= 1 && data[0] == '\t' { + return 1 + } + if len(data) >= 4 && data[0] == ' ' && data[1] == ' ' && data[2] == ' ' && data[3] == ' ' { + return 4 + } + return 0 +} + +func (p *Markdown) code(data []byte) int { + var work bytes.Buffer + + i := 0 + for i < len(data) { + beg := i + for i < len(data) && data[i] != '\n' { + i++ + } + if i < len(data) && data[i] == '\n' { + i++ + } + + blankline := p.isEmpty(data[beg:i]) > 0 + if pre := p.codePrefix(data[beg:i]); pre > 0 { + beg += pre + } else if !blankline { + // non-empty, non-prefixed line breaks the pre + i = beg + break + } + + // verbatim copy to the working buffer + if blankline { + work.WriteByte('\n') + } else { + work.Write(data[beg:i]) + } + } + + // trim all the \n off the end of work + workbytes := work.Bytes() + eol := len(workbytes) + for eol > 0 && workbytes[eol-1] == '\n' { + eol-- + } + if eol != len(workbytes) { + work.Truncate(eol) + } + + work.WriteByte('\n') + + block := p.addBlock(CodeBlock, work.Bytes()) // TODO: get rid of temp buffer + block.IsFenced = false + finalizeCodeBlock(block) + + return i +} + +// returns unordered list item prefix +func (p *Markdown) uliPrefix(data []byte) int { + i := 0 + // start with up to 3 spaces + for i < len(data) && i < 3 && data[i] == ' ' { + i++ + } + if i >= len(data)-1 { + return 0 + } + // need one of {'*', '+', '-'} followed by a space or a tab + if (data[i] != '*' && data[i] != '+' && data[i] != '-') || + (data[i+1] != ' ' && data[i+1] != '\t') { + return 0 + } + return i + 2 +} + +// returns ordered list item prefix +func (p *Markdown) oliPrefix(data []byte) int { + i := 0 + + // start with up to 3 spaces + for i < 3 && i < len(data) && data[i] == ' ' { + i++ + } + + // count the digits + start := i + for i < len(data) && data[i] >= '0' && data[i] <= '9' { + i++ + } + if start == i || i >= len(data)-1 { + return 0 + } + + // we need >= 1 digits followed by a dot and a space or a tab + if data[i] != '.' || !(data[i+1] == ' ' || data[i+1] == '\t') { + return 0 + } + return i + 2 +} + +// returns definition list item prefix +func (p *Markdown) dliPrefix(data []byte) int { + if len(data) < 2 { + return 0 + } + i := 0 + // need a ':' followed by a space or a tab + if data[i] != ':' || !(data[i+1] == ' ' || data[i+1] == '\t') { + return 0 + } + for i < len(data) && data[i] == ' ' { + i++ + } + return i + 2 +} + +// parse ordered or unordered list block +func (p *Markdown) list(data []byte, flags ListType) int { + i := 0 + flags |= ListItemBeginningOfList + block := p.addBlock(List, nil) + block.ListFlags = flags + block.Tight = true + + for i < len(data) { + skip := p.listItem(data[i:], &flags) + if flags&ListItemContainsBlock != 0 { + block.ListData.Tight = false + } + i += skip + if skip == 0 || flags&ListItemEndOfList != 0 { + break + } + flags &= ^ListItemBeginningOfList + } + + above := block.Parent + finalizeList(block) + p.tip = above + return i +} + +// Returns true if the list item is not the same type as its parent list +func (p *Markdown) listTypeChanged(data []byte, flags *ListType) bool { + if p.dliPrefix(data) > 0 && *flags&ListTypeDefinition == 0 { + return true + } else if p.oliPrefix(data) > 0 && *flags&ListTypeOrdered == 0 { + return true + } else if p.uliPrefix(data) > 0 && (*flags&ListTypeOrdered != 0 || *flags&ListTypeDefinition != 0) { + return true + } + return false +} + +// Returns true if block ends with a blank line, descending if needed +// into lists and sublists. +func endsWithBlankLine(block *Node) bool { + // TODO: figure this out. Always false now. + for block != nil { + //if block.lastLineBlank { + //return true + //} + t := block.Type + if t == List || t == Item { + block = block.LastChild + } else { + break + } + } + return false +} + +func finalizeList(block *Node) { + block.open = false + item := block.FirstChild + for item != nil { + // check for non-final list item ending with blank line: + if endsWithBlankLine(item) && item.Next != nil { + block.ListData.Tight = false + break + } + // recurse into children of list item, to see if there are spaces + // between any of them: + subItem := item.FirstChild + for subItem != nil { + if endsWithBlankLine(subItem) && (item.Next != nil || subItem.Next != nil) { + block.ListData.Tight = false + break + } + subItem = subItem.Next + } + item = item.Next + } +} + +// Parse a single list item. +// Assumes initial prefix is already removed if this is a sublist. +func (p *Markdown) listItem(data []byte, flags *ListType) int { + // keep track of the indentation of the first line + itemIndent := 0 + if data[0] == '\t' { + itemIndent += 4 + } else { + for itemIndent < 3 && data[itemIndent] == ' ' { + itemIndent++ + } + } + + var bulletChar byte = '*' + i := p.uliPrefix(data) + if i == 0 { + i = p.oliPrefix(data) + } else { + bulletChar = data[i-2] + } + if i == 0 { + i = p.dliPrefix(data) + // reset definition term flag + if i > 0 { + *flags &= ^ListTypeTerm + } + } + if i == 0 { + // if in definition list, set term flag and continue + if *flags&ListTypeDefinition != 0 { + *flags |= ListTypeTerm + } else { + return 0 + } + } + + // skip leading whitespace on first line + for i < len(data) && data[i] == ' ' { + i++ + } + + // find the end of the line + line := i + for i > 0 && i < len(data) && data[i-1] != '\n' { + i++ + } + + // get working buffer + var raw bytes.Buffer + + // put the first line into the working buffer + raw.Write(data[line:i]) + line = i + + // process the following lines + containsBlankLine := false + sublist := 0 + codeBlockMarker := "" + +gatherlines: + for line < len(data) { + i++ + + // find the end of this line + for i < len(data) && data[i-1] != '\n' { + i++ + } + + // if it is an empty line, guess that it is part of this item + // and move on to the next line + if p.isEmpty(data[line:i]) > 0 { + containsBlankLine = true + line = i + continue + } + + // calculate the indentation + indent := 0 + indentIndex := 0 + if data[line] == '\t' { + indentIndex++ + indent += 4 + } else { + for indent < 4 && line+indent < i && data[line+indent] == ' ' { + indent++ + indentIndex++ + } + } + + chunk := data[line+indentIndex : i] + + if p.extensions&FencedCode != 0 { + // determine if in or out of codeblock + // if in codeblock, ignore normal list processing + _, marker := isFenceLine(chunk, nil, codeBlockMarker) + if marker != "" { + if codeBlockMarker == "" { + // start of codeblock + codeBlockMarker = marker + } else { + // end of codeblock. + codeBlockMarker = "" + } + } + // we are in a codeblock, write line, and continue + if codeBlockMarker != "" || marker != "" { + raw.Write(data[line+indentIndex : i]) + line = i + continue gatherlines + } + } + + // evaluate how this line fits in + switch { + // is this a nested list item? + case (p.uliPrefix(chunk) > 0 && !p.isHRule(chunk)) || + p.oliPrefix(chunk) > 0 || + p.dliPrefix(chunk) > 0: + + // to be a nested list, it must be indented more + // if not, it is either a different kind of list + // or the next item in the same list + if indent <= itemIndent { + if p.listTypeChanged(chunk, flags) { + *flags |= ListItemEndOfList + } else if containsBlankLine { + *flags |= ListItemContainsBlock + } + + break gatherlines + } + + if containsBlankLine { + *flags |= ListItemContainsBlock + } + + // is this the first item in the nested list? + if sublist == 0 { + sublist = raw.Len() + } + + // is this a nested prefix heading? + case p.isPrefixHeading(chunk): + // if the heading is not indented, it is not nested in the list + // and thus ends the list + if containsBlankLine && indent < 4 { + *flags |= ListItemEndOfList + break gatherlines + } + *flags |= ListItemContainsBlock + + // anything following an empty line is only part + // of this item if it is indented 4 spaces + // (regardless of the indentation of the beginning of the item) + case containsBlankLine && indent < 4: + if *flags&ListTypeDefinition != 0 && i < len(data)-1 { + // is the next item still a part of this list? + next := i + for next < len(data) && data[next] != '\n' { + next++ + } + for next < len(data)-1 && data[next] == '\n' { + next++ + } + if i < len(data)-1 && data[i] != ':' && data[next] != ':' { + *flags |= ListItemEndOfList + } + } else { + *flags |= ListItemEndOfList + } + break gatherlines + + // a blank line means this should be parsed as a block + case containsBlankLine: + raw.WriteByte('\n') + *flags |= ListItemContainsBlock + } + + // if this line was preceded by one or more blanks, + // re-introduce the blank into the buffer + if containsBlankLine { + containsBlankLine = false + raw.WriteByte('\n') + } + + // add the line into the working buffer without prefix + raw.Write(data[line+indentIndex : i]) + + line = i + } + + rawBytes := raw.Bytes() + + block := p.addBlock(Item, nil) + block.ListFlags = *flags + block.Tight = false + block.BulletChar = bulletChar + block.Delimiter = '.' // Only '.' is possible in Markdown, but ')' will also be possible in CommonMark + + // render the contents of the list item + if *flags&ListItemContainsBlock != 0 && *flags&ListTypeTerm == 0 { + // intermediate render of block item, except for definition term + if sublist > 0 { + p.block(rawBytes[:sublist]) + p.block(rawBytes[sublist:]) + } else { + p.block(rawBytes) + } + } else { + // intermediate render of inline item + if sublist > 0 { + child := p.addChild(Paragraph, 0) + child.content = rawBytes[:sublist] + p.block(rawBytes[sublist:]) + } else { + child := p.addChild(Paragraph, 0) + child.content = rawBytes + } + } + return line +} + +// render a single paragraph that has already been parsed out +func (p *Markdown) renderParagraph(data []byte) { + if len(data) == 0 { + return + } + + // trim leading spaces + beg := 0 + for data[beg] == ' ' { + beg++ + } + + end := len(data) + // trim trailing newline + if data[len(data)-1] == '\n' { + end-- + } + + // trim trailing spaces + for end > beg && data[end-1] == ' ' { + end-- + } + + p.addBlock(Paragraph, data[beg:end]) +} + +func (p *Markdown) paragraph(data []byte) int { + // prev: index of 1st char of previous line + // line: index of 1st char of current line + // i: index of cursor/end of current line + var prev, line, i int + tabSize := TabSizeDefault + if p.extensions&TabSizeEight != 0 { + tabSize = TabSizeDouble + } + // keep going until we find something to mark the end of the paragraph + for i < len(data) { + // mark the beginning of the current line + prev = line + current := data[i:] + line = i + + // did we find a reference or a footnote? If so, end a paragraph + // preceding it and report that we have consumed up to the end of that + // reference: + if refEnd := isReference(p, current, tabSize); refEnd > 0 { + p.renderParagraph(data[:i]) + return i + refEnd + } + + // did we find a blank line marking the end of the paragraph? + if n := p.isEmpty(current); n > 0 { + // did this blank line followed by a definition list item? + if p.extensions&DefinitionLists != 0 { + if i < len(data)-1 && data[i+1] == ':' { + return p.list(data[prev:], ListTypeDefinition) + } + } + + p.renderParagraph(data[:i]) + return i + n + } + + // an underline under some text marks a heading, so our paragraph ended on prev line + if i > 0 { + if level := p.isUnderlinedHeading(current); level > 0 { + // render the paragraph + p.renderParagraph(data[:prev]) + + // ignore leading and trailing whitespace + eol := i - 1 + for prev < eol && data[prev] == ' ' { + prev++ + } + for eol > prev && data[eol-1] == ' ' { + eol-- + } + + id := "" + if p.extensions&AutoHeadingIDs != 0 { + id = SanitizedAnchorName(string(data[prev:eol])) + } + + block := p.addBlock(Heading, data[prev:eol]) + block.Level = level + block.HeadingID = id + + // find the end of the underline + for i < len(data) && data[i] != '\n' { + i++ + } + return i + } + } + + // if the next line starts a block of HTML, then the paragraph ends here + if p.extensions&LaxHTMLBlocks != 0 { + if data[i] == '<' && p.html(current, false) > 0 { + // rewind to before the HTML block + p.renderParagraph(data[:i]) + return i + } + } + + // if there's a prefixed heading or a horizontal rule after this, paragraph is over + if p.isPrefixHeading(current) || p.isHRule(current) { + p.renderParagraph(data[:i]) + return i + } + + // if there's a fenced code block, paragraph is over + if p.extensions&FencedCode != 0 { + if p.fencedCodeBlock(current, false) > 0 { + p.renderParagraph(data[:i]) + return i + } + } + + // if there's a definition list item, prev line is a definition term + if p.extensions&DefinitionLists != 0 { + if p.dliPrefix(current) != 0 { + ret := p.list(data[prev:], ListTypeDefinition) + return ret + } + } + + // if there's a list after this, paragraph is over + if p.extensions&NoEmptyLineBeforeBlock != 0 { + if p.uliPrefix(current) != 0 || + p.oliPrefix(current) != 0 || + p.quotePrefix(current) != 0 || + p.codePrefix(current) != 0 { + p.renderParagraph(data[:i]) + return i + } + } + + // otherwise, scan to the beginning of the next line + nl := bytes.IndexByte(data[i:], '\n') + if nl >= 0 { + i += nl + 1 + } else { + i += len(data[i:]) + } + } + + p.renderParagraph(data[:i]) + return i +} + +func skipChar(data []byte, start int, char byte) int { + i := start + for i < len(data) && data[i] == char { + i++ + } + return i +} + +func skipUntilChar(text []byte, start int, char byte) int { + i := start + for i < len(text) && text[i] != char { + i++ + } + return i +} + +// SanitizedAnchorName returns a sanitized anchor name for the given text. +// +// It implements the algorithm specified in the package comment. +func SanitizedAnchorName(text string) string { + var anchorName []rune + futureDash := false + for _, r := range text { + switch { + case unicode.IsLetter(r) || unicode.IsNumber(r): + if futureDash && len(anchorName) > 0 { + anchorName = append(anchorName, '-') + } + futureDash = false + anchorName = append(anchorName, unicode.ToLower(r)) + default: + futureDash = true + } + } + return string(anchorName) +} diff --git a/vendor/github.com/russross/blackfriday/v2/doc.go b/vendor/github.com/russross/blackfriday/v2/doc.go new file mode 100644 index 0000000000..57ff152a05 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/doc.go @@ -0,0 +1,46 @@ +// Package blackfriday is a markdown processor. +// +// It translates plain text with simple formatting rules into an AST, which can +// then be further processed to HTML (provided by Blackfriday itself) or other +// formats (provided by the community). +// +// The simplest way to invoke Blackfriday is to call the Run function. It will +// take a text input and produce a text output in HTML (or other format). +// +// A slightly more sophisticated way to use Blackfriday is to create a Markdown +// processor and to call Parse, which returns a syntax tree for the input +// document. You can leverage Blackfriday's parsing for content extraction from +// markdown documents. You can assign a custom renderer and set various options +// to the Markdown processor. +// +// If you're interested in calling Blackfriday from command line, see +// https://github.com/russross/blackfriday-tool. +// +// Sanitized Anchor Names +// +// Blackfriday includes an algorithm for creating sanitized anchor names +// corresponding to a given input text. This algorithm is used to create +// anchors for headings when AutoHeadingIDs extension is enabled. The +// algorithm is specified below, so that other packages can create +// compatible anchor names and links to those anchors. +// +// The algorithm iterates over the input text, interpreted as UTF-8, +// one Unicode code point (rune) at a time. All runes that are letters (category L) +// or numbers (category N) are considered valid characters. They are mapped to +// lower case, and included in the output. All other runes are considered +// invalid characters. Invalid characters that precede the first valid character, +// as well as invalid character that follow the last valid character +// are dropped completely. All other sequences of invalid characters +// between two valid characters are replaced with a single dash character '-'. +// +// SanitizedAnchorName exposes this functionality, and can be used to +// create compatible links to the anchor names generated by blackfriday. +// This algorithm is also implemented in a small standalone package at +// github.com/shurcooL/sanitized_anchor_name. It can be useful for clients +// that want a small package and don't need full functionality of blackfriday. +package blackfriday + +// NOTE: Keep Sanitized Anchor Name algorithm in sync with package +// github.com/shurcooL/sanitized_anchor_name. +// Otherwise, users of sanitized_anchor_name will get anchor names +// that are incompatible with those generated by blackfriday. diff --git a/vendor/github.com/russross/blackfriday/v2/entities.go b/vendor/github.com/russross/blackfriday/v2/entities.go new file mode 100644 index 0000000000..a2c3edb691 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/entities.go @@ -0,0 +1,2236 @@ +package blackfriday + +// Extracted from https://html.spec.whatwg.org/multipage/entities.json +var entities = map[string]bool{ + "Æ": true, + "Æ": true, + "&": true, + "&": true, + "Á": true, + "Á": true, + "Ă": true, + "Â": true, + "Â": true, + "А": true, + "𝔄": true, + "À": true, + "À": true, + "Α": true, + "Ā": true, + "⩓": true, + "Ą": true, + "𝔸": true, + "⁡": true, + "Å": true, + "Å": true, + "𝒜": true, + "≔": true, + "Ã": true, + "Ã": true, + "Ä": true, + "Ä": true, + "∖": true, + "⫧": true, + "⌆": true, + "Б": true, + "∵": true, + "ℬ": true, + "Β": true, + "𝔅": true, + "𝔹": true, + "˘": true, + "ℬ": true, + "≎": true, + "Ч": true, + "©": true, + "©": true, + "Ć": true, + "⋒": true, + "ⅅ": true, + "ℭ": true, + "Č": true, + "Ç": true, + "Ç": true, + "Ĉ": true, + "∰": true, + "Ċ": true, + "¸": true, + "·": true, + "ℭ": true, + "Χ": true, + "⊙": true, + "⊖": true, + "⊕": true, + "⊗": true, + "∲": true, + "”": true, + "’": true, + "∷": true, + "⩴": true, + "≡": true, + "∯": true, + "∮": true, + "ℂ": true, + "∐": true, + "∳": true, + "⨯": true, + "𝒞": true, + "⋓": true, + "≍": true, + "ⅅ": true, + "⤑": true, + "Ђ": true, + "Ѕ": true, + "Џ": true, + "‡": true, + "↡": true, + "⫤": true, + "Ď": true, + "Д": true, + "∇": true, + "Δ": true, + "𝔇": true, + "´": true, + "˙": true, + "˝": true, + "`": true, + "˜": true, + "⋄": true, + "ⅆ": true, + "𝔻": true, + "¨": true, + "⃜": true, + "≐": true, + "∯": true, + "¨": true, + "⇓": true, + "⇐": true, + "⇔": true, + "⫤": true, + "⟸": true, + "⟺": true, + "⟹": true, + "⇒": true, + "⊨": true, + "⇑": true, + "⇕": true, + "∥": true, + "↓": true, + "⤓": true, + "⇵": true, + "̑": true, + "⥐": true, + "⥞": true, + "↽": true, + "⥖": true, + "⥟": true, + "⇁": true, + "⥗": true, + "⊤": true, + "↧": true, + "⇓": true, + "𝒟": true, + "Đ": true, + "Ŋ": true, + "Ð": true, + "Ð": true, + "É": true, + "É": true, + "Ě": true, + "Ê": true, + "Ê": true, + "Э": true, + "Ė": true, + "𝔈": true, + "È": true, + "È": true, + "∈": true, + "Ē": true, + "◻": true, + "▫": true, + "Ę": true, + "𝔼": true, + "Ε": true, + "⩵": true, + "≂": true, + "⇌": true, + "ℰ": true, + "⩳": true, + "Η": true, + "Ë": true, + "Ë": true, + "∃": true, + "ⅇ": true, + "Ф": true, + "𝔉": true, + "◼": true, + "▪": true, + "𝔽": true, + "∀": true, + "ℱ": true, + "ℱ": true, + "Ѓ": true, + ">": true, + ">": true, + "Γ": true, + "Ϝ": true, + "Ğ": true, + "Ģ": true, + "Ĝ": true, + "Г": true, + "Ġ": true, + "𝔊": true, + "⋙": true, + "𝔾": true, + "≥": true, + "⋛": true, + "≧": true, + "⪢": true, + "≷": true, + "⩾": true, + "≳": true, + "𝒢": true, + "≫": true, + "Ъ": true, + "ˇ": true, + "^": true, + "Ĥ": true, + "ℌ": true, + "ℋ": true, + "ℍ": true, + "─": true, + "ℋ": true, + "Ħ": true, + "≎": true, + "≏": true, + "Е": true, + "IJ": true, + "Ё": true, + "Í": true, + "Í": true, + "Î": true, + "Î": true, + "И": true, + "İ": true, + "ℑ": true, + "Ì": true, + "Ì": true, + "ℑ": true, + "Ī": true, + "ⅈ": true, + "⇒": true, + "∬": true, + "∫": true, + "⋂": true, + "⁣": true, + "⁢": true, + "Į": true, + "𝕀": true, + "Ι": true, + "ℐ": true, + "Ĩ": true, + "І": true, + "Ï": true, + "Ï": true, + "Ĵ": true, + "Й": true, + "𝔍": true, + "𝕁": true, + "𝒥": true, + "Ј": true, + "Є": true, + "Х": true, + "Ќ": true, + "Κ": true, + "Ķ": true, + "К": true, + "𝔎": true, + "𝕂": true, + "𝒦": true, + "Љ": true, + "<": true, + "<": true, + "Ĺ": true, + "Λ": true, + "⟪": true, + "ℒ": true, + "↞": true, + "Ľ": true, + "Ļ": true, + "Л": true, + "⟨": true, + "←": true, + "⇤": true, + "⇆": true, + "⌈": true, + "⟦": true, + "⥡": true, + "⇃": true, + "⥙": true, + "⌊": true, + "↔": true, + "⥎": true, + "⊣": true, + "↤": true, + "⥚": true, + "⊲": true, + "⧏": true, + "⊴": true, + "⥑": true, + "⥠": true, + "↿": true, + "⥘": true, + "↼": true, + "⥒": true, + "⇐": true, + "⇔": true, + "⋚": true, + "≦": true, + "≶": true, + "⪡": true, + "⩽": true, + "≲": true, + "𝔏": true, + "⋘": true, + "⇚": true, + "Ŀ": true, + "⟵": true, + "⟷": true, + "⟶": true, + "⟸": true, + "⟺": true, + "⟹": true, + "𝕃": true, + "↙": true, + "↘": true, + "ℒ": true, + "↰": true, + "Ł": true, + "≪": true, + "⤅": true, + "М": true, + " ": true, + "ℳ": true, + "𝔐": true, + "∓": true, + "𝕄": true, + "ℳ": true, + "Μ": true, + "Њ": true, + "Ń": true, + "Ň": true, + "Ņ": true, + "Н": true, + "​": true, + "​": true, + "​": true, + "​": true, + "≫": true, + "≪": true, + " ": true, + "𝔑": true, + "⁠": true, + " ": true, + "ℕ": true, + "⫬": true, + "≢": true, + "≭": true, + "∦": true, + "∉": true, + "≠": true, + "≂̸": true, + "∄": true, + "≯": true, + "≱": true, + "≧̸": true, + "≫̸": true, + "≹": true, + "⩾̸": true, + "≵": true, + "≎̸": true, + "≏̸": true, + "⋪": true, + "⧏̸": true, + "⋬": true, + "≮": true, + "≰": true, + "≸": true, + "≪̸": true, + "⩽̸": true, + "≴": true, + "⪢̸": true, + "⪡̸": true, + "⊀": true, + "⪯̸": true, + "⋠": true, + "∌": true, + "⋫": true, + "⧐̸": true, + "⋭": true, + "⊏̸": true, + "⋢": true, + "⊐̸": true, + "⋣": true, + "⊂⃒": true, + "⊈": true, + "⊁": true, + "⪰̸": true, + "⋡": true, + "≿̸": true, + "⊃⃒": true, + "⊉": true, + "≁": true, + "≄": true, + "≇": true, + "≉": true, + "∤": true, + "𝒩": true, + "Ñ": true, + "Ñ": true, + "Ν": true, + "Œ": true, + "Ó": true, + "Ó": true, + "Ô": true, + "Ô": true, + "О": true, + "Ő": true, + "𝔒": true, + "Ò": true, + "Ò": true, + "Ō": true, + "Ω": true, + "Ο": true, + "𝕆": true, + "“": true, + "‘": true, + "⩔": true, + "𝒪": true, + "Ø": true, + "Ø": true, + "Õ": true, + "Õ": true, + "⨷": true, + "Ö": true, + "Ö": true, + "‾": true, + "⏞": true, + "⎴": true, + "⏜": true, + "∂": true, + "П": true, + "𝔓": true, + "Φ": true, + "Π": true, + "±": true, + "ℌ": true, + "ℙ": true, + "⪻": true, + "≺": true, + "⪯": true, + "≼": true, + "≾": true, + "″": true, + "∏": true, + "∷": true, + "∝": true, + "𝒫": true, + "Ψ": true, + """: true, + """: true, + "𝔔": true, + "ℚ": true, + "𝒬": true, + "⤐": true, + "®": true, + "®": true, + "Ŕ": true, + "⟫": true, + "↠": true, + "⤖": true, + "Ř": true, + "Ŗ": true, + "Р": true, + "ℜ": true, + "∋": true, + "⇋": true, + "⥯": true, + "ℜ": true, + "Ρ": true, + "⟩": true, + "→": true, + "⇥": true, + "⇄": true, + "⌉": true, + "⟧": true, + "⥝": true, + "⇂": true, + "⥕": true, + "⌋": true, + "⊢": true, + "↦": true, + "⥛": true, + "⊳": true, + "⧐": true, + "⊵": true, + "⥏": true, + "⥜": true, + "↾": true, + "⥔": true, + "⇀": true, + "⥓": true, + "⇒": true, + "ℝ": true, + "⥰": true, + "⇛": true, + "ℛ": true, + "↱": true, + "⧴": true, + "Щ": true, + "Ш": true, + "Ь": true, + "Ś": true, + "⪼": true, + "Š": true, + "Ş": true, + "Ŝ": true, + "С": true, + "𝔖": true, + "↓": true, + "←": true, + "→": true, + "↑": true, + "Σ": true, + "∘": true, + "𝕊": true, + "√": true, + "□": true, + "⊓": true, + "⊏": true, + "⊑": true, + "⊐": true, + "⊒": true, + "⊔": true, + "𝒮": true, + "⋆": true, + "⋐": true, + "⋐": true, + "⊆": true, + "≻": true, + "⪰": true, + "≽": true, + "≿": true, + "∋": true, + "∑": true, + "⋑": true, + "⊃": true, + "⊇": true, + "⋑": true, + "Þ": true, + "Þ": true, + "™": true, + "Ћ": true, + "Ц": true, + " ": true, + "Τ": true, + "Ť": true, + "Ţ": true, + "Т": true, + "𝔗": true, + "∴": true, + "Θ": true, + "  ": true, + " ": true, + "∼": true, + "≃": true, + "≅": true, + "≈": true, + "𝕋": true, + "⃛": true, + "𝒯": true, + "Ŧ": true, + "Ú": true, + "Ú": true, + "↟": true, + "⥉": true, + "Ў": true, + "Ŭ": true, + "Û": true, + "Û": true, + "У": true, + "Ű": true, + "𝔘": true, + "Ù": true, + "Ù": true, + "Ū": true, + "_": true, + "⏟": true, + "⎵": true, + "⏝": true, + "⋃": true, + "⊎": true, + "Ų": true, + "𝕌": true, + "↑": true, + "⤒": true, + "⇅": true, + "↕": true, + "⥮": true, + "⊥": true, + "↥": true, + "⇑": true, + "⇕": true, + "↖": true, + "↗": true, + "ϒ": true, + "Υ": true, + "Ů": true, + "𝒰": true, + "Ũ": true, + "Ü": true, + "Ü": true, + "⊫": true, + "⫫": true, + "В": true, + "⊩": true, + "⫦": true, + "⋁": true, + "‖": true, + "‖": true, + "∣": true, + "|": true, + "❘": true, + "≀": true, + " ": true, + "𝔙": true, + "𝕍": true, + "𝒱": true, + "⊪": true, + "Ŵ": true, + "⋀": true, + "𝔚": true, + "𝕎": true, + "𝒲": true, + "𝔛": true, + "Ξ": true, + "𝕏": true, + "𝒳": true, + "Я": true, + "Ї": true, + "Ю": true, + "Ý": true, + "Ý": true, + "Ŷ": true, + "Ы": true, + "𝔜": true, + "𝕐": true, + "𝒴": true, + "Ÿ": true, + "Ж": true, + "Ź": true, + "Ž": true, + "З": true, + "Ż": true, + "​": true, + "Ζ": true, + "ℨ": true, + "ℤ": true, + "𝒵": true, + "á": true, + "á": true, + "ă": true, + "∾": true, + "∾̳": true, + "∿": true, + "â": true, + "â": true, + "´": true, + "´": true, + "а": true, + "æ": true, + "æ": true, + "⁡": true, + "𝔞": true, + "à": true, + "à": true, + "ℵ": true, + "ℵ": true, + "α": true, + "ā": true, + "⨿": true, + "&": true, + "&": true, + "∧": true, + "⩕": true, + "⩜": true, + "⩘": true, + "⩚": true, + "∠": true, + "⦤": true, + "∠": true, + "∡": true, + "⦨": true, + "⦩": true, + "⦪": true, + "⦫": true, + "⦬": true, + "⦭": true, + "⦮": true, + "⦯": true, + "∟": true, + "⊾": true, + "⦝": true, + "∢": true, + "Å": true, + "⍼": true, + "ą": true, + "𝕒": true, + "≈": true, + "⩰": true, + "⩯": true, + "≊": true, + "≋": true, + "'": true, + "≈": true, + "≊": true, + "å": true, + "å": true, + "𝒶": true, + "*": true, + "≈": true, + "≍": true, + "ã": true, + "ã": true, + "ä": true, + "ä": true, + "∳": true, + "⨑": true, + "⫭": true, + "≌": true, + "϶": true, + "‵": true, + "∽": true, + "⋍": true, + "⊽": true, + "⌅": true, + "⌅": true, + "⎵": true, + "⎶": true, + "≌": true, + "б": true, + "„": true, + "∵": true, + "∵": true, + "⦰": true, + "϶": true, + "ℬ": true, + "β": true, + "ℶ": true, + "≬": true, + "𝔟": true, + "⋂": true, + "◯": true, + "⋃": true, + "⨀": true, + "⨁": true, + "⨂": true, + "⨆": true, + "★": true, + "▽": true, + "△": true, + "⨄": true, + "⋁": true, + "⋀": true, + "⤍": true, + "⧫": true, + "▪": true, + "▴": true, + "▾": true, + "◂": true, + "▸": true, + "␣": true, + "▒": true, + "░": true, + "▓": true, + "█": true, + "=⃥": true, + "≡⃥": true, + "⌐": true, + "𝕓": true, + "⊥": true, + "⊥": true, + "⋈": true, + "╗": true, + "╔": true, + "╖": true, + "╓": true, + "═": true, + "╦": true, + "╩": true, + "╤": true, + "╧": true, + "╝": true, + "╚": true, + "╜": true, + "╙": true, + "║": true, + "╬": true, + "╣": true, + "╠": true, + "╫": true, + "╢": true, + "╟": true, + "⧉": true, + "╕": true, + "╒": true, + "┐": true, + "┌": true, + "─": true, + "╥": true, + "╨": true, + "┬": true, + "┴": true, + "⊟": true, + "⊞": true, + "⊠": true, + "╛": true, + "╘": true, + "┘": true, + "└": true, + "│": true, + "╪": true, + "╡": true, + "╞": true, + "┼": true, + "┤": true, + "├": true, + "‵": true, + "˘": true, + "¦": true, + "¦": true, + "𝒷": true, + "⁏": true, + "∽": true, + "⋍": true, + "\": true, + "⧅": true, + "⟈": true, + "•": true, + "•": true, + "≎": true, + "⪮": true, + "≏": true, + "≏": true, + "ć": true, + "∩": true, + "⩄": true, + "⩉": true, + "⩋": true, + "⩇": true, + "⩀": true, + "∩︀": true, + "⁁": true, + "ˇ": true, + "⩍": true, + "č": true, + "ç": true, + "ç": true, + "ĉ": true, + "⩌": true, + "⩐": true, + "ċ": true, + "¸": true, + "¸": true, + "⦲": true, + "¢": true, + "¢": true, + "·": true, + "𝔠": true, + "ч": true, + "✓": true, + "✓": true, + "χ": true, + "○": true, + "⧃": true, + "ˆ": true, + "≗": true, + "↺": true, + "↻": true, + "®": true, + "Ⓢ": true, + "⊛": true, + "⊚": true, + "⊝": true, + "≗": true, + "⨐": true, + "⫯": true, + "⧂": true, + "♣": true, + "♣": true, + ":": true, + "≔": true, + "≔": true, + ",": true, + "@": true, + "∁": true, + "∘": true, + "∁": true, + "ℂ": true, + "≅": true, + "⩭": true, + "∮": true, + "𝕔": true, + "∐": true, + "©": true, + "©": true, + "℗": true, + "↵": true, + "✗": true, + "𝒸": true, + "⫏": true, + "⫑": true, + "⫐": true, + "⫒": true, + "⋯": true, + "⤸": true, + "⤵": true, + "⋞": true, + "⋟": true, + "↶": true, + "⤽": true, + "∪": true, + "⩈": true, + "⩆": true, + "⩊": true, + "⊍": true, + "⩅": true, + "∪︀": true, + "↷": true, + "⤼": true, + "⋞": true, + "⋟": true, + "⋎": true, + "⋏": true, + "¤": true, + "¤": true, + "↶": true, + "↷": true, + "⋎": true, + "⋏": true, + "∲": true, + "∱": true, + "⌭": true, + "⇓": true, + "⥥": true, + "†": true, + "ℸ": true, + "↓": true, + "‐": true, + "⊣": true, + "⤏": true, + "˝": true, + "ď": true, + "д": true, + "ⅆ": true, + "‡": true, + "⇊": true, + "⩷": true, + "°": true, + "°": true, + "δ": true, + "⦱": true, + "⥿": true, + "𝔡": true, + "⇃": true, + "⇂": true, + "⋄": true, + "⋄": true, + "♦": true, + "♦": true, + "¨": true, + "ϝ": true, + "⋲": true, + "÷": true, + "÷": true, + "÷": true, + "⋇": true, + "⋇": true, + "ђ": true, + "⌞": true, + "⌍": true, + "$": true, + "𝕕": true, + "˙": true, + "≐": true, + "≑": true, + "∸": true, + "∔": true, + "⊡": true, + "⌆": true, + "↓": true, + "⇊": true, + "⇃": true, + "⇂": true, + "⤐": true, + "⌟": true, + "⌌": true, + "𝒹": true, + "ѕ": true, + "⧶": true, + "đ": true, + "⋱": true, + "▿": true, + "▾": true, + "⇵": true, + "⥯": true, + "⦦": true, + "џ": true, + "⟿": true, + "⩷": true, + "≑": true, + "é": true, + "é": true, + "⩮": true, + "ě": true, + "≖": true, + "ê": true, + "ê": true, + "≕": true, + "э": true, + "ė": true, + "ⅇ": true, + "≒": true, + "𝔢": true, + "⪚": true, + "è": true, + "è": true, + "⪖": true, + "⪘": true, + "⪙": true, + "⏧": true, + "ℓ": true, + "⪕": true, + "⪗": true, + "ē": true, + "∅": true, + "∅": true, + "∅": true, + " ": true, + " ": true, + " ": true, + "ŋ": true, + " ": true, + "ę": true, + "𝕖": true, + "⋕": true, + "⧣": true, + "⩱": true, + "ε": true, + "ε": true, + "ϵ": true, + "≖": true, + "≕": true, + "≂": true, + "⪖": true, + "⪕": true, + "=": true, + "≟": true, + "≡": true, + "⩸": true, + "⧥": true, + "≓": true, + "⥱": true, + "ℯ": true, + "≐": true, + "≂": true, + "η": true, + "ð": true, + "ð": true, + "ë": true, + "ë": true, + "€": true, + "!": true, + "∃": true, + "ℰ": true, + "ⅇ": true, + "≒": true, + "ф": true, + "♀": true, + "ffi": true, + "ff": true, + "ffl": true, + "𝔣": true, + "fi": true, + "fj": true, + "♭": true, + "fl": true, + "▱": true, + "ƒ": true, + "𝕗": true, + "∀": true, + "⋔": true, + "⫙": true, + "⨍": true, + "½": true, + "½": true, + "⅓": true, + "¼": true, + "¼": true, + "⅕": true, + "⅙": true, + "⅛": true, + "⅔": true, + "⅖": true, + "¾": true, + "¾": true, + "⅗": true, + "⅜": true, + "⅘": true, + "⅚": true, + "⅝": true, + "⅞": true, + "⁄": true, + "⌢": true, + "𝒻": true, + "≧": true, + "⪌": true, + "ǵ": true, + "γ": true, + "ϝ": true, + "⪆": true, + "ğ": true, + "ĝ": true, + "г": true, + "ġ": true, + "≥": true, + "⋛": true, + "≥": true, + "≧": true, + "⩾": true, + "⩾": true, + "⪩": true, + "⪀": true, + "⪂": true, + "⪄": true, + "⋛︀": true, + "⪔": true, + "𝔤": true, + "≫": true, + "⋙": true, + "ℷ": true, + "ѓ": true, + "≷": true, + "⪒": true, + "⪥": true, + "⪤": true, + "≩": true, + "⪊": true, + "⪊": true, + "⪈": true, + "⪈": true, + "≩": true, + "⋧": true, + "𝕘": true, + "`": true, + "ℊ": true, + "≳": true, + "⪎": true, + "⪐": true, + ">": true, + ">": true, + "⪧": true, + "⩺": true, + "⋗": true, + "⦕": true, + "⩼": true, + "⪆": true, + "⥸": true, + "⋗": true, + "⋛": true, + "⪌": true, + "≷": true, + "≳": true, + "≩︀": true, + "≩︀": true, + "⇔": true, + " ": true, + "½": true, + "ℋ": true, + "ъ": true, + "↔": true, + "⥈": true, + "↭": true, + "ℏ": true, + "ĥ": true, + "♥": true, + "♥": true, + "…": true, + "⊹": true, + "𝔥": true, + "⤥": true, + "⤦": true, + "⇿": true, + "∻": true, + "↩": true, + "↪": true, + "𝕙": true, + "―": true, + "𝒽": true, + "ℏ": true, + "ħ": true, + "⁃": true, + "‐": true, + "í": true, + "í": true, + "⁣": true, + "î": true, + "î": true, + "и": true, + "е": true, + "¡": true, + "¡": true, + "⇔": true, + "𝔦": true, + "ì": true, + "ì": true, + "ⅈ": true, + "⨌": true, + "∭": true, + "⧜": true, + "℩": true, + "ij": true, + "ī": true, + "ℑ": true, + "ℐ": true, + "ℑ": true, + "ı": true, + "⊷": true, + "Ƶ": true, + "∈": true, + "℅": true, + "∞": true, + "⧝": true, + "ı": true, + "∫": true, + "⊺": true, + "ℤ": true, + "⊺": true, + "⨗": true, + "⨼": true, + "ё": true, + "į": true, + "𝕚": true, + "ι": true, + "⨼": true, + "¿": true, + "¿": true, + "𝒾": true, + "∈": true, + "⋹": true, + "⋵": true, + "⋴": true, + "⋳": true, + "∈": true, + "⁢": true, + "ĩ": true, + "і": true, + "ï": true, + "ï": true, + "ĵ": true, + "й": true, + "𝔧": true, + "ȷ": true, + "𝕛": true, + "𝒿": true, + "ј": true, + "є": true, + "κ": true, + "ϰ": true, + "ķ": true, + "к": true, + "𝔨": true, + "ĸ": true, + "х": true, + "ќ": true, + "𝕜": true, + "𝓀": true, + "⇚": true, + "⇐": true, + "⤛": true, + "⤎": true, + "≦": true, + "⪋": true, + "⥢": true, + "ĺ": true, + "⦴": true, + "ℒ": true, + "λ": true, + "⟨": true, + "⦑": true, + "⟨": true, + "⪅": true, + "«": true, + "«": true, + "←": true, + "⇤": true, + "⤟": true, + "⤝": true, + "↩": true, + "↫": true, + "⤹": true, + "⥳": true, + "↢": true, + "⪫": true, + "⤙": true, + "⪭": true, + "⪭︀": true, + "⤌": true, + "❲": true, + "{": true, + "[": true, + "⦋": true, + "⦏": true, + "⦍": true, + "ľ": true, + "ļ": true, + "⌈": true, + "{": true, + "л": true, + "⤶": true, + "“": true, + "„": true, + "⥧": true, + "⥋": true, + "↲": true, + "≤": true, + "←": true, + "↢": true, + "↽": true, + "↼": true, + "⇇": true, + "↔": true, + "⇆": true, + "⇋": true, + "↭": true, + "⋋": true, + "⋚": true, + "≤": true, + "≦": true, + "⩽": true, + "⩽": true, + "⪨": true, + "⩿": true, + "⪁": true, + "⪃": true, + "⋚︀": true, + "⪓": true, + "⪅": true, + "⋖": true, + "⋚": true, + "⪋": true, + "≶": true, + "≲": true, + "⥼": true, + "⌊": true, + "𝔩": true, + "≶": true, + "⪑": true, + "↽": true, + "↼": true, + "⥪": true, + "▄": true, + "љ": true, + "≪": true, + "⇇": true, + "⌞": true, + "⥫": true, + "◺": true, + "ŀ": true, + "⎰": true, + "⎰": true, + "≨": true, + "⪉": true, + "⪉": true, + "⪇": true, + "⪇": true, + "≨": true, + "⋦": true, + "⟬": true, + "⇽": true, + "⟦": true, + "⟵": true, + "⟷": true, + "⟼": true, + "⟶": true, + "↫": true, + "↬": true, + "⦅": true, + "𝕝": true, + "⨭": true, + "⨴": true, + "∗": true, + "_": true, + "◊": true, + "◊": true, + "⧫": true, + "(": true, + "⦓": true, + "⇆": true, + "⌟": true, + "⇋": true, + "⥭": true, + "‎": true, + "⊿": true, + "‹": true, + "𝓁": true, + "↰": true, + "≲": true, + "⪍": true, + "⪏": true, + "[": true, + "‘": true, + "‚": true, + "ł": true, + "<": true, + "<": true, + "⪦": true, + "⩹": true, + "⋖": true, + "⋋": true, + "⋉": true, + "⥶": true, + "⩻": true, + "⦖": true, + "◃": true, + "⊴": true, + "◂": true, + "⥊": true, + "⥦": true, + "≨︀": true, + "≨︀": true, + "∺": true, + "¯": true, + "¯": true, + "♂": true, + "✠": true, + "✠": true, + "↦": true, + "↦": true, + "↧": true, + "↤": true, + "↥": true, + "▮": true, + "⨩": true, + "м": true, + "—": true, + "∡": true, + "𝔪": true, + "℧": true, + "µ": true, + "µ": true, + "∣": true, + "*": true, + "⫰": true, + "·": true, + "·": true, + "−": true, + "⊟": true, + "∸": true, + "⨪": true, + "⫛": true, + "…": true, + "∓": true, + "⊧": true, + "𝕞": true, + "∓": true, + "𝓂": true, + "∾": true, + "μ": true, + "⊸": true, + "⊸": true, + "⋙̸": true, + "≫⃒": true, + "≫̸": true, + "⇍": true, + "⇎": true, + "⋘̸": true, + "≪⃒": true, + "≪̸": true, + "⇏": true, + "⊯": true, + "⊮": true, + "∇": true, + "ń": true, + "∠⃒": true, + "≉": true, + "⩰̸": true, + "≋̸": true, + "ʼn": true, + "≉": true, + "♮": true, + "♮": true, + "ℕ": true, + " ": true, + " ": true, + "≎̸": true, + "≏̸": true, + "⩃": true, + "ň": true, + "ņ": true, + "≇": true, + "⩭̸": true, + "⩂": true, + "н": true, + "–": true, + "≠": true, + "⇗": true, + "⤤": true, + "↗": true, + "↗": true, + "≐̸": true, + "≢": true, + "⤨": true, + "≂̸": true, + "∄": true, + "∄": true, + "𝔫": true, + "≧̸": true, + "≱": true, + "≱": true, + "≧̸": true, + "⩾̸": true, + "⩾̸": true, + "≵": true, + "≯": true, + "≯": true, + "⇎": true, + "↮": true, + "⫲": true, + "∋": true, + "⋼": true, + "⋺": true, + "∋": true, + "њ": true, + "⇍": true, + "≦̸": true, + "↚": true, + "‥": true, + "≰": true, + "↚": true, + "↮": true, + "≰": true, + "≦̸": true, + "⩽̸": true, + "⩽̸": true, + "≮": true, + "≴": true, + "≮": true, + "⋪": true, + "⋬": true, + "∤": true, + "𝕟": true, + "¬": true, + "¬": true, + "∉": true, + "⋹̸": true, + "⋵̸": true, + "∉": true, + "⋷": true, + "⋶": true, + "∌": true, + "∌": true, + "⋾": true, + "⋽": true, + "∦": true, + "∦": true, + "⫽⃥": true, + "∂̸": true, + "⨔": true, + "⊀": true, + "⋠": true, + "⪯̸": true, + "⊀": true, + "⪯̸": true, + "⇏": true, + "↛": true, + "⤳̸": true, + "↝̸": true, + "↛": true, + "⋫": true, + "⋭": true, + "⊁": true, + "⋡": true, + "⪰̸": true, + "𝓃": true, + "∤": true, + "∦": true, + "≁": true, + "≄": true, + "≄": true, + "∤": true, + "∦": true, + "⋢": true, + "⋣": true, + "⊄": true, + "⫅̸": true, + "⊈": true, + "⊂⃒": true, + "⊈": true, + "⫅̸": true, + "⊁": true, + "⪰̸": true, + "⊅": true, + "⫆̸": true, + "⊉": true, + "⊃⃒": true, + "⊉": true, + "⫆̸": true, + "≹": true, + "ñ": true, + "ñ": true, + "≸": true, + "⋪": true, + "⋬": true, + "⋫": true, + "⋭": true, + "ν": true, + "#": true, + "№": true, + " ": true, + "⊭": true, + "⤄": true, + "≍⃒": true, + "⊬": true, + "≥⃒": true, + ">⃒": true, + "⧞": true, + "⤂": true, + "≤⃒": true, + "<⃒": true, + "⊴⃒": true, + "⤃": true, + "⊵⃒": true, + "∼⃒": true, + "⇖": true, + "⤣": true, + "↖": true, + "↖": true, + "⤧": true, + "Ⓢ": true, + "ó": true, + "ó": true, + "⊛": true, + "⊚": true, + "ô": true, + "ô": true, + "о": true, + "⊝": true, + "ő": true, + "⨸": true, + "⊙": true, + "⦼": true, + "œ": true, + "⦿": true, + "𝔬": true, + "˛": true, + "ò": true, + "ò": true, + "⧁": true, + "⦵": true, + "Ω": true, + "∮": true, + "↺": true, + "⦾": true, + "⦻": true, + "‾": true, + "⧀": true, + "ō": true, + "ω": true, + "ο": true, + "⦶": true, + "⊖": true, + "𝕠": true, + "⦷": true, + "⦹": true, + "⊕": true, + "∨": true, + "↻": true, + "⩝": true, + "ℴ": true, + "ℴ": true, + "ª": true, + "ª": true, + "º": true, + "º": true, + "⊶": true, + "⩖": true, + "⩗": true, + "⩛": true, + "ℴ": true, + "ø": true, + "ø": true, + "⊘": true, + "õ": true, + "õ": true, + "⊗": true, + "⨶": true, + "ö": true, + "ö": true, + "⌽": true, + "∥": true, + "¶": true, + "¶": true, + "∥": true, + "⫳": true, + "⫽": true, + "∂": true, + "п": true, + "%": true, + ".": true, + "‰": true, + "⊥": true, + "‱": true, + "𝔭": true, + "φ": true, + "ϕ": true, + "ℳ": true, + "☎": true, + "π": true, + "⋔": true, + "ϖ": true, + "ℏ": true, + "ℎ": true, + "ℏ": true, + "+": true, + "⨣": true, + "⊞": true, + "⨢": true, + "∔": true, + "⨥": true, + "⩲": true, + "±": true, + "±": true, + "⨦": true, + "⨧": true, + "±": true, + "⨕": true, + "𝕡": true, + "£": true, + "£": true, + "≺": true, + "⪳": true, + "⪷": true, + "≼": true, + "⪯": true, + "≺": true, + "⪷": true, + "≼": true, + "⪯": true, + "⪹": true, + "⪵": true, + "⋨": true, + "≾": true, + "′": true, + "ℙ": true, + "⪵": true, + "⪹": true, + "⋨": true, + "∏": true, + "⌮": true, + "⌒": true, + "⌓": true, + "∝": true, + "∝": true, + "≾": true, + "⊰": true, + "𝓅": true, + "ψ": true, + " ": true, + "𝔮": true, + "⨌": true, + "𝕢": true, + "⁗": true, + "𝓆": true, + "ℍ": true, + "⨖": true, + "?": true, + "≟": true, + """: true, + """: true, + "⇛": true, + "⇒": true, + "⤜": true, + "⤏": true, + "⥤": true, + "∽̱": true, + "ŕ": true, + "√": true, + "⦳": true, + "⟩": true, + "⦒": true, + "⦥": true, + "⟩": true, + "»": true, + "»": true, + "→": true, + "⥵": true, + "⇥": true, + "⤠": true, + "⤳": true, + "⤞": true, + "↪": true, + "↬": true, + "⥅": true, + "⥴": true, + "↣": true, + "↝": true, + "⤚": true, + "∶": true, + "ℚ": true, + "⤍": true, + "❳": true, + "}": true, + "]": true, + "⦌": true, + "⦎": true, + "⦐": true, + "ř": true, + "ŗ": true, + "⌉": true, + "}": true, + "р": true, + "⤷": true, + "⥩": true, + "”": true, + "”": true, + "↳": true, + "ℜ": true, + "ℛ": true, + "ℜ": true, + "ℝ": true, + "▭": true, + "®": true, + "®": true, + "⥽": true, + "⌋": true, + "𝔯": true, + "⇁": true, + "⇀": true, + "⥬": true, + "ρ": true, + "ϱ": true, + "→": true, + "↣": true, + "⇁": true, + "⇀": true, + "⇄": true, + "⇌": true, + "⇉": true, + "↝": true, + "⋌": true, + "˚": true, + "≓": true, + "⇄": true, + "⇌": true, + "‏": true, + "⎱": true, + "⎱": true, + "⫮": true, + "⟭": true, + "⇾": true, + "⟧": true, + "⦆": true, + "𝕣": true, + "⨮": true, + "⨵": true, + ")": true, + "⦔": true, + "⨒": true, + "⇉": true, + "›": true, + "𝓇": true, + "↱": true, + "]": true, + "’": true, + "’": true, + "⋌": true, + "⋊": true, + "▹": true, + "⊵": true, + "▸": true, + "⧎": true, + "⥨": true, + "℞": true, + "ś": true, + "‚": true, + "≻": true, + "⪴": true, + "⪸": true, + "š": true, + "≽": true, + "⪰": true, + "ş": true, + "ŝ": true, + "⪶": true, + "⪺": true, + "⋩": true, + "⨓": true, + "≿": true, + "с": true, + "⋅": true, + "⊡": true, + "⩦": true, + "⇘": true, + "⤥": true, + "↘": true, + "↘": true, + "§": true, + "§": true, + ";": true, + "⤩": true, + "∖": true, + "∖": true, + "✶": true, + "𝔰": true, + "⌢": true, + "♯": true, + "щ": true, + "ш": true, + "∣": true, + "∥": true, + "­": true, + "­": true, + "σ": true, + "ς": true, + "ς": true, + "∼": true, + "⩪": true, + "≃": true, + "≃": true, + "⪞": true, + "⪠": true, + "⪝": true, + "⪟": true, + "≆": true, + "⨤": true, + "⥲": true, + "←": true, + "∖": true, + "⨳": true, + "⧤": true, + "∣": true, + "⌣": true, + "⪪": true, + "⪬": true, + "⪬︀": true, + "ь": true, + "/": true, + "⧄": true, + "⌿": true, + "𝕤": true, + "♠": true, + "♠": true, + "∥": true, + "⊓": true, + "⊓︀": true, + "⊔": true, + "⊔︀": true, + "⊏": true, + "⊑": true, + "⊏": true, + "⊑": true, + "⊐": true, + "⊒": true, + "⊐": true, + "⊒": true, + "□": true, + "□": true, + "▪": true, + "▪": true, + "→": true, + "𝓈": true, + "∖": true, + "⌣": true, + "⋆": true, + "☆": true, + "★": true, + "ϵ": true, + "ϕ": true, + "¯": true, + "⊂": true, + "⫅": true, + "⪽": true, + "⊆": true, + "⫃": true, + "⫁": true, + "⫋": true, + "⊊": true, + "⪿": true, + "⥹": true, + "⊂": true, + "⊆": true, + "⫅": true, + "⊊": true, + "⫋": true, + "⫇": true, + "⫕": true, + "⫓": true, + "≻": true, + "⪸": true, + "≽": true, + "⪰": true, + "⪺": true, + "⪶": true, + "⋩": true, + "≿": true, + "∑": true, + "♪": true, + "¹": true, + "¹": true, + "²": true, + "²": true, + "³": true, + "³": true, + "⊃": true, + "⫆": true, + "⪾": true, + "⫘": true, + "⊇": true, + "⫄": true, + "⟉": true, + "⫗": true, + "⥻": true, + "⫂": true, + "⫌": true, + "⊋": true, + "⫀": true, + "⊃": true, + "⊇": true, + "⫆": true, + "⊋": true, + "⫌": true, + "⫈": true, + "⫔": true, + "⫖": true, + "⇙": true, + "⤦": true, + "↙": true, + "↙": true, + "⤪": true, + "ß": true, + "ß": true, + "⌖": true, + "τ": true, + "⎴": true, + "ť": true, + "ţ": true, + "т": true, + "⃛": true, + "⌕": true, + "𝔱": true, + "∴": true, + "∴": true, + "θ": true, + "ϑ": true, + "ϑ": true, + "≈": true, + "∼": true, + " ": true, + "≈": true, + "∼": true, + "þ": true, + "þ": true, + "˜": true, + "×": true, + "×": true, + "⊠": true, + "⨱": true, + "⨰": true, + "∭": true, + "⤨": true, + "⊤": true, + "⌶": true, + "⫱": true, + "𝕥": true, + "⫚": true, + "⤩": true, + "‴": true, + "™": true, + "▵": true, + "▿": true, + "◃": true, + "⊴": true, + "≜": true, + "▹": true, + "⊵": true, + "◬": true, + "≜": true, + "⨺": true, + "⨹": true, + "⧍": true, + "⨻": true, + "⏢": true, + "𝓉": true, + "ц": true, + "ћ": true, + "ŧ": true, + "≬": true, + "↞": true, + "↠": true, + "⇑": true, + "⥣": true, + "ú": true, + "ú": true, + "↑": true, + "ў": true, + "ŭ": true, + "û": true, + "û": true, + "у": true, + "⇅": true, + "ű": true, + "⥮": true, + "⥾": true, + "𝔲": true, + "ù": true, + "ù": true, + "↿": true, + "↾": true, + "▀": true, + "⌜": true, + "⌜": true, + "⌏": true, + "◸": true, + "ū": true, + "¨": true, + "¨": true, + "ų": true, + "𝕦": true, + "↑": true, + "↕": true, + "↿": true, + "↾": true, + "⊎": true, + "υ": true, + "ϒ": true, + "υ": true, + "⇈": true, + "⌝": true, + "⌝": true, + "⌎": true, + "ů": true, + "◹": true, + "𝓊": true, + "⋰": true, + "ũ": true, + "▵": true, + "▴": true, + "⇈": true, + "ü": true, + "ü": true, + "⦧": true, + "⇕": true, + "⫨": true, + "⫩": true, + "⊨": true, + "⦜": true, + "ϵ": true, + "ϰ": true, + "∅": true, + "ϕ": true, + "ϖ": true, + "∝": true, + "↕": true, + "ϱ": true, + "ς": true, + "⊊︀": true, + "⫋︀": true, + "⊋︀": true, + "⫌︀": true, + "ϑ": true, + "⊲": true, + "⊳": true, + "в": true, + "⊢": true, + "∨": true, + "⊻": true, + "≚": true, + "⋮": true, + "|": true, + "|": true, + "𝔳": true, + "⊲": true, + "⊂⃒": true, + "⊃⃒": true, + "𝕧": true, + "∝": true, + "⊳": true, + "𝓋": true, + "⫋︀": true, + "⊊︀": true, + "⫌︀": true, + "⊋︀": true, + "⦚": true, + "ŵ": true, + "⩟": true, + "∧": true, + "≙": true, + "℘": true, + "𝔴": true, + "𝕨": true, + "℘": true, + "≀": true, + "≀": true, + "𝓌": true, + "⋂": true, + "◯": true, + "⋃": true, + "▽": true, + "𝔵": true, + "⟺": true, + "⟷": true, + "ξ": true, + "⟸": true, + "⟵": true, + "⟼": true, + "⋻": true, + "⨀": true, + "𝕩": true, + "⨁": true, + "⨂": true, + "⟹": true, + "⟶": true, + "𝓍": true, + "⨆": true, + "⨄": true, + "△": true, + "⋁": true, + "⋀": true, + "ý": true, + "ý": true, + "я": true, + "ŷ": true, + "ы": true, + "¥": true, + "¥": true, + "𝔶": true, + "ї": true, + "𝕪": true, + "𝓎": true, + "ю": true, + "ÿ": true, + "ÿ": true, + "ź": true, + "ž": true, + "з": true, + "ż": true, + "ℨ": true, + "ζ": true, + "𝔷": true, + "ж": true, + "⇝": true, + "𝕫": true, + "𝓏": true, + "‍": true, + "‌": true, +} diff --git a/vendor/github.com/russross/blackfriday/v2/esc.go b/vendor/github.com/russross/blackfriday/v2/esc.go new file mode 100644 index 0000000000..6ab60102c9 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/esc.go @@ -0,0 +1,70 @@ +package blackfriday + +import ( + "html" + "io" +) + +var htmlEscaper = [256][]byte{ + '&': []byte("&"), + '<': []byte("<"), + '>': []byte(">"), + '"': []byte("""), +} + +func escapeHTML(w io.Writer, s []byte) { + escapeEntities(w, s, false) +} + +func escapeAllHTML(w io.Writer, s []byte) { + escapeEntities(w, s, true) +} + +func escapeEntities(w io.Writer, s []byte, escapeValidEntities bool) { + var start, end int + for end < len(s) { + escSeq := htmlEscaper[s[end]] + if escSeq != nil { + isEntity, entityEnd := nodeIsEntity(s, end) + if isEntity && !escapeValidEntities { + w.Write(s[start : entityEnd+1]) + start = entityEnd + 1 + } else { + w.Write(s[start:end]) + w.Write(escSeq) + start = end + 1 + } + } + end++ + } + if start < len(s) && end <= len(s) { + w.Write(s[start:end]) + } +} + +func nodeIsEntity(s []byte, end int) (isEntity bool, endEntityPos int) { + isEntity = false + endEntityPos = end + 1 + + if s[end] == '&' { + for endEntityPos < len(s) { + if s[endEntityPos] == ';' { + if entities[string(s[end:endEntityPos+1])] { + isEntity = true + break + } + } + if !isalnum(s[endEntityPos]) && s[endEntityPos] != '&' && s[endEntityPos] != '#' { + break + } + endEntityPos++ + } + } + + return isEntity, endEntityPos +} + +func escLink(w io.Writer, text []byte) { + unesc := html.UnescapeString(string(text)) + escapeHTML(w, []byte(unesc)) +} diff --git a/vendor/github.com/russross/blackfriday/v2/html.go b/vendor/github.com/russross/blackfriday/v2/html.go new file mode 100644 index 0000000000..cb4f26e30f --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/html.go @@ -0,0 +1,952 @@ +// +// Blackfriday Markdown Processor +// Available at http://github.com/russross/blackfriday +// +// Copyright © 2011 Russ Ross . +// Distributed under the Simplified BSD License. +// See README.md for details. +// + +// +// +// HTML rendering backend +// +// + +package blackfriday + +import ( + "bytes" + "fmt" + "io" + "regexp" + "strings" +) + +// HTMLFlags control optional behavior of HTML renderer. +type HTMLFlags int + +// HTML renderer configuration options. +const ( + HTMLFlagsNone HTMLFlags = 0 + SkipHTML HTMLFlags = 1 << iota // Skip preformatted HTML blocks + SkipImages // Skip embedded images + SkipLinks // Skip all links + Safelink // Only link to trusted protocols + NofollowLinks // Only link with rel="nofollow" + NoreferrerLinks // Only link with rel="noreferrer" + NoopenerLinks // Only link with rel="noopener" + HrefTargetBlank // Add a blank target + CompletePage // Generate a complete HTML page + UseXHTML // Generate XHTML output instead of HTML + FootnoteReturnLinks // Generate a link at the end of a footnote to return to the source + Smartypants // Enable smart punctuation substitutions + SmartypantsFractions // Enable smart fractions (with Smartypants) + SmartypantsDashes // Enable smart dashes (with Smartypants) + SmartypantsLatexDashes // Enable LaTeX-style dashes (with Smartypants) + SmartypantsAngledQuotes // Enable angled double quotes (with Smartypants) for double quotes rendering + SmartypantsQuotesNBSP // Enable « French guillemets » (with Smartypants) + TOC // Generate a table of contents +) + +var ( + htmlTagRe = regexp.MustCompile("(?i)^" + htmlTag) +) + +const ( + htmlTag = "(?:" + openTag + "|" + closeTag + "|" + htmlComment + "|" + + processingInstruction + "|" + declaration + "|" + cdata + ")" + closeTag = "]" + openTag = "<" + tagName + attribute + "*" + "\\s*/?>" + attribute = "(?:" + "\\s+" + attributeName + attributeValueSpec + "?)" + attributeValue = "(?:" + unquotedValue + "|" + singleQuotedValue + "|" + doubleQuotedValue + ")" + attributeValueSpec = "(?:" + "\\s*=" + "\\s*" + attributeValue + ")" + attributeName = "[a-zA-Z_:][a-zA-Z0-9:._-]*" + cdata = "" + declaration = "]*>" + doubleQuotedValue = "\"[^\"]*\"" + htmlComment = "|" + processingInstruction = "[<][?].*?[?][>]" + singleQuotedValue = "'[^']*'" + tagName = "[A-Za-z][A-Za-z0-9-]*" + unquotedValue = "[^\"'=<>`\\x00-\\x20]+" +) + +// HTMLRendererParameters is a collection of supplementary parameters tweaking +// the behavior of various parts of HTML renderer. +type HTMLRendererParameters struct { + // Prepend this text to each relative URL. + AbsolutePrefix string + // Add this text to each footnote anchor, to ensure uniqueness. + FootnoteAnchorPrefix string + // Show this text inside the
      tag for a footnote return link, if the + // HTML_FOOTNOTE_RETURN_LINKS flag is enabled. If blank, the string + // [return] is used. + FootnoteReturnLinkContents string + // If set, add this text to the front of each Heading ID, to ensure + // uniqueness. + HeadingIDPrefix string + // If set, add this text to the back of each Heading ID, to ensure uniqueness. + HeadingIDSuffix string + // Increase heading levels: if the offset is 1,

      becomes

      etc. + // Negative offset is also valid. + // Resulting levels are clipped between 1 and 6. + HeadingLevelOffset int + + Title string // Document title (used if CompletePage is set) + CSS string // Optional CSS file URL (used if CompletePage is set) + Icon string // Optional icon file URL (used if CompletePage is set) + + Flags HTMLFlags // Flags allow customizing this renderer's behavior +} + +// HTMLRenderer is a type that implements the Renderer interface for HTML output. +// +// Do not create this directly, instead use the NewHTMLRenderer function. +type HTMLRenderer struct { + HTMLRendererParameters + + closeTag string // how to end singleton tags: either " />" or ">" + + // Track heading IDs to prevent ID collision in a single generation. + headingIDs map[string]int + + lastOutputLen int + disableTags int + + sr *SPRenderer +} + +const ( + xhtmlClose = " />" + htmlClose = ">" +) + +// NewHTMLRenderer creates and configures an HTMLRenderer object, which +// satisfies the Renderer interface. +func NewHTMLRenderer(params HTMLRendererParameters) *HTMLRenderer { + // configure the rendering engine + closeTag := htmlClose + if params.Flags&UseXHTML != 0 { + closeTag = xhtmlClose + } + + if params.FootnoteReturnLinkContents == "" { + // U+FE0E is VARIATION SELECTOR-15. + // It suppresses automatic emoji presentation of the preceding + // U+21A9 LEFTWARDS ARROW WITH HOOK on iOS and iPadOS. + params.FootnoteReturnLinkContents = "↩\ufe0e" + } + + return &HTMLRenderer{ + HTMLRendererParameters: params, + + closeTag: closeTag, + headingIDs: make(map[string]int), + + sr: NewSmartypantsRenderer(params.Flags), + } +} + +func isHTMLTag(tag []byte, tagname string) bool { + found, _ := findHTMLTagPos(tag, tagname) + return found +} + +// Look for a character, but ignore it when it's in any kind of quotes, it +// might be JavaScript +func skipUntilCharIgnoreQuotes(html []byte, start int, char byte) int { + inSingleQuote := false + inDoubleQuote := false + inGraveQuote := false + i := start + for i < len(html) { + switch { + case html[i] == char && !inSingleQuote && !inDoubleQuote && !inGraveQuote: + return i + case html[i] == '\'': + inSingleQuote = !inSingleQuote + case html[i] == '"': + inDoubleQuote = !inDoubleQuote + case html[i] == '`': + inGraveQuote = !inGraveQuote + } + i++ + } + return start +} + +func findHTMLTagPos(tag []byte, tagname string) (bool, int) { + i := 0 + if i < len(tag) && tag[0] != '<' { + return false, -1 + } + i++ + i = skipSpace(tag, i) + + if i < len(tag) && tag[i] == '/' { + i++ + } + + i = skipSpace(tag, i) + j := 0 + for ; i < len(tag); i, j = i+1, j+1 { + if j >= len(tagname) { + break + } + + if strings.ToLower(string(tag[i]))[0] != tagname[j] { + return false, -1 + } + } + + if i == len(tag) { + return false, -1 + } + + rightAngle := skipUntilCharIgnoreQuotes(tag, i, '>') + if rightAngle >= i { + return true, rightAngle + } + + return false, -1 +} + +func skipSpace(tag []byte, i int) int { + for i < len(tag) && isspace(tag[i]) { + i++ + } + return i +} + +func isRelativeLink(link []byte) (yes bool) { + // a tag begin with '#' + if link[0] == '#' { + return true + } + + // link begin with '/' but not '//', the second maybe a protocol relative link + if len(link) >= 2 && link[0] == '/' && link[1] != '/' { + return true + } + + // only the root '/' + if len(link) == 1 && link[0] == '/' { + return true + } + + // current directory : begin with "./" + if bytes.HasPrefix(link, []byte("./")) { + return true + } + + // parent directory : begin with "../" + if bytes.HasPrefix(link, []byte("../")) { + return true + } + + return false +} + +func (r *HTMLRenderer) ensureUniqueHeadingID(id string) string { + for count, found := r.headingIDs[id]; found; count, found = r.headingIDs[id] { + tmp := fmt.Sprintf("%s-%d", id, count+1) + + if _, tmpFound := r.headingIDs[tmp]; !tmpFound { + r.headingIDs[id] = count + 1 + id = tmp + } else { + id = id + "-1" + } + } + + if _, found := r.headingIDs[id]; !found { + r.headingIDs[id] = 0 + } + + return id +} + +func (r *HTMLRenderer) addAbsPrefix(link []byte) []byte { + if r.AbsolutePrefix != "" && isRelativeLink(link) && link[0] != '.' { + newDest := r.AbsolutePrefix + if link[0] != '/' { + newDest += "/" + } + newDest += string(link) + return []byte(newDest) + } + return link +} + +func appendLinkAttrs(attrs []string, flags HTMLFlags, link []byte) []string { + if isRelativeLink(link) { + return attrs + } + val := []string{} + if flags&NofollowLinks != 0 { + val = append(val, "nofollow") + } + if flags&NoreferrerLinks != 0 { + val = append(val, "noreferrer") + } + if flags&NoopenerLinks != 0 { + val = append(val, "noopener") + } + if flags&HrefTargetBlank != 0 { + attrs = append(attrs, "target=\"_blank\"") + } + if len(val) == 0 { + return attrs + } + attr := fmt.Sprintf("rel=%q", strings.Join(val, " ")) + return append(attrs, attr) +} + +func isMailto(link []byte) bool { + return bytes.HasPrefix(link, []byte("mailto:")) +} + +func needSkipLink(flags HTMLFlags, dest []byte) bool { + if flags&SkipLinks != 0 { + return true + } + return flags&Safelink != 0 && !isSafeLink(dest) && !isMailto(dest) +} + +func isSmartypantable(node *Node) bool { + pt := node.Parent.Type + return pt != Link && pt != CodeBlock && pt != Code +} + +func appendLanguageAttr(attrs []string, info []byte) []string { + if len(info) == 0 { + return attrs + } + endOfLang := bytes.IndexAny(info, "\t ") + if endOfLang < 0 { + endOfLang = len(info) + } + return append(attrs, fmt.Sprintf("class=\"language-%s\"", info[:endOfLang])) +} + +func (r *HTMLRenderer) tag(w io.Writer, name []byte, attrs []string) { + w.Write(name) + if len(attrs) > 0 { + w.Write(spaceBytes) + w.Write([]byte(strings.Join(attrs, " "))) + } + w.Write(gtBytes) + r.lastOutputLen = 1 +} + +func footnoteRef(prefix string, node *Node) []byte { + urlFrag := prefix + string(slugify(node.Destination)) + anchor := fmt.Sprintf(`%d`, urlFrag, node.NoteID) + return []byte(fmt.Sprintf(`%s`, urlFrag, anchor)) +} + +func footnoteItem(prefix string, slug []byte) []byte { + return []byte(fmt.Sprintf(`
    1. `, prefix, slug)) +} + +func footnoteReturnLink(prefix, returnLink string, slug []byte) []byte { + const format = ` %s` + return []byte(fmt.Sprintf(format, prefix, slug, returnLink)) +} + +func itemOpenCR(node *Node) bool { + if node.Prev == nil { + return false + } + ld := node.Parent.ListData + return !ld.Tight && ld.ListFlags&ListTypeDefinition == 0 +} + +func skipParagraphTags(node *Node) bool { + grandparent := node.Parent.Parent + if grandparent == nil || grandparent.Type != List { + return false + } + tightOrTerm := grandparent.Tight || node.Parent.ListFlags&ListTypeTerm != 0 + return grandparent.Type == List && tightOrTerm +} + +func cellAlignment(align CellAlignFlags) string { + switch align { + case TableAlignmentLeft: + return "left" + case TableAlignmentRight: + return "right" + case TableAlignmentCenter: + return "center" + default: + return "" + } +} + +func (r *HTMLRenderer) out(w io.Writer, text []byte) { + if r.disableTags > 0 { + w.Write(htmlTagRe.ReplaceAll(text, []byte{})) + } else { + w.Write(text) + } + r.lastOutputLen = len(text) +} + +func (r *HTMLRenderer) cr(w io.Writer) { + if r.lastOutputLen > 0 { + r.out(w, nlBytes) + } +} + +var ( + nlBytes = []byte{'\n'} + gtBytes = []byte{'>'} + spaceBytes = []byte{' '} +) + +var ( + brTag = []byte("
      ") + brXHTMLTag = []byte("
      ") + emTag = []byte("") + emCloseTag = []byte("") + strongTag = []byte("") + strongCloseTag = []byte("") + delTag = []byte("") + delCloseTag = []byte("") + ttTag = []byte("") + ttCloseTag = []byte("") + aTag = []byte("") + preTag = []byte("
      ")
      +	preCloseTag        = []byte("
      ") + codeTag = []byte("") + codeCloseTag = []byte("") + pTag = []byte("

      ") + pCloseTag = []byte("

      ") + blockquoteTag = []byte("
      ") + blockquoteCloseTag = []byte("
      ") + hrTag = []byte("
      ") + hrXHTMLTag = []byte("
      ") + ulTag = []byte("
        ") + ulCloseTag = []byte("
      ") + olTag = []byte("
        ") + olCloseTag = []byte("
      ") + dlTag = []byte("
      ") + dlCloseTag = []byte("
      ") + liTag = []byte("
    2. ") + liCloseTag = []byte("
    3. ") + ddTag = []byte("
      ") + ddCloseTag = []byte("
      ") + dtTag = []byte("
      ") + dtCloseTag = []byte("
      ") + tableTag = []byte("") + tableCloseTag = []byte("
      ") + tdTag = []byte("") + thTag = []byte("") + theadTag = []byte("") + theadCloseTag = []byte("") + tbodyTag = []byte("") + tbodyCloseTag = []byte("") + trTag = []byte("") + trCloseTag = []byte("") + h1Tag = []byte("") + h2Tag = []byte("") + h3Tag = []byte("") + h4Tag = []byte("") + h5Tag = []byte("") + h6Tag = []byte("") + + footnotesDivBytes = []byte("\n
      \n\n") + footnotesCloseDivBytes = []byte("\n
      \n") +) + +func headingTagsFromLevel(level int) ([]byte, []byte) { + if level <= 1 { + return h1Tag, h1CloseTag + } + switch level { + case 2: + return h2Tag, h2CloseTag + case 3: + return h3Tag, h3CloseTag + case 4: + return h4Tag, h4CloseTag + case 5: + return h5Tag, h5CloseTag + } + return h6Tag, h6CloseTag +} + +func (r *HTMLRenderer) outHRTag(w io.Writer) { + if r.Flags&UseXHTML == 0 { + r.out(w, hrTag) + } else { + r.out(w, hrXHTMLTag) + } +} + +// RenderNode is a default renderer of a single node of a syntax tree. For +// block nodes it will be called twice: first time with entering=true, second +// time with entering=false, so that it could know when it's working on an open +// tag and when on close. It writes the result to w. +// +// The return value is a way to tell the calling walker to adjust its walk +// pattern: e.g. it can terminate the traversal by returning Terminate. Or it +// can ask the walker to skip a subtree of this node by returning SkipChildren. +// The typical behavior is to return GoToNext, which asks for the usual +// traversal to the next node. +func (r *HTMLRenderer) RenderNode(w io.Writer, node *Node, entering bool) WalkStatus { + attrs := []string{} + switch node.Type { + case Text: + if r.Flags&Smartypants != 0 { + var tmp bytes.Buffer + escapeHTML(&tmp, node.Literal) + r.sr.Process(w, tmp.Bytes()) + } else { + if node.Parent.Type == Link { + escLink(w, node.Literal) + } else { + escapeHTML(w, node.Literal) + } + } + case Softbreak: + r.cr(w) + // TODO: make it configurable via out(renderer.softbreak) + case Hardbreak: + if r.Flags&UseXHTML == 0 { + r.out(w, brTag) + } else { + r.out(w, brXHTMLTag) + } + r.cr(w) + case Emph: + if entering { + r.out(w, emTag) + } else { + r.out(w, emCloseTag) + } + case Strong: + if entering { + r.out(w, strongTag) + } else { + r.out(w, strongCloseTag) + } + case Del: + if entering { + r.out(w, delTag) + } else { + r.out(w, delCloseTag) + } + case HTMLSpan: + if r.Flags&SkipHTML != 0 { + break + } + r.out(w, node.Literal) + case Link: + // mark it but don't link it if it is not a safe link: no smartypants + dest := node.LinkData.Destination + if needSkipLink(r.Flags, dest) { + if entering { + r.out(w, ttTag) + } else { + r.out(w, ttCloseTag) + } + } else { + if entering { + dest = r.addAbsPrefix(dest) + var hrefBuf bytes.Buffer + hrefBuf.WriteString("href=\"") + escLink(&hrefBuf, dest) + hrefBuf.WriteByte('"') + attrs = append(attrs, hrefBuf.String()) + if node.NoteID != 0 { + r.out(w, footnoteRef(r.FootnoteAnchorPrefix, node)) + break + } + attrs = appendLinkAttrs(attrs, r.Flags, dest) + if len(node.LinkData.Title) > 0 { + var titleBuff bytes.Buffer + titleBuff.WriteString("title=\"") + escapeHTML(&titleBuff, node.LinkData.Title) + titleBuff.WriteByte('"') + attrs = append(attrs, titleBuff.String()) + } + r.tag(w, aTag, attrs) + } else { + if node.NoteID != 0 { + break + } + r.out(w, aCloseTag) + } + } + case Image: + if r.Flags&SkipImages != 0 { + return SkipChildren + } + if entering { + dest := node.LinkData.Destination + dest = r.addAbsPrefix(dest) + if r.disableTags == 0 { + //if options.safe && potentiallyUnsafe(dest) { + //out(w, ``)
+				//} else {
+				r.out(w, []byte(`<img src=`)) + } + } + case Code: + r.out(w, codeTag) + escapeAllHTML(w, node.Literal) + r.out(w, codeCloseTag) + case Document: + break + case Paragraph: + if skipParagraphTags(node) { + break + } + if entering { + // TODO: untangle this clusterfuck about when the newlines need + // to be added and when not. + if node.Prev != nil { + switch node.Prev.Type { + case HTMLBlock, List, Paragraph, Heading, CodeBlock, BlockQuote, HorizontalRule: + r.cr(w) + } + } + if node.Parent.Type == BlockQuote && node.Prev == nil { + r.cr(w) + } + r.out(w, pTag) + } else { + r.out(w, pCloseTag) + if !(node.Parent.Type == Item && node.Next == nil) { + r.cr(w) + } + } + case BlockQuote: + if entering { + r.cr(w) + r.out(w, blockquoteTag) + } else { + r.out(w, blockquoteCloseTag) + r.cr(w) + } + case HTMLBlock: + if r.Flags&SkipHTML != 0 { + break + } + r.cr(w) + r.out(w, node.Literal) + r.cr(w) + case Heading: + headingLevel := r.HTMLRendererParameters.HeadingLevelOffset + node.Level + openTag, closeTag := headingTagsFromLevel(headingLevel) + if entering { + if node.IsTitleblock { + attrs = append(attrs, `class="title"`) + } + if node.HeadingID != "" { + id := r.ensureUniqueHeadingID(node.HeadingID) + if r.HeadingIDPrefix != "" { + id = r.HeadingIDPrefix + id + } + if r.HeadingIDSuffix != "" { + id = id + r.HeadingIDSuffix + } + attrs = append(attrs, fmt.Sprintf(`id="%s"`, id)) + } + r.cr(w) + r.tag(w, openTag, attrs) + } else { + r.out(w, closeTag) + if !(node.Parent.Type == Item && node.Next == nil) { + r.cr(w) + } + } + case HorizontalRule: + r.cr(w) + r.outHRTag(w) + r.cr(w) + case List: + openTag := ulTag + closeTag := ulCloseTag + if node.ListFlags&ListTypeOrdered != 0 { + openTag = olTag + closeTag = olCloseTag + } + if node.ListFlags&ListTypeDefinition != 0 { + openTag = dlTag + closeTag = dlCloseTag + } + if entering { + if node.IsFootnotesList { + r.out(w, footnotesDivBytes) + r.outHRTag(w) + r.cr(w) + } + r.cr(w) + if node.Parent.Type == Item && node.Parent.Parent.Tight { + r.cr(w) + } + r.tag(w, openTag[:len(openTag)-1], attrs) + r.cr(w) + } else { + r.out(w, closeTag) + //cr(w) + //if node.parent.Type != Item { + // cr(w) + //} + if node.Parent.Type == Item && node.Next != nil { + r.cr(w) + } + if node.Parent.Type == Document || node.Parent.Type == BlockQuote { + r.cr(w) + } + if node.IsFootnotesList { + r.out(w, footnotesCloseDivBytes) + } + } + case Item: + openTag := liTag + closeTag := liCloseTag + if node.ListFlags&ListTypeDefinition != 0 { + openTag = ddTag + closeTag = ddCloseTag + } + if node.ListFlags&ListTypeTerm != 0 { + openTag = dtTag + closeTag = dtCloseTag + } + if entering { + if itemOpenCR(node) { + r.cr(w) + } + if node.ListData.RefLink != nil { + slug := slugify(node.ListData.RefLink) + r.out(w, footnoteItem(r.FootnoteAnchorPrefix, slug)) + break + } + r.out(w, openTag) + } else { + if node.ListData.RefLink != nil { + slug := slugify(node.ListData.RefLink) + if r.Flags&FootnoteReturnLinks != 0 { + r.out(w, footnoteReturnLink(r.FootnoteAnchorPrefix, r.FootnoteReturnLinkContents, slug)) + } + } + r.out(w, closeTag) + r.cr(w) + } + case CodeBlock: + attrs = appendLanguageAttr(attrs, node.Info) + r.cr(w) + r.out(w, preTag) + r.tag(w, codeTag[:len(codeTag)-1], attrs) + escapeAllHTML(w, node.Literal) + r.out(w, codeCloseTag) + r.out(w, preCloseTag) + if node.Parent.Type != Item { + r.cr(w) + } + case Table: + if entering { + r.cr(w) + r.out(w, tableTag) + } else { + r.out(w, tableCloseTag) + r.cr(w) + } + case TableCell: + openTag := tdTag + closeTag := tdCloseTag + if node.IsHeader { + openTag = thTag + closeTag = thCloseTag + } + if entering { + align := cellAlignment(node.Align) + if align != "" { + attrs = append(attrs, fmt.Sprintf(`align="%s"`, align)) + } + if node.Prev == nil { + r.cr(w) + } + r.tag(w, openTag, attrs) + } else { + r.out(w, closeTag) + r.cr(w) + } + case TableHead: + if entering { + r.cr(w) + r.out(w, theadTag) + } else { + r.out(w, theadCloseTag) + r.cr(w) + } + case TableBody: + if entering { + r.cr(w) + r.out(w, tbodyTag) + // XXX: this is to adhere to a rather silly test. Should fix test. + if node.FirstChild == nil { + r.cr(w) + } + } else { + r.out(w, tbodyCloseTag) + r.cr(w) + } + case TableRow: + if entering { + r.cr(w) + r.out(w, trTag) + } else { + r.out(w, trCloseTag) + r.cr(w) + } + default: + panic("Unknown node type " + node.Type.String()) + } + return GoToNext +} + +// RenderHeader writes HTML document preamble and TOC if requested. +func (r *HTMLRenderer) RenderHeader(w io.Writer, ast *Node) { + r.writeDocumentHeader(w) + if r.Flags&TOC != 0 { + r.writeTOC(w, ast) + } +} + +// RenderFooter writes HTML document footer. +func (r *HTMLRenderer) RenderFooter(w io.Writer, ast *Node) { + if r.Flags&CompletePage == 0 { + return + } + io.WriteString(w, "\n\n\n") +} + +func (r *HTMLRenderer) writeDocumentHeader(w io.Writer) { + if r.Flags&CompletePage == 0 { + return + } + ending := "" + if r.Flags&UseXHTML != 0 { + io.WriteString(w, "\n") + io.WriteString(w, "\n") + ending = " /" + } else { + io.WriteString(w, "\n") + io.WriteString(w, "\n") + } + io.WriteString(w, "\n") + io.WriteString(w, " ") + if r.Flags&Smartypants != 0 { + r.sr.Process(w, []byte(r.Title)) + } else { + escapeHTML(w, []byte(r.Title)) + } + io.WriteString(w, "\n") + io.WriteString(w, " \n") + io.WriteString(w, " \n") + if r.CSS != "" { + io.WriteString(w, " \n") + } + if r.Icon != "" { + io.WriteString(w, " \n") + } + io.WriteString(w, "\n") + io.WriteString(w, "\n\n") +} + +func (r *HTMLRenderer) writeTOC(w io.Writer, ast *Node) { + buf := bytes.Buffer{} + + inHeading := false + tocLevel := 0 + headingCount := 0 + + ast.Walk(func(node *Node, entering bool) WalkStatus { + if node.Type == Heading && !node.HeadingData.IsTitleblock { + inHeading = entering + if entering { + node.HeadingID = fmt.Sprintf("toc_%d", headingCount) + if node.Level == tocLevel { + buf.WriteString("\n\n
    4. ") + } else if node.Level < tocLevel { + for node.Level < tocLevel { + tocLevel-- + buf.WriteString("
    5. \n") + } + buf.WriteString("\n\n
    6. ") + } else { + for node.Level > tocLevel { + tocLevel++ + buf.WriteString("\n") + } + + if buf.Len() > 0 { + io.WriteString(w, "\n") + } + r.lastOutputLen = buf.Len() +} diff --git a/vendor/github.com/russross/blackfriday/v2/inline.go b/vendor/github.com/russross/blackfriday/v2/inline.go new file mode 100644 index 0000000000..d45bd94172 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/inline.go @@ -0,0 +1,1228 @@ +// +// Blackfriday Markdown Processor +// Available at http://github.com/russross/blackfriday +// +// Copyright © 2011 Russ Ross . +// Distributed under the Simplified BSD License. +// See README.md for details. +// + +// +// Functions to parse inline elements. +// + +package blackfriday + +import ( + "bytes" + "regexp" + "strconv" +) + +var ( + urlRe = `((https?|ftp):\/\/|\/)[-A-Za-z0-9+&@#\/%?=~_|!:,.;\(\)]+` + anchorRe = regexp.MustCompile(`^(]+")?\s?>` + urlRe + `<\/a>)`) + + // https://www.w3.org/TR/html5/syntax.html#character-references + // highest unicode code point in 17 planes (2^20): 1,114,112d = + // 7 dec digits or 6 hex digits + // named entity references can be 2-31 characters with stuff like < + // at one end and ∳ at the other. There + // are also sometimes numbers at the end, although this isn't inherent + // in the specification; there are never numbers anywhere else in + // current character references, though; see ¾ and ▒, etc. + // https://www.w3.org/TR/html5/syntax.html#named-character-references + // + // entity := "&" (named group | number ref) ";" + // named group := [a-zA-Z]{2,31}[0-9]{0,2} + // number ref := "#" (dec ref | hex ref) + // dec ref := [0-9]{1,7} + // hex ref := ("x" | "X") [0-9a-fA-F]{1,6} + htmlEntityRe = regexp.MustCompile(`&([a-zA-Z]{2,31}[0-9]{0,2}|#([0-9]{1,7}|[xX][0-9a-fA-F]{1,6}));`) +) + +// Functions to parse text within a block +// Each function returns the number of chars taken care of +// data is the complete block being rendered +// offset is the number of valid chars before the current cursor + +func (p *Markdown) inline(currBlock *Node, data []byte) { + // handlers might call us recursively: enforce a maximum depth + if p.nesting >= p.maxNesting || len(data) == 0 { + return + } + p.nesting++ + beg, end := 0, 0 + for end < len(data) { + handler := p.inlineCallback[data[end]] + if handler != nil { + if consumed, node := handler(p, data, end); consumed == 0 { + // No action from the callback. + end++ + } else { + // Copy inactive chars into the output. + currBlock.AppendChild(text(data[beg:end])) + if node != nil { + currBlock.AppendChild(node) + } + // Skip past whatever the callback used. + beg = end + consumed + end = beg + } + } else { + end++ + } + } + if beg < len(data) { + if data[end-1] == '\n' { + end-- + } + currBlock.AppendChild(text(data[beg:end])) + } + p.nesting-- +} + +// single and double emphasis parsing +func emphasis(p *Markdown, data []byte, offset int) (int, *Node) { + data = data[offset:] + c := data[0] + + if len(data) > 2 && data[1] != c { + // whitespace cannot follow an opening emphasis; + // strikethrough only takes two characters '~~' + if c == '~' || isspace(data[1]) { + return 0, nil + } + ret, node := helperEmphasis(p, data[1:], c) + if ret == 0 { + return 0, nil + } + + return ret + 1, node + } + + if len(data) > 3 && data[1] == c && data[2] != c { + if isspace(data[2]) { + return 0, nil + } + ret, node := helperDoubleEmphasis(p, data[2:], c) + if ret == 0 { + return 0, nil + } + + return ret + 2, node + } + + if len(data) > 4 && data[1] == c && data[2] == c && data[3] != c { + if c == '~' || isspace(data[3]) { + return 0, nil + } + ret, node := helperTripleEmphasis(p, data, 3, c) + if ret == 0 { + return 0, nil + } + + return ret + 3, node + } + + return 0, nil +} + +func codeSpan(p *Markdown, data []byte, offset int) (int, *Node) { + data = data[offset:] + + nb := 0 + + // count the number of backticks in the delimiter + for nb < len(data) && data[nb] == '`' { + nb++ + } + + // find the next delimiter + i, end := 0, 0 + for end = nb; end < len(data) && i < nb; end++ { + if data[end] == '`' { + i++ + } else { + i = 0 + } + } + + // no matching delimiter? + if i < nb && end >= len(data) { + return 0, nil + } + + // trim outside whitespace + fBegin := nb + for fBegin < end && data[fBegin] == ' ' { + fBegin++ + } + + fEnd := end - nb + for fEnd > fBegin && data[fEnd-1] == ' ' { + fEnd-- + } + + // render the code span + if fBegin != fEnd { + code := NewNode(Code) + code.Literal = data[fBegin:fEnd] + return end, code + } + + return end, nil +} + +// newline preceded by two spaces becomes
      +func maybeLineBreak(p *Markdown, data []byte, offset int) (int, *Node) { + origOffset := offset + for offset < len(data) && data[offset] == ' ' { + offset++ + } + + if offset < len(data) && data[offset] == '\n' { + if offset-origOffset >= 2 { + return offset - origOffset + 1, NewNode(Hardbreak) + } + return offset - origOffset, nil + } + return 0, nil +} + +// newline without two spaces works when HardLineBreak is enabled +func lineBreak(p *Markdown, data []byte, offset int) (int, *Node) { + if p.extensions&HardLineBreak != 0 { + return 1, NewNode(Hardbreak) + } + return 0, nil +} + +type linkType int + +const ( + linkNormal linkType = iota + linkImg + linkDeferredFootnote + linkInlineFootnote +) + +func isReferenceStyleLink(data []byte, pos int, t linkType) bool { + if t == linkDeferredFootnote { + return false + } + return pos < len(data)-1 && data[pos] == '[' && data[pos+1] != '^' +} + +func maybeImage(p *Markdown, data []byte, offset int) (int, *Node) { + if offset < len(data)-1 && data[offset+1] == '[' { + return link(p, data, offset) + } + return 0, nil +} + +func maybeInlineFootnote(p *Markdown, data []byte, offset int) (int, *Node) { + if offset < len(data)-1 && data[offset+1] == '[' { + return link(p, data, offset) + } + return 0, nil +} + +// '[': parse a link or an image or a footnote +func link(p *Markdown, data []byte, offset int) (int, *Node) { + // no links allowed inside regular links, footnote, and deferred footnotes + if p.insideLink && (offset > 0 && data[offset-1] == '[' || len(data)-1 > offset && data[offset+1] == '^') { + return 0, nil + } + + var t linkType + switch { + // special case: ![^text] == deferred footnote (that follows something with + // an exclamation point) + case p.extensions&Footnotes != 0 && len(data)-1 > offset && data[offset+1] == '^': + t = linkDeferredFootnote + // ![alt] == image + case offset >= 0 && data[offset] == '!': + t = linkImg + offset++ + // ^[text] == inline footnote + // [^refId] == deferred footnote + case p.extensions&Footnotes != 0: + if offset >= 0 && data[offset] == '^' { + t = linkInlineFootnote + offset++ + } else if len(data)-1 > offset && data[offset+1] == '^' { + t = linkDeferredFootnote + } + // [text] == regular link + default: + t = linkNormal + } + + data = data[offset:] + + var ( + i = 1 + noteID int + title, link, altContent []byte + textHasNl = false + ) + + if t == linkDeferredFootnote { + i++ + } + + // look for the matching closing bracket + for level := 1; level > 0 && i < len(data); i++ { + switch { + case data[i] == '\n': + textHasNl = true + + case isBackslashEscaped(data, i): + continue + + case data[i] == '[': + level++ + + case data[i] == ']': + level-- + if level <= 0 { + i-- // compensate for extra i++ in for loop + } + } + } + + if i >= len(data) { + return 0, nil + } + + txtE := i + i++ + var footnoteNode *Node + + // skip any amount of whitespace or newline + // (this is much more lax than original markdown syntax) + for i < len(data) && isspace(data[i]) { + i++ + } + + // inline style link + switch { + case i < len(data) && data[i] == '(': + // skip initial whitespace + i++ + + for i < len(data) && isspace(data[i]) { + i++ + } + + linkB := i + + // look for link end: ' " ) + findlinkend: + for i < len(data) { + switch { + case data[i] == '\\': + i += 2 + + case data[i] == ')' || data[i] == '\'' || data[i] == '"': + break findlinkend + + default: + i++ + } + } + + if i >= len(data) { + return 0, nil + } + linkE := i + + // look for title end if present + titleB, titleE := 0, 0 + if data[i] == '\'' || data[i] == '"' { + i++ + titleB = i + + findtitleend: + for i < len(data) { + switch { + case data[i] == '\\': + i += 2 + + case data[i] == ')': + break findtitleend + + default: + i++ + } + } + + if i >= len(data) { + return 0, nil + } + + // skip whitespace after title + titleE = i - 1 + for titleE > titleB && isspace(data[titleE]) { + titleE-- + } + + // check for closing quote presence + if data[titleE] != '\'' && data[titleE] != '"' { + titleB, titleE = 0, 0 + linkE = i + } + } + + // remove whitespace at the end of the link + for linkE > linkB && isspace(data[linkE-1]) { + linkE-- + } + + // remove optional angle brackets around the link + if data[linkB] == '<' { + linkB++ + } + if data[linkE-1] == '>' { + linkE-- + } + + // build escaped link and title + if linkE > linkB { + link = data[linkB:linkE] + } + + if titleE > titleB { + title = data[titleB:titleE] + } + + i++ + + // reference style link + case isReferenceStyleLink(data, i, t): + var id []byte + altContentConsidered := false + + // look for the id + i++ + linkB := i + for i < len(data) && data[i] != ']' { + i++ + } + if i >= len(data) { + return 0, nil + } + linkE := i + + // find the reference + if linkB == linkE { + if textHasNl { + var b bytes.Buffer + + for j := 1; j < txtE; j++ { + switch { + case data[j] != '\n': + b.WriteByte(data[j]) + case data[j-1] != ' ': + b.WriteByte(' ') + } + } + + id = b.Bytes() + } else { + id = data[1:txtE] + altContentConsidered = true + } + } else { + id = data[linkB:linkE] + } + + // find the reference with matching id + lr, ok := p.getRef(string(id)) + if !ok { + return 0, nil + } + + // keep link and title from reference + link = lr.link + title = lr.title + if altContentConsidered { + altContent = lr.text + } + i++ + + // shortcut reference style link or reference or inline footnote + default: + var id []byte + + // craft the id + if textHasNl { + var b bytes.Buffer + + for j := 1; j < txtE; j++ { + switch { + case data[j] != '\n': + b.WriteByte(data[j]) + case data[j-1] != ' ': + b.WriteByte(' ') + } + } + + id = b.Bytes() + } else { + if t == linkDeferredFootnote { + id = data[2:txtE] // get rid of the ^ + } else { + id = data[1:txtE] + } + } + + footnoteNode = NewNode(Item) + if t == linkInlineFootnote { + // create a new reference + noteID = len(p.notes) + 1 + + var fragment []byte + if len(id) > 0 { + if len(id) < 16 { + fragment = make([]byte, len(id)) + } else { + fragment = make([]byte, 16) + } + copy(fragment, slugify(id)) + } else { + fragment = append([]byte("footnote-"), []byte(strconv.Itoa(noteID))...) + } + + ref := &reference{ + noteID: noteID, + hasBlock: false, + link: fragment, + title: id, + footnote: footnoteNode, + } + + p.notes = append(p.notes, ref) + + link = ref.link + title = ref.title + } else { + // find the reference with matching id + lr, ok := p.getRef(string(id)) + if !ok { + return 0, nil + } + + if t == linkDeferredFootnote { + lr.noteID = len(p.notes) + 1 + lr.footnote = footnoteNode + p.notes = append(p.notes, lr) + } + + // keep link and title from reference + link = lr.link + // if inline footnote, title == footnote contents + title = lr.title + noteID = lr.noteID + } + + // rewind the whitespace + i = txtE + 1 + } + + var uLink []byte + if t == linkNormal || t == linkImg { + if len(link) > 0 { + var uLinkBuf bytes.Buffer + unescapeText(&uLinkBuf, link) + uLink = uLinkBuf.Bytes() + } + + // links need something to click on and somewhere to go + if len(uLink) == 0 || (t == linkNormal && txtE <= 1) { + return 0, nil + } + } + + // call the relevant rendering function + var linkNode *Node + switch t { + case linkNormal: + linkNode = NewNode(Link) + linkNode.Destination = normalizeURI(uLink) + linkNode.Title = title + if len(altContent) > 0 { + linkNode.AppendChild(text(altContent)) + } else { + // links cannot contain other links, so turn off link parsing + // temporarily and recurse + insideLink := p.insideLink + p.insideLink = true + p.inline(linkNode, data[1:txtE]) + p.insideLink = insideLink + } + + case linkImg: + linkNode = NewNode(Image) + linkNode.Destination = uLink + linkNode.Title = title + linkNode.AppendChild(text(data[1:txtE])) + i++ + + case linkInlineFootnote, linkDeferredFootnote: + linkNode = NewNode(Link) + linkNode.Destination = link + linkNode.Title = title + linkNode.NoteID = noteID + linkNode.Footnote = footnoteNode + if t == linkInlineFootnote { + i++ + } + + default: + return 0, nil + } + + return i, linkNode +} + +func (p *Markdown) inlineHTMLComment(data []byte) int { + if len(data) < 5 { + return 0 + } + if data[0] != '<' || data[1] != '!' || data[2] != '-' || data[3] != '-' { + return 0 + } + i := 5 + // scan for an end-of-comment marker, across lines if necessary + for i < len(data) && !(data[i-2] == '-' && data[i-1] == '-' && data[i] == '>') { + i++ + } + // no end-of-comment marker + if i >= len(data) { + return 0 + } + return i + 1 +} + +func stripMailto(link []byte) []byte { + if bytes.HasPrefix(link, []byte("mailto://")) { + return link[9:] + } else if bytes.HasPrefix(link, []byte("mailto:")) { + return link[7:] + } else { + return link + } +} + +// autolinkType specifies a kind of autolink that gets detected. +type autolinkType int + +// These are the possible flag values for the autolink renderer. +const ( + notAutolink autolinkType = iota + normalAutolink + emailAutolink +) + +// '<' when tags or autolinks are allowed +func leftAngle(p *Markdown, data []byte, offset int) (int, *Node) { + data = data[offset:] + altype, end := tagLength(data) + if size := p.inlineHTMLComment(data); size > 0 { + end = size + } + if end > 2 { + if altype != notAutolink { + var uLink bytes.Buffer + unescapeText(&uLink, data[1:end+1-2]) + if uLink.Len() > 0 { + link := uLink.Bytes() + node := NewNode(Link) + node.Destination = link + if altype == emailAutolink { + node.Destination = append([]byte("mailto:"), link...) + } + node.AppendChild(text(stripMailto(link))) + return end, node + } + } else { + htmlTag := NewNode(HTMLSpan) + htmlTag.Literal = data[:end] + return end, htmlTag + } + } + + return end, nil +} + +// '\\' backslash escape +var escapeChars = []byte("\\`*_{}[]()#+-.!:|&<>~") + +func escape(p *Markdown, data []byte, offset int) (int, *Node) { + data = data[offset:] + + if len(data) > 1 { + if p.extensions&BackslashLineBreak != 0 && data[1] == '\n' { + return 2, NewNode(Hardbreak) + } + if bytes.IndexByte(escapeChars, data[1]) < 0 { + return 0, nil + } + + return 2, text(data[1:2]) + } + + return 2, nil +} + +func unescapeText(ob *bytes.Buffer, src []byte) { + i := 0 + for i < len(src) { + org := i + for i < len(src) && src[i] != '\\' { + i++ + } + + if i > org { + ob.Write(src[org:i]) + } + + if i+1 >= len(src) { + break + } + + ob.WriteByte(src[i+1]) + i += 2 + } +} + +// '&' escaped when it doesn't belong to an entity +// valid entities are assumed to be anything matching &#?[A-Za-z0-9]+; +func entity(p *Markdown, data []byte, offset int) (int, *Node) { + data = data[offset:] + + end := 1 + + if end < len(data) && data[end] == '#' { + end++ + } + + for end < len(data) && isalnum(data[end]) { + end++ + } + + if end < len(data) && data[end] == ';' { + end++ // real entity + } else { + return 0, nil // lone '&' + } + + ent := data[:end] + // undo & escaping or it will be converted to &amp; by another + // escaper in the renderer + if bytes.Equal(ent, []byte("&")) { + ent = []byte{'&'} + } + + return end, text(ent) +} + +func linkEndsWithEntity(data []byte, linkEnd int) bool { + entityRanges := htmlEntityRe.FindAllIndex(data[:linkEnd], -1) + return entityRanges != nil && entityRanges[len(entityRanges)-1][1] == linkEnd +} + +// hasPrefixCaseInsensitive is a custom implementation of +// strings.HasPrefix(strings.ToLower(s), prefix) +// we rolled our own because ToLower pulls in a huge machinery of lowercasing +// anything from Unicode and that's very slow. Since this func will only be +// used on ASCII protocol prefixes, we can take shortcuts. +func hasPrefixCaseInsensitive(s, prefix []byte) bool { + if len(s) < len(prefix) { + return false + } + delta := byte('a' - 'A') + for i, b := range prefix { + if b != s[i] && b != s[i]+delta { + return false + } + } + return true +} + +var protocolPrefixes = [][]byte{ + []byte("http://"), + []byte("https://"), + []byte("ftp://"), + []byte("file://"), + []byte("mailto:"), +} + +const shortestPrefix = 6 // len("ftp://"), the shortest of the above + +func maybeAutoLink(p *Markdown, data []byte, offset int) (int, *Node) { + // quick check to rule out most false hits + if p.insideLink || len(data) < offset+shortestPrefix { + return 0, nil + } + for _, prefix := range protocolPrefixes { + endOfHead := offset + 8 // 8 is the len() of the longest prefix + if endOfHead > len(data) { + endOfHead = len(data) + } + if hasPrefixCaseInsensitive(data[offset:endOfHead], prefix) { + return autoLink(p, data, offset) + } + } + return 0, nil +} + +func autoLink(p *Markdown, data []byte, offset int) (int, *Node) { + // Now a more expensive check to see if we're not inside an anchor element + anchorStart := offset + offsetFromAnchor := 0 + for anchorStart > 0 && data[anchorStart] != '<' { + anchorStart-- + offsetFromAnchor++ + } + + anchorStr := anchorRe.Find(data[anchorStart:]) + if anchorStr != nil { + anchorClose := NewNode(HTMLSpan) + anchorClose.Literal = anchorStr[offsetFromAnchor:] + return len(anchorStr) - offsetFromAnchor, anchorClose + } + + // scan backward for a word boundary + rewind := 0 + for offset-rewind > 0 && rewind <= 7 && isletter(data[offset-rewind-1]) { + rewind++ + } + if rewind > 6 { // longest supported protocol is "mailto" which has 6 letters + return 0, nil + } + + origData := data + data = data[offset-rewind:] + + if !isSafeLink(data) { + return 0, nil + } + + linkEnd := 0 + for linkEnd < len(data) && !isEndOfLink(data[linkEnd]) { + linkEnd++ + } + + // Skip punctuation at the end of the link + if (data[linkEnd-1] == '.' || data[linkEnd-1] == ',') && data[linkEnd-2] != '\\' { + linkEnd-- + } + + // But don't skip semicolon if it's a part of escaped entity: + if data[linkEnd-1] == ';' && data[linkEnd-2] != '\\' && !linkEndsWithEntity(data, linkEnd) { + linkEnd-- + } + + // See if the link finishes with a punctuation sign that can be closed. + var copen byte + switch data[linkEnd-1] { + case '"': + copen = '"' + case '\'': + copen = '\'' + case ')': + copen = '(' + case ']': + copen = '[' + case '}': + copen = '{' + default: + copen = 0 + } + + if copen != 0 { + bufEnd := offset - rewind + linkEnd - 2 + + openDelim := 1 + + /* Try to close the final punctuation sign in this same line; + * if we managed to close it outside of the URL, that means that it's + * not part of the URL. If it closes inside the URL, that means it + * is part of the URL. + * + * Examples: + * + * foo http://www.pokemon.com/Pikachu_(Electric) bar + * => http://www.pokemon.com/Pikachu_(Electric) + * + * foo (http://www.pokemon.com/Pikachu_(Electric)) bar + * => http://www.pokemon.com/Pikachu_(Electric) + * + * foo http://www.pokemon.com/Pikachu_(Electric)) bar + * => http://www.pokemon.com/Pikachu_(Electric)) + * + * (foo http://www.pokemon.com/Pikachu_(Electric)) bar + * => foo http://www.pokemon.com/Pikachu_(Electric) + */ + + for bufEnd >= 0 && origData[bufEnd] != '\n' && openDelim != 0 { + if origData[bufEnd] == data[linkEnd-1] { + openDelim++ + } + + if origData[bufEnd] == copen { + openDelim-- + } + + bufEnd-- + } + + if openDelim == 0 { + linkEnd-- + } + } + + var uLink bytes.Buffer + unescapeText(&uLink, data[:linkEnd]) + + if uLink.Len() > 0 { + node := NewNode(Link) + node.Destination = uLink.Bytes() + node.AppendChild(text(uLink.Bytes())) + return linkEnd, node + } + + return linkEnd, nil +} + +func isEndOfLink(char byte) bool { + return isspace(char) || char == '<' +} + +var validUris = [][]byte{[]byte("http://"), []byte("https://"), []byte("ftp://"), []byte("mailto://")} +var validPaths = [][]byte{[]byte("/"), []byte("./"), []byte("../")} + +func isSafeLink(link []byte) bool { + for _, path := range validPaths { + if len(link) >= len(path) && bytes.Equal(link[:len(path)], path) { + if len(link) == len(path) { + return true + } else if isalnum(link[len(path)]) { + return true + } + } + } + + for _, prefix := range validUris { + // TODO: handle unicode here + // case-insensitive prefix test + if len(link) > len(prefix) && bytes.Equal(bytes.ToLower(link[:len(prefix)]), prefix) && isalnum(link[len(prefix)]) { + return true + } + } + + return false +} + +// return the length of the given tag, or 0 is it's not valid +func tagLength(data []byte) (autolink autolinkType, end int) { + var i, j int + + // a valid tag can't be shorter than 3 chars + if len(data) < 3 { + return notAutolink, 0 + } + + // begins with a '<' optionally followed by '/', followed by letter or number + if data[0] != '<' { + return notAutolink, 0 + } + if data[1] == '/' { + i = 2 + } else { + i = 1 + } + + if !isalnum(data[i]) { + return notAutolink, 0 + } + + // scheme test + autolink = notAutolink + + // try to find the beginning of an URI + for i < len(data) && (isalnum(data[i]) || data[i] == '.' || data[i] == '+' || data[i] == '-') { + i++ + } + + if i > 1 && i < len(data) && data[i] == '@' { + if j = isMailtoAutoLink(data[i:]); j != 0 { + return emailAutolink, i + j + } + } + + if i > 2 && i < len(data) && data[i] == ':' { + autolink = normalAutolink + i++ + } + + // complete autolink test: no whitespace or ' or " + switch { + case i >= len(data): + autolink = notAutolink + case autolink != notAutolink: + j = i + + for i < len(data) { + if data[i] == '\\' { + i += 2 + } else if data[i] == '>' || data[i] == '\'' || data[i] == '"' || isspace(data[i]) { + break + } else { + i++ + } + + } + + if i >= len(data) { + return autolink, 0 + } + if i > j && data[i] == '>' { + return autolink, i + 1 + } + + // one of the forbidden chars has been found + autolink = notAutolink + } + i += bytes.IndexByte(data[i:], '>') + if i < 0 { + return autolink, 0 + } + return autolink, i + 1 +} + +// look for the address part of a mail autolink and '>' +// this is less strict than the original markdown e-mail address matching +func isMailtoAutoLink(data []byte) int { + nb := 0 + + // address is assumed to be: [-@._a-zA-Z0-9]+ with exactly one '@' + for i := 0; i < len(data); i++ { + if isalnum(data[i]) { + continue + } + + switch data[i] { + case '@': + nb++ + + case '-', '.', '_': + break + + case '>': + if nb == 1 { + return i + 1 + } + return 0 + default: + return 0 + } + } + + return 0 +} + +// look for the next emph char, skipping other constructs +func helperFindEmphChar(data []byte, c byte) int { + i := 0 + + for i < len(data) { + for i < len(data) && data[i] != c && data[i] != '`' && data[i] != '[' { + i++ + } + if i >= len(data) { + return 0 + } + // do not count escaped chars + if i != 0 && data[i-1] == '\\' { + i++ + continue + } + if data[i] == c { + return i + } + + if data[i] == '`' { + // skip a code span + tmpI := 0 + i++ + for i < len(data) && data[i] != '`' { + if tmpI == 0 && data[i] == c { + tmpI = i + } + i++ + } + if i >= len(data) { + return tmpI + } + i++ + } else if data[i] == '[' { + // skip a link + tmpI := 0 + i++ + for i < len(data) && data[i] != ']' { + if tmpI == 0 && data[i] == c { + tmpI = i + } + i++ + } + i++ + for i < len(data) && (data[i] == ' ' || data[i] == '\n') { + i++ + } + if i >= len(data) { + return tmpI + } + if data[i] != '[' && data[i] != '(' { // not a link + if tmpI > 0 { + return tmpI + } + continue + } + cc := data[i] + i++ + for i < len(data) && data[i] != cc { + if tmpI == 0 && data[i] == c { + return i + } + i++ + } + if i >= len(data) { + return tmpI + } + i++ + } + } + return 0 +} + +func helperEmphasis(p *Markdown, data []byte, c byte) (int, *Node) { + i := 0 + + // skip one symbol if coming from emph3 + if len(data) > 1 && data[0] == c && data[1] == c { + i = 1 + } + + for i < len(data) { + length := helperFindEmphChar(data[i:], c) + if length == 0 { + return 0, nil + } + i += length + if i >= len(data) { + return 0, nil + } + + if i+1 < len(data) && data[i+1] == c { + i++ + continue + } + + if data[i] == c && !isspace(data[i-1]) { + + if p.extensions&NoIntraEmphasis != 0 { + if !(i+1 == len(data) || isspace(data[i+1]) || ispunct(data[i+1])) { + continue + } + } + + emph := NewNode(Emph) + p.inline(emph, data[:i]) + return i + 1, emph + } + } + + return 0, nil +} + +func helperDoubleEmphasis(p *Markdown, data []byte, c byte) (int, *Node) { + i := 0 + + for i < len(data) { + length := helperFindEmphChar(data[i:], c) + if length == 0 { + return 0, nil + } + i += length + + if i+1 < len(data) && data[i] == c && data[i+1] == c && i > 0 && !isspace(data[i-1]) { + nodeType := Strong + if c == '~' { + nodeType = Del + } + node := NewNode(nodeType) + p.inline(node, data[:i]) + return i + 2, node + } + i++ + } + return 0, nil +} + +func helperTripleEmphasis(p *Markdown, data []byte, offset int, c byte) (int, *Node) { + i := 0 + origData := data + data = data[offset:] + + for i < len(data) { + length := helperFindEmphChar(data[i:], c) + if length == 0 { + return 0, nil + } + i += length + + // skip whitespace preceded symbols + if data[i] != c || isspace(data[i-1]) { + continue + } + + switch { + case i+2 < len(data) && data[i+1] == c && data[i+2] == c: + // triple symbol found + strong := NewNode(Strong) + em := NewNode(Emph) + strong.AppendChild(em) + p.inline(em, data[:i]) + return i + 3, strong + case (i+1 < len(data) && data[i+1] == c): + // double symbol found, hand over to emph1 + length, node := helperEmphasis(p, origData[offset-2:], c) + if length == 0 { + return 0, nil + } + return length - 2, node + default: + // single symbol found, hand over to emph2 + length, node := helperDoubleEmphasis(p, origData[offset-1:], c) + if length == 0 { + return 0, nil + } + return length - 1, node + } + } + return 0, nil +} + +func text(s []byte) *Node { + node := NewNode(Text) + node.Literal = s + return node +} + +func normalizeURI(s []byte) []byte { + return s // TODO: implement +} diff --git a/vendor/github.com/russross/blackfriday/v2/markdown.go b/vendor/github.com/russross/blackfriday/v2/markdown.go new file mode 100644 index 0000000000..58d2e4538c --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/markdown.go @@ -0,0 +1,950 @@ +// Blackfriday Markdown Processor +// Available at http://github.com/russross/blackfriday +// +// Copyright © 2011 Russ Ross . +// Distributed under the Simplified BSD License. +// See README.md for details. + +package blackfriday + +import ( + "bytes" + "fmt" + "io" + "strings" + "unicode/utf8" +) + +// +// Markdown parsing and processing +// + +// Version string of the package. Appears in the rendered document when +// CompletePage flag is on. +const Version = "2.0" + +// Extensions is a bitwise or'ed collection of enabled Blackfriday's +// extensions. +type Extensions int + +// These are the supported markdown parsing extensions. +// OR these values together to select multiple extensions. +const ( + NoExtensions Extensions = 0 + NoIntraEmphasis Extensions = 1 << iota // Ignore emphasis markers inside words + Tables // Render tables + FencedCode // Render fenced code blocks + Autolink // Detect embedded URLs that are not explicitly marked + Strikethrough // Strikethrough text using ~~test~~ + LaxHTMLBlocks // Loosen up HTML block parsing rules + SpaceHeadings // Be strict about prefix heading rules + HardLineBreak // Translate newlines into line breaks + TabSizeEight // Expand tabs to eight spaces instead of four + Footnotes // Pandoc-style footnotes + NoEmptyLineBeforeBlock // No need to insert an empty line to start a (code, quote, ordered list, unordered list) block + HeadingIDs // specify heading IDs with {#id} + Titleblock // Titleblock ala pandoc + AutoHeadingIDs // Create the heading ID from the text + BackslashLineBreak // Translate trailing backslashes into line breaks + DefinitionLists // Render definition lists + + CommonHTMLFlags HTMLFlags = UseXHTML | Smartypants | + SmartypantsFractions | SmartypantsDashes | SmartypantsLatexDashes + + CommonExtensions Extensions = NoIntraEmphasis | Tables | FencedCode | + Autolink | Strikethrough | SpaceHeadings | HeadingIDs | + BackslashLineBreak | DefinitionLists +) + +// ListType contains bitwise or'ed flags for list and list item objects. +type ListType int + +// These are the possible flag values for the ListItem renderer. +// Multiple flag values may be ORed together. +// These are mostly of interest if you are writing a new output format. +const ( + ListTypeOrdered ListType = 1 << iota + ListTypeDefinition + ListTypeTerm + + ListItemContainsBlock + ListItemBeginningOfList // TODO: figure out if this is of any use now + ListItemEndOfList +) + +// CellAlignFlags holds a type of alignment in a table cell. +type CellAlignFlags int + +// These are the possible flag values for the table cell renderer. +// Only a single one of these values will be used; they are not ORed together. +// These are mostly of interest if you are writing a new output format. +const ( + TableAlignmentLeft CellAlignFlags = 1 << iota + TableAlignmentRight + TableAlignmentCenter = (TableAlignmentLeft | TableAlignmentRight) +) + +// The size of a tab stop. +const ( + TabSizeDefault = 4 + TabSizeDouble = 8 +) + +// blockTags is a set of tags that are recognized as HTML block tags. +// Any of these can be included in markdown text without special escaping. +var blockTags = map[string]struct{}{ + "blockquote": {}, + "del": {}, + "div": {}, + "dl": {}, + "fieldset": {}, + "form": {}, + "h1": {}, + "h2": {}, + "h3": {}, + "h4": {}, + "h5": {}, + "h6": {}, + "iframe": {}, + "ins": {}, + "math": {}, + "noscript": {}, + "ol": {}, + "pre": {}, + "p": {}, + "script": {}, + "style": {}, + "table": {}, + "ul": {}, + + // HTML5 + "address": {}, + "article": {}, + "aside": {}, + "canvas": {}, + "figcaption": {}, + "figure": {}, + "footer": {}, + "header": {}, + "hgroup": {}, + "main": {}, + "nav": {}, + "output": {}, + "progress": {}, + "section": {}, + "video": {}, +} + +// Renderer is the rendering interface. This is mostly of interest if you are +// implementing a new rendering format. +// +// Only an HTML implementation is provided in this repository, see the README +// for external implementations. +type Renderer interface { + // RenderNode is the main rendering method. It will be called once for + // every leaf node and twice for every non-leaf node (first with + // entering=true, then with entering=false). The method should write its + // rendition of the node to the supplied writer w. + RenderNode(w io.Writer, node *Node, entering bool) WalkStatus + + // RenderHeader is a method that allows the renderer to produce some + // content preceding the main body of the output document. The header is + // understood in the broad sense here. For example, the default HTML + // renderer will write not only the HTML document preamble, but also the + // table of contents if it was requested. + // + // The method will be passed an entire document tree, in case a particular + // implementation needs to inspect it to produce output. + // + // The output should be written to the supplied writer w. If your + // implementation has no header to write, supply an empty implementation. + RenderHeader(w io.Writer, ast *Node) + + // RenderFooter is a symmetric counterpart of RenderHeader. + RenderFooter(w io.Writer, ast *Node) +} + +// Callback functions for inline parsing. One such function is defined +// for each character that triggers a response when parsing inline data. +type inlineParser func(p *Markdown, data []byte, offset int) (int, *Node) + +// Markdown is a type that holds extensions and the runtime state used by +// Parse, and the renderer. You can not use it directly, construct it with New. +type Markdown struct { + renderer Renderer + referenceOverride ReferenceOverrideFunc + refs map[string]*reference + inlineCallback [256]inlineParser + extensions Extensions + nesting int + maxNesting int + insideLink bool + + // Footnotes need to be ordered as well as available to quickly check for + // presence. If a ref is also a footnote, it's stored both in refs and here + // in notes. Slice is nil if footnotes not enabled. + notes []*reference + + doc *Node + tip *Node // = doc + oldTip *Node + lastMatchedContainer *Node // = doc + allClosed bool +} + +func (p *Markdown) getRef(refid string) (ref *reference, found bool) { + if p.referenceOverride != nil { + r, overridden := p.referenceOverride(refid) + if overridden { + if r == nil { + return nil, false + } + return &reference{ + link: []byte(r.Link), + title: []byte(r.Title), + noteID: 0, + hasBlock: false, + text: []byte(r.Text)}, true + } + } + // refs are case insensitive + ref, found = p.refs[strings.ToLower(refid)] + return ref, found +} + +func (p *Markdown) finalize(block *Node) { + above := block.Parent + block.open = false + p.tip = above +} + +func (p *Markdown) addChild(node NodeType, offset uint32) *Node { + return p.addExistingChild(NewNode(node), offset) +} + +func (p *Markdown) addExistingChild(node *Node, offset uint32) *Node { + for !p.tip.canContain(node.Type) { + p.finalize(p.tip) + } + p.tip.AppendChild(node) + p.tip = node + return node +} + +func (p *Markdown) closeUnmatchedBlocks() { + if !p.allClosed { + for p.oldTip != p.lastMatchedContainer { + parent := p.oldTip.Parent + p.finalize(p.oldTip) + p.oldTip = parent + } + p.allClosed = true + } +} + +// +// +// Public interface +// +// + +// Reference represents the details of a link. +// See the documentation in Options for more details on use-case. +type Reference struct { + // Link is usually the URL the reference points to. + Link string + // Title is the alternate text describing the link in more detail. + Title string + // Text is the optional text to override the ref with if the syntax used was + // [refid][] + Text string +} + +// ReferenceOverrideFunc is expected to be called with a reference string and +// return either a valid Reference type that the reference string maps to or +// nil. If overridden is false, the default reference logic will be executed. +// See the documentation in Options for more details on use-case. +type ReferenceOverrideFunc func(reference string) (ref *Reference, overridden bool) + +// New constructs a Markdown processor. You can use the same With* functions as +// for Run() to customize parser's behavior and the renderer. +func New(opts ...Option) *Markdown { + var p Markdown + for _, opt := range opts { + opt(&p) + } + p.refs = make(map[string]*reference) + p.maxNesting = 16 + p.insideLink = false + docNode := NewNode(Document) + p.doc = docNode + p.tip = docNode + p.oldTip = docNode + p.lastMatchedContainer = docNode + p.allClosed = true + // register inline parsers + p.inlineCallback[' '] = maybeLineBreak + p.inlineCallback['*'] = emphasis + p.inlineCallback['_'] = emphasis + if p.extensions&Strikethrough != 0 { + p.inlineCallback['~'] = emphasis + } + p.inlineCallback['`'] = codeSpan + p.inlineCallback['\n'] = lineBreak + p.inlineCallback['['] = link + p.inlineCallback['<'] = leftAngle + p.inlineCallback['\\'] = escape + p.inlineCallback['&'] = entity + p.inlineCallback['!'] = maybeImage + p.inlineCallback['^'] = maybeInlineFootnote + if p.extensions&Autolink != 0 { + p.inlineCallback['h'] = maybeAutoLink + p.inlineCallback['m'] = maybeAutoLink + p.inlineCallback['f'] = maybeAutoLink + p.inlineCallback['H'] = maybeAutoLink + p.inlineCallback['M'] = maybeAutoLink + p.inlineCallback['F'] = maybeAutoLink + } + if p.extensions&Footnotes != 0 { + p.notes = make([]*reference, 0) + } + return &p +} + +// Option customizes the Markdown processor's default behavior. +type Option func(*Markdown) + +// WithRenderer allows you to override the default renderer. +func WithRenderer(r Renderer) Option { + return func(p *Markdown) { + p.renderer = r + } +} + +// WithExtensions allows you to pick some of the many extensions provided by +// Blackfriday. You can bitwise OR them. +func WithExtensions(e Extensions) Option { + return func(p *Markdown) { + p.extensions = e + } +} + +// WithNoExtensions turns off all extensions and custom behavior. +func WithNoExtensions() Option { + return func(p *Markdown) { + p.extensions = NoExtensions + p.renderer = NewHTMLRenderer(HTMLRendererParameters{ + Flags: HTMLFlagsNone, + }) + } +} + +// WithRefOverride sets an optional function callback that is called every +// time a reference is resolved. +// +// In Markdown, the link reference syntax can be made to resolve a link to +// a reference instead of an inline URL, in one of the following ways: +// +// * [link text][refid] +// * [refid][] +// +// Usually, the refid is defined at the bottom of the Markdown document. If +// this override function is provided, the refid is passed to the override +// function first, before consulting the defined refids at the bottom. If +// the override function indicates an override did not occur, the refids at +// the bottom will be used to fill in the link details. +func WithRefOverride(o ReferenceOverrideFunc) Option { + return func(p *Markdown) { + p.referenceOverride = o + } +} + +// Run is the main entry point to Blackfriday. It parses and renders a +// block of markdown-encoded text. +// +// The simplest invocation of Run takes one argument, input: +// output := Run(input) +// This will parse the input with CommonExtensions enabled and render it with +// the default HTMLRenderer (with CommonHTMLFlags). +// +// Variadic arguments opts can customize the default behavior. Since Markdown +// type does not contain exported fields, you can not use it directly. Instead, +// use the With* functions. For example, this will call the most basic +// functionality, with no extensions: +// output := Run(input, WithNoExtensions()) +// +// You can use any number of With* arguments, even contradicting ones. They +// will be applied in order of appearance and the latter will override the +// former: +// output := Run(input, WithNoExtensions(), WithExtensions(exts), +// WithRenderer(yourRenderer)) +func Run(input []byte, opts ...Option) []byte { + r := NewHTMLRenderer(HTMLRendererParameters{ + Flags: CommonHTMLFlags, + }) + optList := []Option{WithRenderer(r), WithExtensions(CommonExtensions)} + optList = append(optList, opts...) + parser := New(optList...) + ast := parser.Parse(input) + var buf bytes.Buffer + parser.renderer.RenderHeader(&buf, ast) + ast.Walk(func(node *Node, entering bool) WalkStatus { + return parser.renderer.RenderNode(&buf, node, entering) + }) + parser.renderer.RenderFooter(&buf, ast) + return buf.Bytes() +} + +// Parse is an entry point to the parsing part of Blackfriday. It takes an +// input markdown document and produces a syntax tree for its contents. This +// tree can then be rendered with a default or custom renderer, or +// analyzed/transformed by the caller to whatever non-standard needs they have. +// The return value is the root node of the syntax tree. +func (p *Markdown) Parse(input []byte) *Node { + p.block(input) + // Walk the tree and finish up some of unfinished blocks + for p.tip != nil { + p.finalize(p.tip) + } + // Walk the tree again and process inline markdown in each block + p.doc.Walk(func(node *Node, entering bool) WalkStatus { + if node.Type == Paragraph || node.Type == Heading || node.Type == TableCell { + p.inline(node, node.content) + node.content = nil + } + return GoToNext + }) + p.parseRefsToAST() + return p.doc +} + +func (p *Markdown) parseRefsToAST() { + if p.extensions&Footnotes == 0 || len(p.notes) == 0 { + return + } + p.tip = p.doc + block := p.addBlock(List, nil) + block.IsFootnotesList = true + block.ListFlags = ListTypeOrdered + flags := ListItemBeginningOfList + // Note: this loop is intentionally explicit, not range-form. This is + // because the body of the loop will append nested footnotes to p.notes and + // we need to process those late additions. Range form would only walk over + // the fixed initial set. + for i := 0; i < len(p.notes); i++ { + ref := p.notes[i] + p.addExistingChild(ref.footnote, 0) + block := ref.footnote + block.ListFlags = flags | ListTypeOrdered + block.RefLink = ref.link + if ref.hasBlock { + flags |= ListItemContainsBlock + p.block(ref.title) + } else { + p.inline(block, ref.title) + } + flags &^= ListItemBeginningOfList | ListItemContainsBlock + } + above := block.Parent + finalizeList(block) + p.tip = above + block.Walk(func(node *Node, entering bool) WalkStatus { + if node.Type == Paragraph || node.Type == Heading { + p.inline(node, node.content) + node.content = nil + } + return GoToNext + }) +} + +// +// Link references +// +// This section implements support for references that (usually) appear +// as footnotes in a document, and can be referenced anywhere in the document. +// The basic format is: +// +// [1]: http://www.google.com/ "Google" +// [2]: http://www.github.com/ "Github" +// +// Anywhere in the document, the reference can be linked by referring to its +// label, i.e., 1 and 2 in this example, as in: +// +// This library is hosted on [Github][2], a git hosting site. +// +// Actual footnotes as specified in Pandoc and supported by some other Markdown +// libraries such as php-markdown are also taken care of. They look like this: +// +// This sentence needs a bit of further explanation.[^note] +// +// [^note]: This is the explanation. +// +// Footnotes should be placed at the end of the document in an ordered list. +// Finally, there are inline footnotes such as: +// +// Inline footnotes^[Also supported.] provide a quick inline explanation, +// but are rendered at the bottom of the document. +// + +// reference holds all information necessary for a reference-style links or +// footnotes. +// +// Consider this markdown with reference-style links: +// +// [link][ref] +// +// [ref]: /url/ "tooltip title" +// +// It will be ultimately converted to this HTML: +// +//

      link

      +// +// And a reference structure will be populated as follows: +// +// p.refs["ref"] = &reference{ +// link: "/url/", +// title: "tooltip title", +// } +// +// Alternatively, reference can contain information about a footnote. Consider +// this markdown: +// +// Text needing a footnote.[^a] +// +// [^a]: This is the note +// +// A reference structure will be populated as follows: +// +// p.refs["a"] = &reference{ +// link: "a", +// title: "This is the note", +// noteID: , +// } +// +// TODO: As you can see, it begs for splitting into two dedicated structures +// for refs and for footnotes. +type reference struct { + link []byte + title []byte + noteID int // 0 if not a footnote ref + hasBlock bool + footnote *Node // a link to the Item node within a list of footnotes + + text []byte // only gets populated by refOverride feature with Reference.Text +} + +func (r *reference) String() string { + return fmt.Sprintf("{link: %q, title: %q, text: %q, noteID: %d, hasBlock: %v}", + r.link, r.title, r.text, r.noteID, r.hasBlock) +} + +// Check whether or not data starts with a reference link. +// If so, it is parsed and stored in the list of references +// (in the render struct). +// Returns the number of bytes to skip to move past it, +// or zero if the first line is not a reference. +func isReference(p *Markdown, data []byte, tabSize int) int { + // up to 3 optional leading spaces + if len(data) < 4 { + return 0 + } + i := 0 + for i < 3 && data[i] == ' ' { + i++ + } + + noteID := 0 + + // id part: anything but a newline between brackets + if data[i] != '[' { + return 0 + } + i++ + if p.extensions&Footnotes != 0 { + if i < len(data) && data[i] == '^' { + // we can set it to anything here because the proper noteIds will + // be assigned later during the second pass. It just has to be != 0 + noteID = 1 + i++ + } + } + idOffset := i + for i < len(data) && data[i] != '\n' && data[i] != '\r' && data[i] != ']' { + i++ + } + if i >= len(data) || data[i] != ']' { + return 0 + } + idEnd := i + // footnotes can have empty ID, like this: [^], but a reference can not be + // empty like this: []. Break early if it's not a footnote and there's no ID + if noteID == 0 && idOffset == idEnd { + return 0 + } + // spacer: colon (space | tab)* newline? (space | tab)* + i++ + if i >= len(data) || data[i] != ':' { + return 0 + } + i++ + for i < len(data) && (data[i] == ' ' || data[i] == '\t') { + i++ + } + if i < len(data) && (data[i] == '\n' || data[i] == '\r') { + i++ + if i < len(data) && data[i] == '\n' && data[i-1] == '\r' { + i++ + } + } + for i < len(data) && (data[i] == ' ' || data[i] == '\t') { + i++ + } + if i >= len(data) { + return 0 + } + + var ( + linkOffset, linkEnd int + titleOffset, titleEnd int + lineEnd int + raw []byte + hasBlock bool + ) + + if p.extensions&Footnotes != 0 && noteID != 0 { + linkOffset, linkEnd, raw, hasBlock = scanFootnote(p, data, i, tabSize) + lineEnd = linkEnd + } else { + linkOffset, linkEnd, titleOffset, titleEnd, lineEnd = scanLinkRef(p, data, i) + } + if lineEnd == 0 { + return 0 + } + + // a valid ref has been found + + ref := &reference{ + noteID: noteID, + hasBlock: hasBlock, + } + + if noteID > 0 { + // reusing the link field for the id since footnotes don't have links + ref.link = data[idOffset:idEnd] + // if footnote, it's not really a title, it's the contained text + ref.title = raw + } else { + ref.link = data[linkOffset:linkEnd] + ref.title = data[titleOffset:titleEnd] + } + + // id matches are case-insensitive + id := string(bytes.ToLower(data[idOffset:idEnd])) + + p.refs[id] = ref + + return lineEnd +} + +func scanLinkRef(p *Markdown, data []byte, i int) (linkOffset, linkEnd, titleOffset, titleEnd, lineEnd int) { + // link: whitespace-free sequence, optionally between angle brackets + if data[i] == '<' { + i++ + } + linkOffset = i + for i < len(data) && data[i] != ' ' && data[i] != '\t' && data[i] != '\n' && data[i] != '\r' { + i++ + } + linkEnd = i + if data[linkOffset] == '<' && data[linkEnd-1] == '>' { + linkOffset++ + linkEnd-- + } + + // optional spacer: (space | tab)* (newline | '\'' | '"' | '(' ) + for i < len(data) && (data[i] == ' ' || data[i] == '\t') { + i++ + } + if i < len(data) && data[i] != '\n' && data[i] != '\r' && data[i] != '\'' && data[i] != '"' && data[i] != '(' { + return + } + + // compute end-of-line + if i >= len(data) || data[i] == '\r' || data[i] == '\n' { + lineEnd = i + } + if i+1 < len(data) && data[i] == '\r' && data[i+1] == '\n' { + lineEnd++ + } + + // optional (space|tab)* spacer after a newline + if lineEnd > 0 { + i = lineEnd + 1 + for i < len(data) && (data[i] == ' ' || data[i] == '\t') { + i++ + } + } + + // optional title: any non-newline sequence enclosed in '"() alone on its line + if i+1 < len(data) && (data[i] == '\'' || data[i] == '"' || data[i] == '(') { + i++ + titleOffset = i + + // look for EOL + for i < len(data) && data[i] != '\n' && data[i] != '\r' { + i++ + } + if i+1 < len(data) && data[i] == '\n' && data[i+1] == '\r' { + titleEnd = i + 1 + } else { + titleEnd = i + } + + // step back + i-- + for i > titleOffset && (data[i] == ' ' || data[i] == '\t') { + i-- + } + if i > titleOffset && (data[i] == '\'' || data[i] == '"' || data[i] == ')') { + lineEnd = titleEnd + titleEnd = i + } + } + + return +} + +// The first bit of this logic is the same as Parser.listItem, but the rest +// is much simpler. This function simply finds the entire block and shifts it +// over by one tab if it is indeed a block (just returns the line if it's not). +// blockEnd is the end of the section in the input buffer, and contents is the +// extracted text that was shifted over one tab. It will need to be rendered at +// the end of the document. +func scanFootnote(p *Markdown, data []byte, i, indentSize int) (blockStart, blockEnd int, contents []byte, hasBlock bool) { + if i == 0 || len(data) == 0 { + return + } + + // skip leading whitespace on first line + for i < len(data) && data[i] == ' ' { + i++ + } + + blockStart = i + + // find the end of the line + blockEnd = i + for i < len(data) && data[i-1] != '\n' { + i++ + } + + // get working buffer + var raw bytes.Buffer + + // put the first line into the working buffer + raw.Write(data[blockEnd:i]) + blockEnd = i + + // process the following lines + containsBlankLine := false + +gatherLines: + for blockEnd < len(data) { + i++ + + // find the end of this line + for i < len(data) && data[i-1] != '\n' { + i++ + } + + // if it is an empty line, guess that it is part of this item + // and move on to the next line + if p.isEmpty(data[blockEnd:i]) > 0 { + containsBlankLine = true + blockEnd = i + continue + } + + n := 0 + if n = isIndented(data[blockEnd:i], indentSize); n == 0 { + // this is the end of the block. + // we don't want to include this last line in the index. + break gatherLines + } + + // if there were blank lines before this one, insert a new one now + if containsBlankLine { + raw.WriteByte('\n') + containsBlankLine = false + } + + // get rid of that first tab, write to buffer + raw.Write(data[blockEnd+n : i]) + hasBlock = true + + blockEnd = i + } + + if data[blockEnd-1] != '\n' { + raw.WriteByte('\n') + } + + contents = raw.Bytes() + + return +} + +// +// +// Miscellaneous helper functions +// +// + +// Test if a character is a punctuation symbol. +// Taken from a private function in regexp in the stdlib. +func ispunct(c byte) bool { + for _, r := range []byte("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~") { + if c == r { + return true + } + } + return false +} + +// Test if a character is a whitespace character. +func isspace(c byte) bool { + return ishorizontalspace(c) || isverticalspace(c) +} + +// Test if a character is a horizontal whitespace character. +func ishorizontalspace(c byte) bool { + return c == ' ' || c == '\t' +} + +// Test if a character is a vertical character. +func isverticalspace(c byte) bool { + return c == '\n' || c == '\r' || c == '\f' || c == '\v' +} + +// Test if a character is letter. +func isletter(c byte) bool { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') +} + +// Test if a character is a letter or a digit. +// TODO: check when this is looking for ASCII alnum and when it should use unicode +func isalnum(c byte) bool { + return (c >= '0' && c <= '9') || isletter(c) +} + +// Replace tab characters with spaces, aligning to the next TAB_SIZE column. +// always ends output with a newline +func expandTabs(out *bytes.Buffer, line []byte, tabSize int) { + // first, check for common cases: no tabs, or only tabs at beginning of line + i, prefix := 0, 0 + slowcase := false + for i = 0; i < len(line); i++ { + if line[i] == '\t' { + if prefix == i { + prefix++ + } else { + slowcase = true + break + } + } + } + + // no need to decode runes if all tabs are at the beginning of the line + if !slowcase { + for i = 0; i < prefix*tabSize; i++ { + out.WriteByte(' ') + } + out.Write(line[prefix:]) + return + } + + // the slow case: we need to count runes to figure out how + // many spaces to insert for each tab + column := 0 + i = 0 + for i < len(line) { + start := i + for i < len(line) && line[i] != '\t' { + _, size := utf8.DecodeRune(line[i:]) + i += size + column++ + } + + if i > start { + out.Write(line[start:i]) + } + + if i >= len(line) { + break + } + + for { + out.WriteByte(' ') + column++ + if column%tabSize == 0 { + break + } + } + + i++ + } +} + +// Find if a line counts as indented or not. +// Returns number of characters the indent is (0 = not indented). +func isIndented(data []byte, indentSize int) int { + if len(data) == 0 { + return 0 + } + if data[0] == '\t' { + return 1 + } + if len(data) < indentSize { + return 0 + } + for i := 0; i < indentSize; i++ { + if data[i] != ' ' { + return 0 + } + } + return indentSize +} + +// Create a url-safe slug for fragments +func slugify(in []byte) []byte { + if len(in) == 0 { + return in + } + out := make([]byte, 0, len(in)) + sym := false + + for _, ch := range in { + if isalnum(ch) { + sym = false + out = append(out, ch) + } else if sym { + continue + } else { + out = append(out, '-') + sym = true + } + } + var a, b int + var ch byte + for a, ch = range out { + if ch != '-' { + break + } + } + for b = len(out) - 1; b > 0; b-- { + if out[b] != '-' { + break + } + } + return out[a : b+1] +} diff --git a/vendor/github.com/russross/blackfriday/v2/node.go b/vendor/github.com/russross/blackfriday/v2/node.go new file mode 100644 index 0000000000..04e6050cee --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/node.go @@ -0,0 +1,360 @@ +package blackfriday + +import ( + "bytes" + "fmt" +) + +// NodeType specifies a type of a single node of a syntax tree. Usually one +// node (and its type) corresponds to a single markdown feature, e.g. emphasis +// or code block. +type NodeType int + +// Constants for identifying different types of nodes. See NodeType. +const ( + Document NodeType = iota + BlockQuote + List + Item + Paragraph + Heading + HorizontalRule + Emph + Strong + Del + Link + Image + Text + HTMLBlock + CodeBlock + Softbreak + Hardbreak + Code + HTMLSpan + Table + TableCell + TableHead + TableBody + TableRow +) + +var nodeTypeNames = []string{ + Document: "Document", + BlockQuote: "BlockQuote", + List: "List", + Item: "Item", + Paragraph: "Paragraph", + Heading: "Heading", + HorizontalRule: "HorizontalRule", + Emph: "Emph", + Strong: "Strong", + Del: "Del", + Link: "Link", + Image: "Image", + Text: "Text", + HTMLBlock: "HTMLBlock", + CodeBlock: "CodeBlock", + Softbreak: "Softbreak", + Hardbreak: "Hardbreak", + Code: "Code", + HTMLSpan: "HTMLSpan", + Table: "Table", + TableCell: "TableCell", + TableHead: "TableHead", + TableBody: "TableBody", + TableRow: "TableRow", +} + +func (t NodeType) String() string { + return nodeTypeNames[t] +} + +// ListData contains fields relevant to a List and Item node type. +type ListData struct { + ListFlags ListType + Tight bool // Skip

      s around list item data if true + BulletChar byte // '*', '+' or '-' in bullet lists + Delimiter byte // '.' or ')' after the number in ordered lists + RefLink []byte // If not nil, turns this list item into a footnote item and triggers different rendering + IsFootnotesList bool // This is a list of footnotes +} + +// LinkData contains fields relevant to a Link node type. +type LinkData struct { + Destination []byte // Destination is what goes into a href + Title []byte // Title is the tooltip thing that goes in a title attribute + NoteID int // NoteID contains a serial number of a footnote, zero if it's not a footnote + Footnote *Node // If it's a footnote, this is a direct link to the footnote Node. Otherwise nil. +} + +// CodeBlockData contains fields relevant to a CodeBlock node type. +type CodeBlockData struct { + IsFenced bool // Specifies whether it's a fenced code block or an indented one + Info []byte // This holds the info string + FenceChar byte + FenceLength int + FenceOffset int +} + +// TableCellData contains fields relevant to a TableCell node type. +type TableCellData struct { + IsHeader bool // This tells if it's under the header row + Align CellAlignFlags // This holds the value for align attribute +} + +// HeadingData contains fields relevant to a Heading node type. +type HeadingData struct { + Level int // This holds the heading level number + HeadingID string // This might hold heading ID, if present + IsTitleblock bool // Specifies whether it's a title block +} + +// Node is a single element in the abstract syntax tree of the parsed document. +// It holds connections to the structurally neighboring nodes and, for certain +// types of nodes, additional information that might be needed when rendering. +type Node struct { + Type NodeType // Determines the type of the node + Parent *Node // Points to the parent + FirstChild *Node // Points to the first child, if any + LastChild *Node // Points to the last child, if any + Prev *Node // Previous sibling; nil if it's the first child + Next *Node // Next sibling; nil if it's the last child + + Literal []byte // Text contents of the leaf nodes + + HeadingData // Populated if Type is Heading + ListData // Populated if Type is List + CodeBlockData // Populated if Type is CodeBlock + LinkData // Populated if Type is Link + TableCellData // Populated if Type is TableCell + + content []byte // Markdown content of the block nodes + open bool // Specifies an open block node that has not been finished to process yet +} + +// NewNode allocates a node of a specified type. +func NewNode(typ NodeType) *Node { + return &Node{ + Type: typ, + open: true, + } +} + +func (n *Node) String() string { + ellipsis := "" + snippet := n.Literal + if len(snippet) > 16 { + snippet = snippet[:16] + ellipsis = "..." + } + return fmt.Sprintf("%s: '%s%s'", n.Type, snippet, ellipsis) +} + +// Unlink removes node 'n' from the tree. +// It panics if the node is nil. +func (n *Node) Unlink() { + if n.Prev != nil { + n.Prev.Next = n.Next + } else if n.Parent != nil { + n.Parent.FirstChild = n.Next + } + if n.Next != nil { + n.Next.Prev = n.Prev + } else if n.Parent != nil { + n.Parent.LastChild = n.Prev + } + n.Parent = nil + n.Next = nil + n.Prev = nil +} + +// AppendChild adds a node 'child' as a child of 'n'. +// It panics if either node is nil. +func (n *Node) AppendChild(child *Node) { + child.Unlink() + child.Parent = n + if n.LastChild != nil { + n.LastChild.Next = child + child.Prev = n.LastChild + n.LastChild = child + } else { + n.FirstChild = child + n.LastChild = child + } +} + +// InsertBefore inserts 'sibling' immediately before 'n'. +// It panics if either node is nil. +func (n *Node) InsertBefore(sibling *Node) { + sibling.Unlink() + sibling.Prev = n.Prev + if sibling.Prev != nil { + sibling.Prev.Next = sibling + } + sibling.Next = n + n.Prev = sibling + sibling.Parent = n.Parent + if sibling.Prev == nil { + sibling.Parent.FirstChild = sibling + } +} + +// IsContainer returns true if 'n' can contain children. +func (n *Node) IsContainer() bool { + switch n.Type { + case Document: + fallthrough + case BlockQuote: + fallthrough + case List: + fallthrough + case Item: + fallthrough + case Paragraph: + fallthrough + case Heading: + fallthrough + case Emph: + fallthrough + case Strong: + fallthrough + case Del: + fallthrough + case Link: + fallthrough + case Image: + fallthrough + case Table: + fallthrough + case TableHead: + fallthrough + case TableBody: + fallthrough + case TableRow: + fallthrough + case TableCell: + return true + default: + return false + } +} + +// IsLeaf returns true if 'n' is a leaf node. +func (n *Node) IsLeaf() bool { + return !n.IsContainer() +} + +func (n *Node) canContain(t NodeType) bool { + if n.Type == List { + return t == Item + } + if n.Type == Document || n.Type == BlockQuote || n.Type == Item { + return t != Item + } + if n.Type == Table { + return t == TableHead || t == TableBody + } + if n.Type == TableHead || n.Type == TableBody { + return t == TableRow + } + if n.Type == TableRow { + return t == TableCell + } + return false +} + +// WalkStatus allows NodeVisitor to have some control over the tree traversal. +// It is returned from NodeVisitor and different values allow Node.Walk to +// decide which node to go to next. +type WalkStatus int + +const ( + // GoToNext is the default traversal of every node. + GoToNext WalkStatus = iota + // SkipChildren tells walker to skip all children of current node. + SkipChildren + // Terminate tells walker to terminate the traversal. + Terminate +) + +// NodeVisitor is a callback to be called when traversing the syntax tree. +// Called twice for every node: once with entering=true when the branch is +// first visited, then with entering=false after all the children are done. +type NodeVisitor func(node *Node, entering bool) WalkStatus + +// Walk is a convenience method that instantiates a walker and starts a +// traversal of subtree rooted at n. +func (n *Node) Walk(visitor NodeVisitor) { + w := newNodeWalker(n) + for w.current != nil { + status := visitor(w.current, w.entering) + switch status { + case GoToNext: + w.next() + case SkipChildren: + w.entering = false + w.next() + case Terminate: + return + } + } +} + +type nodeWalker struct { + current *Node + root *Node + entering bool +} + +func newNodeWalker(root *Node) *nodeWalker { + return &nodeWalker{ + current: root, + root: root, + entering: true, + } +} + +func (nw *nodeWalker) next() { + if (!nw.current.IsContainer() || !nw.entering) && nw.current == nw.root { + nw.current = nil + return + } + if nw.entering && nw.current.IsContainer() { + if nw.current.FirstChild != nil { + nw.current = nw.current.FirstChild + nw.entering = true + } else { + nw.entering = false + } + } else if nw.current.Next == nil { + nw.current = nw.current.Parent + nw.entering = false + } else { + nw.current = nw.current.Next + nw.entering = true + } +} + +func dump(ast *Node) { + fmt.Println(dumpString(ast)) +} + +func dumpR(ast *Node, depth int) string { + if ast == nil { + return "" + } + indent := bytes.Repeat([]byte("\t"), depth) + content := ast.Literal + if content == nil { + content = ast.content + } + result := fmt.Sprintf("%s%s(%q)\n", indent, ast.Type, content) + for n := ast.FirstChild; n != nil; n = n.Next { + result += dumpR(n, depth+1) + } + return result +} + +func dumpString(ast *Node) string { + return dumpR(ast, 0) +} diff --git a/vendor/github.com/russross/blackfriday/v2/smartypants.go b/vendor/github.com/russross/blackfriday/v2/smartypants.go new file mode 100644 index 0000000000..3a220e9424 --- /dev/null +++ b/vendor/github.com/russross/blackfriday/v2/smartypants.go @@ -0,0 +1,457 @@ +// +// Blackfriday Markdown Processor +// Available at http://github.com/russross/blackfriday +// +// Copyright © 2011 Russ Ross . +// Distributed under the Simplified BSD License. +// See README.md for details. +// + +// +// +// SmartyPants rendering +// +// + +package blackfriday + +import ( + "bytes" + "io" +) + +// SPRenderer is a struct containing state of a Smartypants renderer. +type SPRenderer struct { + inSingleQuote bool + inDoubleQuote bool + callbacks [256]smartCallback +} + +func wordBoundary(c byte) bool { + return c == 0 || isspace(c) || ispunct(c) +} + +func tolower(c byte) byte { + if c >= 'A' && c <= 'Z' { + return c - 'A' + 'a' + } + return c +} + +func isdigit(c byte) bool { + return c >= '0' && c <= '9' +} + +func smartQuoteHelper(out *bytes.Buffer, previousChar byte, nextChar byte, quote byte, isOpen *bool, addNBSP bool) bool { + // edge of the buffer is likely to be a tag that we don't get to see, + // so we treat it like text sometimes + + // enumerate all sixteen possibilities for (previousChar, nextChar) + // each can be one of {0, space, punct, other} + switch { + case previousChar == 0 && nextChar == 0: + // context is not any help here, so toggle + *isOpen = !*isOpen + case isspace(previousChar) && nextChar == 0: + // [ "] might be [ "foo...] + *isOpen = true + case ispunct(previousChar) && nextChar == 0: + // [!"] hmm... could be [Run!"] or [("...] + *isOpen = false + case /* isnormal(previousChar) && */ nextChar == 0: + // [a"] is probably a close + *isOpen = false + case previousChar == 0 && isspace(nextChar): + // [" ] might be [...foo" ] + *isOpen = false + case isspace(previousChar) && isspace(nextChar): + // [ " ] context is not any help here, so toggle + *isOpen = !*isOpen + case ispunct(previousChar) && isspace(nextChar): + // [!" ] is probably a close + *isOpen = false + case /* isnormal(previousChar) && */ isspace(nextChar): + // [a" ] this is one of the easy cases + *isOpen = false + case previousChar == 0 && ispunct(nextChar): + // ["!] hmm... could be ["$1.95] or ["!...] + *isOpen = false + case isspace(previousChar) && ispunct(nextChar): + // [ "!] looks more like [ "$1.95] + *isOpen = true + case ispunct(previousChar) && ispunct(nextChar): + // [!"!] context is not any help here, so toggle + *isOpen = !*isOpen + case /* isnormal(previousChar) && */ ispunct(nextChar): + // [a"!] is probably a close + *isOpen = false + case previousChar == 0 /* && isnormal(nextChar) */ : + // ["a] is probably an open + *isOpen = true + case isspace(previousChar) /* && isnormal(nextChar) */ : + // [ "a] this is one of the easy cases + *isOpen = true + case ispunct(previousChar) /* && isnormal(nextChar) */ : + // [!"a] is probably an open + *isOpen = true + default: + // [a'b] maybe a contraction? + *isOpen = false + } + + // Note that with the limited lookahead, this non-breaking + // space will also be appended to single double quotes. + if addNBSP && !*isOpen { + out.WriteString(" ") + } + + out.WriteByte('&') + if *isOpen { + out.WriteByte('l') + } else { + out.WriteByte('r') + } + out.WriteByte(quote) + out.WriteString("quo;") + + if addNBSP && *isOpen { + out.WriteString(" ") + } + + return true +} + +func (r *SPRenderer) smartSingleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { + if len(text) >= 2 { + t1 := tolower(text[1]) + + if t1 == '\'' { + nextChar := byte(0) + if len(text) >= 3 { + nextChar = text[2] + } + if smartQuoteHelper(out, previousChar, nextChar, 'd', &r.inDoubleQuote, false) { + return 1 + } + } + + if (t1 == 's' || t1 == 't' || t1 == 'm' || t1 == 'd') && (len(text) < 3 || wordBoundary(text[2])) { + out.WriteString("’") + return 0 + } + + if len(text) >= 3 { + t2 := tolower(text[2]) + + if ((t1 == 'r' && t2 == 'e') || (t1 == 'l' && t2 == 'l') || (t1 == 'v' && t2 == 'e')) && + (len(text) < 4 || wordBoundary(text[3])) { + out.WriteString("’") + return 0 + } + } + } + + nextChar := byte(0) + if len(text) > 1 { + nextChar = text[1] + } + if smartQuoteHelper(out, previousChar, nextChar, 's', &r.inSingleQuote, false) { + return 0 + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartParens(out *bytes.Buffer, previousChar byte, text []byte) int { + if len(text) >= 3 { + t1 := tolower(text[1]) + t2 := tolower(text[2]) + + if t1 == 'c' && t2 == ')' { + out.WriteString("©") + return 2 + } + + if t1 == 'r' && t2 == ')' { + out.WriteString("®") + return 2 + } + + if len(text) >= 4 && t1 == 't' && t2 == 'm' && text[3] == ')' { + out.WriteString("™") + return 3 + } + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartDash(out *bytes.Buffer, previousChar byte, text []byte) int { + if len(text) >= 2 { + if text[1] == '-' { + out.WriteString("—") + return 1 + } + + if wordBoundary(previousChar) && wordBoundary(text[1]) { + out.WriteString("–") + return 0 + } + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartDashLatex(out *bytes.Buffer, previousChar byte, text []byte) int { + if len(text) >= 3 && text[1] == '-' && text[2] == '-' { + out.WriteString("—") + return 2 + } + if len(text) >= 2 && text[1] == '-' { + out.WriteString("–") + return 1 + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartAmpVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte, addNBSP bool) int { + if bytes.HasPrefix(text, []byte(""")) { + nextChar := byte(0) + if len(text) >= 7 { + nextChar = text[6] + } + if smartQuoteHelper(out, previousChar, nextChar, quote, &r.inDoubleQuote, addNBSP) { + return 5 + } + } + + if bytes.HasPrefix(text, []byte("�")) { + return 3 + } + + out.WriteByte('&') + return 0 +} + +func (r *SPRenderer) smartAmp(angledQuotes, addNBSP bool) func(*bytes.Buffer, byte, []byte) int { + var quote byte = 'd' + if angledQuotes { + quote = 'a' + } + + return func(out *bytes.Buffer, previousChar byte, text []byte) int { + return r.smartAmpVariant(out, previousChar, text, quote, addNBSP) + } +} + +func (r *SPRenderer) smartPeriod(out *bytes.Buffer, previousChar byte, text []byte) int { + if len(text) >= 3 && text[1] == '.' && text[2] == '.' { + out.WriteString("…") + return 2 + } + + if len(text) >= 5 && text[1] == ' ' && text[2] == '.' && text[3] == ' ' && text[4] == '.' { + out.WriteString("…") + return 4 + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartBacktick(out *bytes.Buffer, previousChar byte, text []byte) int { + if len(text) >= 2 && text[1] == '`' { + nextChar := byte(0) + if len(text) >= 3 { + nextChar = text[2] + } + if smartQuoteHelper(out, previousChar, nextChar, 'd', &r.inDoubleQuote, false) { + return 1 + } + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartNumberGeneric(out *bytes.Buffer, previousChar byte, text []byte) int { + if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 { + // is it of the form digits/digits(word boundary)?, i.e., \d+/\d+\b + // note: check for regular slash (/) or fraction slash (⁄, 0x2044, or 0xe2 81 84 in utf-8) + // and avoid changing dates like 1/23/2005 into fractions. + numEnd := 0 + for len(text) > numEnd && isdigit(text[numEnd]) { + numEnd++ + } + if numEnd == 0 { + out.WriteByte(text[0]) + return 0 + } + denStart := numEnd + 1 + if len(text) > numEnd+3 && text[numEnd] == 0xe2 && text[numEnd+1] == 0x81 && text[numEnd+2] == 0x84 { + denStart = numEnd + 3 + } else if len(text) < numEnd+2 || text[numEnd] != '/' { + out.WriteByte(text[0]) + return 0 + } + denEnd := denStart + for len(text) > denEnd && isdigit(text[denEnd]) { + denEnd++ + } + if denEnd == denStart { + out.WriteByte(text[0]) + return 0 + } + if len(text) == denEnd || wordBoundary(text[denEnd]) && text[denEnd] != '/' { + out.WriteString("") + out.Write(text[:numEnd]) + out.WriteString("") + out.Write(text[denStart:denEnd]) + out.WriteString("") + return denEnd - 1 + } + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartNumber(out *bytes.Buffer, previousChar byte, text []byte) int { + if wordBoundary(previousChar) && previousChar != '/' && len(text) >= 3 { + if text[0] == '1' && text[1] == '/' && text[2] == '2' { + if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' { + out.WriteString("½") + return 2 + } + } + + if text[0] == '1' && text[1] == '/' && text[2] == '4' { + if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' || (len(text) >= 5 && tolower(text[3]) == 't' && tolower(text[4]) == 'h') { + out.WriteString("¼") + return 2 + } + } + + if text[0] == '3' && text[1] == '/' && text[2] == '4' { + if len(text) < 4 || wordBoundary(text[3]) && text[3] != '/' || (len(text) >= 6 && tolower(text[3]) == 't' && tolower(text[4]) == 'h' && tolower(text[5]) == 's') { + out.WriteString("¾") + return 2 + } + } + } + + out.WriteByte(text[0]) + return 0 +} + +func (r *SPRenderer) smartDoubleQuoteVariant(out *bytes.Buffer, previousChar byte, text []byte, quote byte) int { + nextChar := byte(0) + if len(text) > 1 { + nextChar = text[1] + } + if !smartQuoteHelper(out, previousChar, nextChar, quote, &r.inDoubleQuote, false) { + out.WriteString(""") + } + + return 0 +} + +func (r *SPRenderer) smartDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { + return r.smartDoubleQuoteVariant(out, previousChar, text, 'd') +} + +func (r *SPRenderer) smartAngledDoubleQuote(out *bytes.Buffer, previousChar byte, text []byte) int { + return r.smartDoubleQuoteVariant(out, previousChar, text, 'a') +} + +func (r *SPRenderer) smartLeftAngle(out *bytes.Buffer, previousChar byte, text []byte) int { + i := 0 + + for i < len(text) && text[i] != '>' { + i++ + } + + out.Write(text[:i+1]) + return i +} + +type smartCallback func(out *bytes.Buffer, previousChar byte, text []byte) int + +// NewSmartypantsRenderer constructs a Smartypants renderer object. +func NewSmartypantsRenderer(flags HTMLFlags) *SPRenderer { + var ( + r SPRenderer + + smartAmpAngled = r.smartAmp(true, false) + smartAmpAngledNBSP = r.smartAmp(true, true) + smartAmpRegular = r.smartAmp(false, false) + smartAmpRegularNBSP = r.smartAmp(false, true) + + addNBSP = flags&SmartypantsQuotesNBSP != 0 + ) + + if flags&SmartypantsAngledQuotes == 0 { + r.callbacks['"'] = r.smartDoubleQuote + if !addNBSP { + r.callbacks['&'] = smartAmpRegular + } else { + r.callbacks['&'] = smartAmpRegularNBSP + } + } else { + r.callbacks['"'] = r.smartAngledDoubleQuote + if !addNBSP { + r.callbacks['&'] = smartAmpAngled + } else { + r.callbacks['&'] = smartAmpAngledNBSP + } + } + r.callbacks['\''] = r.smartSingleQuote + r.callbacks['('] = r.smartParens + if flags&SmartypantsDashes != 0 { + if flags&SmartypantsLatexDashes == 0 { + r.callbacks['-'] = r.smartDash + } else { + r.callbacks['-'] = r.smartDashLatex + } + } + r.callbacks['.'] = r.smartPeriod + if flags&SmartypantsFractions == 0 { + r.callbacks['1'] = r.smartNumber + r.callbacks['3'] = r.smartNumber + } else { + for ch := '1'; ch <= '9'; ch++ { + r.callbacks[ch] = r.smartNumberGeneric + } + } + r.callbacks['<'] = r.smartLeftAngle + r.callbacks['`'] = r.smartBacktick + return &r +} + +// Process is the entry point of the Smartypants renderer. +func (r *SPRenderer) Process(w io.Writer, text []byte) { + mark := 0 + for i := 0; i < len(text); i++ { + if action := r.callbacks[text[i]]; action != nil { + if i > mark { + w.Write(text[mark:i]) + } + previousChar := byte(0) + if i > 0 { + previousChar = text[i-1] + } + var tmp bytes.Buffer + i += action(&tmp, previousChar, text[i:]) + w.Write(tmp.Bytes()) + mark = i + 1 + } + } + if mark < len(text) { + w.Write(text[mark:]) + } +} diff --git a/vendor/github.com/tidwall/btree/LICENSE b/vendor/github.com/tidwall/btree/LICENSE new file mode 100644 index 0000000000..5f1fbd044a --- /dev/null +++ b/vendor/github.com/tidwall/btree/LICENSE @@ -0,0 +1,18 @@ +Copyright (c) 2020 Josh Baker + +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/tidwall/btree/PATH_HINT.md b/vendor/github.com/tidwall/btree/PATH_HINT.md new file mode 100644 index 0000000000..4f243c47de --- /dev/null +++ b/vendor/github.com/tidwall/btree/PATH_HINT.md @@ -0,0 +1,45 @@ +# B-tree Path Hints + +I use a thing I call path hints in my B-tree [C](https://github.com/tidwall/btree.c) and [Go](https://github.com/tidwall/btree) implementations. It's a search optimization. + +## The B-tree + +A standard [B-tree](https://en.wikipedia.org/wiki/B-tree) is an ordered tree-based data structure that stores its items in nodes. The B-tree has a single root node, which may have children nodes, and those children nodes may also have children nodes. + +image + +Searching for items in a B-tree is fast. [O(log N)](https://en.wikipedia.org/wiki/Big_O_notation) to be exact. +This is because the [binary search algorithm](https://en.wikipedia.org/wiki/Binary_search_algorithm) is used. + +A binary search works by first comparing the item at the middle-most index of the root node with the target item. +If the middle item is greater than the target item, then it divides the node in two and does the binary search on the left part of the node. If the middle is less, it searches the right part. And so on. If the target item is found, then the search stop. If the item is not found, then the search is passed to the child node at the appropriate index. This traversal terminates when item is found or there are no more child nodes. + +image + +## The Path + +Each index is a component of the path to the item (or where the item should be stored, if it does not exist in the tree). + +Take the first example image. The item 9 is at path “1/0”. The item 16 is at path “1”. The item 21 is at path “2/1”. The item 5 is at path “0/2”. + +## The Path Hint + +A Path Hint is a predefined path that is provided to B-tree operations. It’s just a hint that says, “Hey B-tree, instead of starting your binary search with the middle index, start with what I provide you. My path may be wrong, and if so please provide me with the correct path so I get it right the next time.” + +I’ve found using path hints can lead to a little performance increase of 150% - 300%. This is because in real-world cases the items that I’m working with are usually nearby each other in the tree. + +Take for example inserting a group of timeseries points. They may often be received as chucks of near-contiguous items. +Or, I'm sequentially inserting an ordered group of rows somewhere in the middle of a table. +Or, I have a Redis-style key/value store, where the keys look have the common structure “user:98512:name”, “user:98512:email”, and I want to update a bunch of values for specified user. +Using a path hint may help to avoid the unnecessary binary searching in each of these examples. + +While I may see a 3x boost in when the path hint is right on, I'll only see around 5% decrease when the path hint is totally wrong. + +## Using a Path Hint + +All of the functions that take in a path hint argument mutate the path hint argument. + +For single-threaded programs, it’s possible to use one shared path hint per B-tree for the life of the program. +For multi-threaded programs, I find it best to use one path hint per B-tree , per thread. +For server-client programs, one path hint per B-tree, per client should suffice. + diff --git a/vendor/github.com/tidwall/btree/README.md b/vendor/github.com/tidwall/btree/README.md new file mode 100644 index 0000000000..b3572f940e --- /dev/null +++ b/vendor/github.com/tidwall/btree/README.md @@ -0,0 +1,455 @@ +# btree + +[![GoDoc](https://godoc.org/github.com/tidwall/btree?status.svg)](https://godoc.org/github.com/tidwall/btree) + +An efficient [B-tree](https://en.wikipedia.org/wiki/B-tree) implementation in Go. + +## Features + +- Support for [Generics](#generics) (Go 1.18+). +- `Map` and `Set` types for ordered key-value maps and sets, +- Fast bulk loading for pre-ordered data using the `Load()` method. +- `Copy()` method with copy-on-write support. +- [Path hinting](PATH_HINT.md) optimization for operations with nearby keys. + +## Using + +To start using this package, install Go and run: + +```sh +$ go get github.com/tidwall/btree +``` + +## B-tree types + +This package includes the following types of B-trees: + +- [`btree.Map`](#btreemap): +A fast B-tree for storing ordered key value pairs. + +- [`btree.Set`](#btreeset): +Like `Map`, but only for storing keys. + +- [`btree.BTreeG`](#btreebtreeg): +A feature-rich B-tree for storing data using a custom comparator. Thread-safe. + +- [`btree.BTree`](#btreebtree): +Like `BTreeG` but uses the `interface{}` type for data. Backwards compatible. Thread-safe. + +### btree.Map + +```go +// Basic +Set(key, value) // insert or replace an item +Get(key, value) // get an existing item +Delete(key) // delete an item +Len() // return the number of items in the map + +// Iteration +Scan(iter) // scan items in ascending order +Reverse(iter) // scan items in descending order +Ascend(key, iter) // scan items in ascending order that are >= to key +Descend(key, iter) // scan items in descending order that are <= to key. +Iter() // returns a read-only iterator for for-loops. + +// Array-like operations +GetAt(index) // returns the item at index +DeleteAt(index) // deletes the item at index + +// Bulk-loading +Load(key, value) // load presorted items into tree +``` + +#### Example + +```go +package main + +import ( + "fmt" + "github.com/tidwall/btree" +) + +func main() { + // create a map + var users btree.Map[string, string] + + // add some users + users.Set("user:4", "Andrea") + users.Set("user:6", "Andy") + users.Set("user:2", "Andy") + users.Set("user:1", "Jane") + users.Set("user:5", "Janet") + users.Set("user:3", "Steve") + + // Iterate over the maps and print each user + users.Scan(func(key, value string) bool { + fmt.Printf("%s %s\n", key, value) + return true + }) + fmt.Printf("\n") + + // Delete a couple + users.Delete("user:5") + users.Delete("user:1") + + // print the map again + users.Scan(func(key, value string) bool { + fmt.Printf("%s %s\n", key, value) + return true + }) + fmt.Printf("\n") + + // Output: + // user:1 Jane + // user:2 Andy + // user:3 Steve + // user:4 Andrea + // user:5 Janet + // user:6 Andy + // + // user:2 Andy + // user:3 Steve + // user:4 Andrea + // user:6 Andy +} +``` + +### btree.Set + +```go +// Basic +Insert(key) // insert an item +Contains(key) // test if item exists +Delete(key) // delete an item +Len() // return the number of items in the set + +// Iteration +Scan(iter) // scan items in ascending order +Reverse(iter) // scan items in descending order +Ascend(key, iter) // scan items in ascending order that are >= to key +Descend(key, iter) // scan items in descending order that are <= to key. +Iter() // returns a read-only iterator for for-loops. + +// Array-like operations +GetAt(index) // returns the item at index +DeleteAt(index) // deletes the item at index + +// Bulk-loading +Load(key) // load presorted item into tree +``` + +#### Example + +```go +package main + +import ( + "fmt" + "github.com/tidwall/btree" +) + +func main() { + // create a set + var names btree.Set[string] + + // add some names + names.Insert("Jane") + names.Insert("Andrea") + names.Insert("Steve") + names.Insert("Andy") + names.Insert("Janet") + names.Insert("Andy") + + // Iterate over the maps and print each user + names.Scan(func(key string) bool { + fmt.Printf("%s\n", key) + return true + }) + fmt.Printf("\n") + + // Delete a couple + names.Delete("Steve") + names.Delete("Andy") + + // print the map again + names.Scan(func(key string) bool { + fmt.Printf("%s\n", key) + return true + }) + fmt.Printf("\n") + + // Output: + // Andrea + // Andy + // Jane + // Janet + // Steve + // + // Andrea + // Jane + // Janet +} +``` + +### btree.BTreeG + +```go +// Basic +Set(item) // insert or replace an item +Get(item) // get an existing item +Delete(item) // delete an item +Len() // return the number of items in the btree + +// Iteration +Scan(iter) // scan items in ascending order +Reverse(iter) // scan items in descending order +Ascend(key, iter) // scan items in ascending order that are >= to key +Descend(key, iter) // scan items in descending order that are <= to key. +Iter() // returns a read-only iterator for for-loops. + +// Array-like operations +GetAt(index) // returns the item at index +DeleteAt(index) // deletes the item at index + +// Bulk-loading +Load(item) // load presorted items into tree + +// Path hinting +SetHint(item, *hint) // insert or replace an existing item +GetHint(item, *hint) // get an existing item +DeleteHint(item, *hint) // delete an item +AscendHint(key, iter, *hint) +DescendHint(key, iter, *hint) +SeekHint(key, iter, *hint) + +// Copy-on-write +Copy() // copy the btree +``` + +#### Example + +```go +package main + +import ( + "fmt" + + "github.com/tidwall/btree" +) + +type Item struct { + Key, Val string +} + +// byKeys is a comparison function that compares item keys and returns true +// when a is less than b. +func byKeys(a, b Item) bool { + return a.Key < b.Key +} + +// byVals is a comparison function that compares item values and returns true +// when a is less than b. +func byVals(a, b Item) bool { + if a.Val < b.Val { + return true + } + if a.Val > b.Val { + return false + } + // Both vals are equal so we should fall though + // and let the key comparison take over. + return byKeys(a, b) +} + +func main() { + // Create a tree for keys and a tree for values. + // The "keys" tree will be sorted on the Keys field. + // The "values" tree will be sorted on the Values field. + keys := btree.NewBTreeG[Item](byKeys) + vals := btree.NewBTreeG[Item](byVals) + + // Create some items. + users := []Item{ + Item{Key: "user:1", Val: "Jane"}, + Item{Key: "user:2", Val: "Andy"}, + Item{Key: "user:3", Val: "Steve"}, + Item{Key: "user:4", Val: "Andrea"}, + Item{Key: "user:5", Val: "Janet"}, + Item{Key: "user:6", Val: "Andy"}, + } + + // Insert each user into both trees + for _, user := range users { + keys.Set(user) + vals.Set(user) + } + + // Iterate over each user in the key tree + keys.Scan(func(item Item) bool { + fmt.Printf("%s %s\n", item.Key, item.Val) + return true + }) + fmt.Printf("\n") + + // Iterate over each user in the val tree + vals.Scan(func(item Item) bool { + fmt.Printf("%s %s\n", item.Key, item.Val) + return true + }) + + // Output: + // user:1 Jane + // user:2 Andy + // user:3 Steve + // user:4 Andrea + // user:5 Janet + // user:6 Andy + // + // user:4 Andrea + // user:2 Andy + // user:6 Andy + // user:1 Jane + // user:5 Janet + // user:3 Steve +} +``` + +### btree.BTree + +```go +// Basic +Set(item) // insert or replace an item +Get(item) // get an existing item +Delete(item) // delete an item +Len() // return the number of items in the btree + +// Iteration +Scan(iter) // scan items in ascending order +Reverse(iter) // scan items in descending order +Ascend(key, iter) // scan items in ascending order that are >= to key +Descend(key, iter) // scan items in descending order that are <= to key. +Iter() // returns a read-only iterator for for-loops. + +// Array-like operations +GetAt(index) // returns the item at index +DeleteAt(index) // deletes the item at index + +// Bulk-loading +Load(item) // load presorted items into tree + +// Path hinting +SetHint(item, *hint) // insert or replace an existing item +GetHint(item, *hint) // get an existing item +DeleteHint(item, *hint) // delete an item +AscendHint(key, iter, *hint) +DescendHint(key, iter, *hint) +SeekHint(key, iter, *hint) + +// Copy-on-write +Copy() // copy the btree +``` + +#### Example + +```go +package main + +import ( + "fmt" + + "github.com/tidwall/btree" +) + +type Item struct { + Key, Val string +} + +// byKeys is a comparison function that compares item keys and returns true +// when a is less than b. +func byKeys(a, b interface{}) bool { + i1, i2 := a.(*Item), b.(*Item) + return i1.Key < i2.Key +} + +// byVals is a comparison function that compares item values and returns true +// when a is less than b. +func byVals(a, b interface{}) bool { + i1, i2 := a.(*Item), b.(*Item) + if i1.Val < i2.Val { + return true + } + if i1.Val > i2.Val { + return false + } + // Both vals are equal so we should fall though + // and let the key comparison take over. + return byKeys(a, b) +} + +func main() { + // Create a tree for keys and a tree for values. + // The "keys" tree will be sorted on the Keys field. + // The "values" tree will be sorted on the Values field. + keys := btree.New(byKeys) + vals := btree.New(byVals) + + // Create some items. + users := []*Item{ + &Item{Key: "user:1", Val: "Jane"}, + &Item{Key: "user:2", Val: "Andy"}, + &Item{Key: "user:3", Val: "Steve"}, + &Item{Key: "user:4", Val: "Andrea"}, + &Item{Key: "user:5", Val: "Janet"}, + &Item{Key: "user:6", Val: "Andy"}, + } + + // Insert each user into both trees + for _, user := range users { + keys.Set(user) + vals.Set(user) + } + + // Iterate over each user in the key tree + keys.Ascend(nil, func(item interface{}) bool { + kvi := item.(*Item) + fmt.Printf("%s %s\n", kvi.Key, kvi.Val) + return true + }) + + fmt.Printf("\n") + // Iterate over each user in the val tree + vals.Ascend(nil, func(item interface{}) bool { + kvi := item.(*Item) + fmt.Printf("%s %s\n", kvi.Key, kvi.Val) + return true + }) + + // Output: + // user:1 Jane + // user:2 Andy + // user:3 Steve + // user:4 Andrea + // user:5 Janet + // user:6 Andy + // + // user:4 Andrea + // user:2 Andy + // user:6 Andy + // user:1 Jane + // user:5 Janet + // user:3 Steve +} +``` + +## Performance + +See [tidwall/btree-benchmark](https://github.com/tidwall/btree-benchmark) for benchmark numbers. + +## Contact + +Josh Baker [@tidwall](http://twitter.com/tidwall) + +## License + +Source code is available under the MIT [License](/LICENSE). diff --git a/vendor/github.com/tidwall/btree/btree.go b/vendor/github.com/tidwall/btree/btree.go new file mode 100644 index 0000000000..9e2327e670 --- /dev/null +++ b/vendor/github.com/tidwall/btree/btree.go @@ -0,0 +1,399 @@ +// Copyright 2020 Joshua J Baker. All rights reserved. +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. +package btree + +type BTree struct { + base *BTreeG[any] +} + +// New returns a new BTree +func New(less func(a, b any) bool) *BTree { + if less == nil { + panic("nil less") + } + return &BTree{base: NewBTreeG(less)} +} + +// NewNonConcurrent returns a new BTree which is not safe for concurrent +// write operations by multiple goroutines. +// +// This is useful for when you do not need the BTree to manage the locking, +// but would rather do it yourself. +// +// Deprecated: use NewOptions +func NewNonConcurrent(less func(a, b any) bool) *BTree { + if less == nil { + panic("nil less") + } + return &BTree{base: NewBTreeGOptions(less, Options{NoLocks: true})} +} + +// NewOptions returns a new BTree +func NewOptions(less func(a, b any) bool, opts Options) *BTree { + if less == nil { + panic("nil less") + } + return &BTree{base: NewBTreeGOptions(less, opts)} +} + +// Less is a convenience function that performs a comparison of two items +// using the same "less" function provided to New. +func (tr *BTree) Less(a, b any) bool { + return tr.base.Less(a, b) +} + +// Set or replace a value for a key +// Returns the value for the replaced item or nil if the key was not found. +func (tr *BTree) Set(item any) (prev any) { + return tr.SetHint(item, nil) +} + +// SetHint sets or replace a value for a key using a path hint +// Returns the value for the replaced item or nil if the key was not found. +func (tr *BTree) SetHint(item any, hint *PathHint) (prev any) { + if item == nil { + panic("nil item") + } + v, ok := tr.base.SetHint(item, hint) + if !ok { + return nil + } + return v +} + +// Get a value for key. +// Returns nil if the key was not found. +func (tr *BTree) Get(key any) any { + return tr.getHintMut(key, nil, false) +} + +func (tr *BTree) GetMut(key any) any { + return tr.getHintMut(key, nil, true) +} + +func (tr *BTree) GetHint(key any, hint *PathHint) any { + return tr.getHintMut(key, hint, false) +} + +func (tr *BTree) GetHintMut(key any, hint *PathHint) any { + return tr.getHintMut(key, hint, true) +} + +// GetHint gets a value for key using a path hint. +// Returns nil if the item was not found. +func (tr *BTree) getHintMut(key any, hint *PathHint, mut bool) (value any) { + if key == nil { + return nil + } + var v any + var ok bool + if mut { + v, ok = tr.base.GetHintMut(key, hint) + } else { + v, ok = tr.base.GetHint(key, hint) + } + if !ok { + return nil + } + return v +} + +// Len returns the number of items in the tree +func (tr *BTree) Len() int { + return tr.base.Len() +} + +// Delete an item for a key. +// Returns the deleted value or nil if the key was not found. +func (tr *BTree) Delete(key any) (prev any) { + return tr.DeleteHint(key, nil) +} + +// DeleteHint deletes a value for a key using a path hint +// Returns the deleted value or nil if the key was not found. +func (tr *BTree) DeleteHint(key any, hint *PathHint) (prev any) { + if key == nil { + return nil + } + v, ok := tr.base.DeleteHint(key, nil) + if !ok { + return nil + } + return v +} + +// Ascend the tree within the range [pivot, last] +// Pass nil for pivot to scan all item in ascending order +// Return false to stop iterating +func (tr *BTree) Ascend(pivot any, iter func(item any) bool) { + if pivot == nil { + tr.base.Scan(iter) + } else { + tr.base.Ascend(pivot, iter) + } +} + +func (tr *BTree) AscendMut(pivot any, iter func(item any) bool) { + if pivot == nil { + tr.base.ScanMut(iter) + } else { + tr.base.AscendMut(pivot, iter) + } +} + +func (tr *BTree) AscendHint(pivot any, iter func(item any) bool, + hint *PathHint, +) { + if pivot == nil { + tr.base.Scan(iter) + } else { + tr.base.AscendHint(pivot, iter, hint) + } +} + +func (tr *BTree) AscendHintMut(pivot any, iter func(item any) bool, + hint *PathHint, +) { + if pivot == nil { + tr.base.ScanMut(iter) + } else { + tr.base.AscendHintMut(pivot, iter, hint) + } +} + +// Descend the tree within the range [pivot, first] +// Pass nil for pivot to scan all item in descending order +// Return false to stop iterating +func (tr *BTree) Descend(pivot any, iter func(item any) bool) { + if pivot == nil { + tr.base.Reverse(iter) + } else { + tr.base.Descend(pivot, iter) + } +} + +func (tr *BTree) DescendMut(pivot any, iter func(item any) bool) { + if pivot == nil { + tr.base.ReverseMut(iter) + } else { + tr.base.DescendMut(pivot, iter) + } +} + +func (tr *BTree) DescendHint(pivot any, iter func(item any) bool, + hint *PathHint, +) { + if pivot == nil { + tr.base.Reverse(iter) + } else { + tr.base.DescendHint(pivot, iter, hint) + } +} + +func (tr *BTree) DescendHintMut(pivot any, iter func(item any) bool, + hint *PathHint, +) { + if pivot == nil { + tr.base.ReverseMut(iter) + } else { + tr.base.DescendHintMut(pivot, iter, hint) + } +} + +// Load is for bulk loading pre-sorted items +// If the load replaces and existing item then the value for the replaced item +// is returned. +func (tr *BTree) Load(item any) (prev any) { + if item == nil { + panic("nil item") + } + v, ok := tr.base.Load(item) + if !ok { + return nil + } + return v +} + +// Min returns the minimum item in tree. +// Returns nil if the tree has no items. +func (tr *BTree) Min() any { + v, ok := tr.base.Min() + if !ok { + return nil + } + return v +} + +func (tr *BTree) MinMut() any { + v, ok := tr.base.MinMut() + if !ok { + return nil + } + return v +} + +// Max returns the maximum item in tree. +// Returns nil if the tree has no items. +func (tr *BTree) Max() any { + v, ok := tr.base.Max() + if !ok { + return nil + } + return v +} + +func (tr *BTree) MaxMut() any { + v, ok := tr.base.Max() + if !ok { + return nil + } + return v +} + +// PopMin removes the minimum item in tree and returns it. +// Returns nil if the tree has no items. +func (tr *BTree) PopMin() any { + v, ok := tr.base.PopMin() + if !ok { + return nil + } + return v +} + +// PopMax removes the maximum item in tree and returns it. +// Returns nil if the tree has no items. +func (tr *BTree) PopMax() any { + v, ok := tr.base.PopMax() + if !ok { + return nil + } + return v +} + +// GetAt returns the value at index. +// Return nil if the tree is empty or the index is out of bounds. +func (tr *BTree) GetAt(index int) any { + v, ok := tr.base.GetAt(index) + if !ok { + return nil + } + return v +} + +func (tr *BTree) GetAtMut(index int) any { + v, ok := tr.base.GetAtMut(index) + if !ok { + return nil + } + return v +} + +// DeleteAt deletes the item at index. +// Return nil if the tree is empty or the index is out of bounds. +func (tr *BTree) DeleteAt(index int) any { + v, ok := tr.base.DeleteAt(index) + if !ok { + return nil + } + return v +} + +// Height returns the height of the tree. +// Returns zero if tree has no items. +func (tr *BTree) Height() int { + return tr.base.Height() +} + +// Walk iterates over all items in tree, in order. +// The items param will contain one or more items. +func (tr *BTree) Walk(iter func(items []any)) { + tr.base.Walk(func(items []any) bool { + iter(items) + return true + }) +} + +func (tr *BTree) WalkMut(iter func(items []any)) { + tr.base.WalkMut(func(items []any) bool { + iter(items) + return true + }) +} + +// Copy the tree. This is a copy-on-write operation and is very fast because +// it only performs a shadowed copy. +func (tr *BTree) Copy() *BTree { + return &BTree{base: tr.base.Copy()} +} + +func (tr *BTree) IsoCopy() *BTree { + return &BTree{base: tr.base.IsoCopy()} +} + +// Clear will delete all items. +func (tr *BTree) Clear() { + tr.base.Clear() +} + +// Iter is an iterator for +type Iter struct { + base IterG[any] +} + +// Iter returns a read-only iterator. +// The Release method must be called finished with iterator. +func (tr *BTree) Iter() Iter { + return Iter{tr.base.Iter()} +} + +func (tr *BTree) IterMut() Iter { + return Iter{tr.base.IterMut()} +} + +// Seek to item greater-or-equal-to key. +// Returns false if there was no item found. +func (iter *Iter) Seek(key any) bool { + return iter.base.Seek(key) +} + +func (iter *Iter) SeekHint(key any, hint *PathHint) bool { + return iter.base.SeekHint(key, hint) +} + +// First moves iterator to first item in tree. +// Returns false if the tree is empty. +func (iter *Iter) First() bool { + return iter.base.First() +} + +// Last moves iterator to last item in tree. +// Returns false if the tree is empty. +func (iter *Iter) Last() bool { + return iter.base.Last() +} + +// First moves iterator to first item in tree. +// Returns false if the tree is empty. +func (iter *Iter) Release() { + iter.base.Release() +} + +// Next moves iterator to the next item in iterator. +// Returns false if the tree is empty or the iterator is at the end of +// the tree. +func (iter *Iter) Next() bool { + return iter.base.Next() +} + +// Prev moves iterator to the previous item in iterator. +// Returns false if the tree is empty or the iterator is at the beginning of +// the tree. +func (iter *Iter) Prev() bool { + return iter.base.Prev() +} + +// Item returns the current iterator item. +func (iter *Iter) Item() any { + return iter.base.Item() +} diff --git a/vendor/github.com/tidwall/btree/btreeg.go b/vendor/github.com/tidwall/btree/btreeg.go new file mode 100644 index 0000000000..b83055dfba --- /dev/null +++ b/vendor/github.com/tidwall/btree/btreeg.go @@ -0,0 +1,1427 @@ +// Copyright 2020 Joshua J Baker. All rights reserved. +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. +package btree + +import "sync" + +type BTreeG[T any] struct { + isoid uint64 + mu *sync.RWMutex + root *node[T] + count int + locks bool + copyItems bool + isoCopyItems bool + less func(a, b T) bool + empty T + max int + min int +} + +type node[T any] struct { + isoid uint64 + count int + items []T + children *[]*node[T] +} + +// PathHint is a utility type used with the *Hint() functions. Hints provide +// faster operations for clustered keys. +type PathHint struct { + used [8]bool + path [8]uint8 +} + +// Options for passing to New when creating a new BTree. +type Options struct { + // Degree is used to define how many items and children each internal node + // can contain before it must branch. For example, a degree of 2 will + // create a 2-3-4 tree, where each node may contains 1-3 items and + // 2-4 children. See https://en.wikipedia.org/wiki/2–3–4_tree. + // Default is 32 + Degree int + // NoLocks will disable locking. Otherwide a sync.RWMutex is used to + // ensure all operations are safe across multiple goroutines. + NoLocks bool +} + +// New returns a new BTree +func NewBTreeG[T any](less func(a, b T) bool) *BTreeG[T] { + return NewBTreeGOptions(less, Options{}) +} + +func NewBTreeGOptions[T any](less func(a, b T) bool, opts Options) *BTreeG[T] { + tr := new(BTreeG[T]) + tr.isoid = newIsoID() + tr.mu = new(sync.RWMutex) + tr.locks = !opts.NoLocks + tr.less = less + tr.init(opts.Degree) + return tr +} + +func (tr *BTreeG[T]) init(degree int) { + if tr.min != 0 { + return + } + tr.min, tr.max = degreeToMinMax(degree) + _, tr.copyItems = ((interface{})(tr.empty)).(copier[T]) + if !tr.copyItems { + _, tr.isoCopyItems = ((interface{})(tr.empty)).(isoCopier[T]) + } +} + +// Less is a convenience function that performs a comparison of two items +// using the same "less" function provided to New. +func (tr *BTreeG[T]) Less(a, b T) bool { + return tr.less(a, b) +} + +func (tr *BTreeG[T]) newNode(leaf bool) *node[T] { + n := &node[T]{isoid: tr.isoid} + if !leaf { + n.children = new([]*node[T]) + } + return n +} + +// leaf returns true if the node is a leaf. +func (n *node[T]) leaf() bool { + return n.children == nil +} + +func (tr *BTreeG[T]) bsearch(n *node[T], key T) (index int, found bool) { + low, high := 0, len(n.items) + for low < high { + h := (low + high) / 2 + if !tr.less(key, n.items[h]) { + low = h + 1 + } else { + high = h + } + } + if low > 0 && !tr.less(n.items[low-1], key) { + return low - 1, true + } + return low, false +} + +func (tr *BTreeG[T]) find(n *node[T], key T, hint *PathHint, depth int, +) (index int, found bool) { + if hint == nil { + return tr.bsearch(n, key) + } + return tr.hintsearch(n, key, hint, depth) +} + +func (tr *BTreeG[T]) hintsearch(n *node[T], key T, hint *PathHint, depth int, +) (index int, found bool) { + // Best case finds the exact match, updates the hint and returns. + // Worst case, updates the low and high bounds to binary search between. + low := 0 + high := len(n.items) - 1 + if depth < 8 && hint.used[depth] { + index = int(hint.path[depth]) + if index >= len(n.items) { + // tail item + if tr.Less(n.items[len(n.items)-1], key) { + index = len(n.items) + goto path_match + } + index = len(n.items) - 1 + } + if tr.Less(key, n.items[index]) { + if index == 0 || tr.Less(n.items[index-1], key) { + goto path_match + } + high = index - 1 + } else if tr.Less(n.items[index], key) { + low = index + 1 + } else { + found = true + goto path_match + } + } + + // Do a binary search between low and high + // keep on going until low > high, where the guarantee on low is that + // key >= items[low - 1] + for low <= high { + mid := low + ((high+1)-low)/2 + // if key >= n.items[mid], low = mid + 1 + // which implies that key >= everything below low + if !tr.Less(key, n.items[mid]) { + low = mid + 1 + } else { + high = mid - 1 + } + } + + // if low > 0, n.items[low - 1] >= key, + // we have from before that key >= n.items[low - 1] + // therefore key = n.items[low - 1], + // and we have found the entry for key. + // Otherwise we must keep searching for the key in index `low`. + if low > 0 && !tr.Less(n.items[low-1], key) { + index = low - 1 + found = true + } else { + index = low + found = false + } + +path_match: + if depth < 8 { + hint.used[depth] = true + var pathIndex uint8 + if n.leaf() && found { + pathIndex = uint8(index + 1) + } else { + pathIndex = uint8(index) + } + if pathIndex != hint.path[depth] { + hint.path[depth] = pathIndex + for i := depth + 1; i < 8; i++ { + hint.used[i] = false + } + } + } + return index, found +} + +// SetHint sets or replace a value for a key using a path hint +func (tr *BTreeG[T]) SetHint(item T, hint *PathHint) (prev T, replaced bool) { + if tr.locks { + tr.mu.Lock() + prev, replaced = tr.setHint(item, hint) + tr.mu.Unlock() + } else { + prev, replaced = tr.setHint(item, hint) + } + return prev, replaced +} + +func (tr *BTreeG[T]) setHint(item T, hint *PathHint) (prev T, replaced bool) { + if tr.root == nil { + tr.init(0) + tr.root = tr.newNode(true) + tr.root.items = append([]T{}, item) + tr.root.count = 1 + tr.count = 1 + return tr.empty, false + } + prev, replaced, split := tr.nodeSet(&tr.root, item, hint, 0) + if split { + left := tr.isoLoad(&tr.root, true) + right, median := tr.nodeSplit(left) + tr.root = tr.newNode(false) + *tr.root.children = make([]*node[T], 0, tr.max+1) + *tr.root.children = append([]*node[T]{}, left, right) + tr.root.items = append([]T{}, median) + tr.root.updateCount() + return tr.setHint(item, hint) + } + if replaced { + return prev, true + } + tr.count++ + return tr.empty, false +} + +// Set or replace a value for a key +func (tr *BTreeG[T]) Set(item T) (T, bool) { + return tr.SetHint(item, nil) +} + +func (tr *BTreeG[T]) nodeSplit(n *node[T]) (right *node[T], median T) { + i := tr.max / 2 + median = n.items[i] + + // right node + right = tr.newNode(n.leaf()) + right.items = n.items[i+1:] + if !n.leaf() { + *right.children = (*n.children)[i+1:] + } + right.updateCount() + + // left node + n.items[i] = tr.empty + n.items = n.items[:i:i] + if !n.leaf() { + *n.children = (*n.children)[: i+1 : i+1] + } + n.updateCount() + + return right, median +} + +func (n *node[T]) updateCount() { + n.count = len(n.items) + if !n.leaf() { + for i := 0; i < len(*n.children); i++ { + n.count += (*n.children)[i].count + } + } +} + +// Copy the node for safe isolation. +func (tr *BTreeG[T]) copy(n *node[T]) *node[T] { + n2 := new(node[T]) + n2.isoid = tr.isoid + n2.count = n.count + n2.items = make([]T, len(n.items), cap(n.items)) + copy(n2.items, n.items) + if tr.copyItems { + for i := 0; i < len(n2.items); i++ { + n2.items[i] = ((interface{})(n2.items[i])).(copier[T]).Copy() + } + } else if tr.isoCopyItems { + for i := 0; i < len(n2.items); i++ { + n2.items[i] = ((interface{})(n2.items[i])).(isoCopier[T]).IsoCopy() + } + } + if !n.leaf() { + n2.children = new([]*node[T]) + *n2.children = make([]*node[T], len(*n.children), tr.max+1) + copy(*n2.children, *n.children) + } + return n2 +} + +// isoLoad loads the provided node and, if needed, performs a copy-on-write. +func (tr *BTreeG[T]) isoLoad(cn **node[T], mut bool) *node[T] { + if mut && (*cn).isoid != tr.isoid { + *cn = tr.copy(*cn) + } + return *cn +} + +func (tr *BTreeG[T]) nodeSet(cn **node[T], item T, + hint *PathHint, depth int, +) (prev T, replaced bool, split bool) { + if (*cn).isoid != tr.isoid { + *cn = tr.copy(*cn) + } + n := *cn + var i int + var found bool + if hint == nil { + i, found = tr.bsearch(n, item) + } else { + i, found = tr.hintsearch(n, item, hint, depth) + } + if found { + prev = n.items[i] + n.items[i] = item + return prev, true, false + } + if n.leaf() { + if len(n.items) == tr.max { + return tr.empty, false, true + } + n.items = append(n.items, tr.empty) + copy(n.items[i+1:], n.items[i:]) + n.items[i] = item + n.count++ + return tr.empty, false, false + } + prev, replaced, split = tr.nodeSet(&(*n.children)[i], item, hint, depth+1) + if split { + if len(n.items) == tr.max { + return tr.empty, false, true + } + right, median := tr.nodeSplit((*n.children)[i]) + *n.children = append(*n.children, nil) + copy((*n.children)[i+1:], (*n.children)[i:]) + (*n.children)[i+1] = right + n.items = append(n.items, tr.empty) + copy(n.items[i+1:], n.items[i:]) + n.items[i] = median + return tr.nodeSet(&n, item, hint, depth) + } + if !replaced { + n.count++ + } + return prev, replaced, false +} + +func (tr *BTreeG[T]) Scan(iter func(item T) bool) { + tr.scan(iter, false) +} +func (tr *BTreeG[T]) ScanMut(iter func(item T) bool) { + tr.scan(iter, true) +} + +func (tr *BTreeG[T]) scan(iter func(item T) bool, mut bool) { + if tr.lock(mut) { + defer tr.unlock(mut) + } + if tr.root == nil { + return + } + tr.nodeScan(&tr.root, iter, mut) +} + +func (tr *BTreeG[T]) nodeScan(cn **node[T], iter func(item T) bool, mut bool, +) bool { + n := tr.isoLoad(cn, mut) + if n.leaf() { + for i := 0; i < len(n.items); i++ { + if !iter(n.items[i]) { + return false + } + } + return true + } + for i := 0; i < len(n.items); i++ { + if !tr.nodeScan(&(*n.children)[i], iter, mut) { + return false + } + if !iter(n.items[i]) { + return false + } + } + return tr.nodeScan(&(*n.children)[len(*n.children)-1], iter, mut) +} + +// Get a value for key +func (tr *BTreeG[T]) Get(key T) (T, bool) { + return tr.getHint(key, nil, false) +} + +func (tr *BTreeG[T]) GetMut(key T) (T, bool) { + return tr.getHint(key, nil, true) +} + +// GetHint gets a value for key using a path hint +func (tr *BTreeG[T]) GetHint(key T, hint *PathHint) (value T, ok bool) { + return tr.getHint(key, hint, false) +} +func (tr *BTreeG[T]) GetHintMut(key T, hint *PathHint) (value T, ok bool) { + return tr.getHint(key, hint, true) +} + +// GetHint gets a value for key using a path hint +func (tr *BTreeG[T]) getHint(key T, hint *PathHint, mut bool) (T, bool) { + if tr.lock(mut) { + defer tr.unlock(mut) + } + if tr.root == nil { + return tr.empty, false + } + n := tr.isoLoad(&tr.root, mut) + depth := 0 + for { + i, found := tr.find(n, key, hint, depth) + if found { + return n.items[i], true + } + if n.children == nil { + return tr.empty, false + } + n = tr.isoLoad(&(*n.children)[i], mut) + depth++ + } +} + +// Len returns the number of items in the tree +func (tr *BTreeG[T]) Len() int { + return tr.count +} + +// Delete a value for a key and returns the deleted value. +// Returns false if there was no value by that key found. +func (tr *BTreeG[T]) Delete(key T) (T, bool) { + return tr.DeleteHint(key, nil) +} + +// DeleteHint deletes a value for a key using a path hint and returns the +// deleted value. +// Returns false if there was no value by that key found. +func (tr *BTreeG[T]) DeleteHint(key T, hint *PathHint) (T, bool) { + if tr.lock(true) { + defer tr.unlock(true) + } + return tr.deleteHint(key, hint) +} + +func (tr *BTreeG[T]) deleteHint(key T, hint *PathHint) (T, bool) { + if tr.root == nil { + return tr.empty, false + } + prev, deleted := tr.delete(&tr.root, false, key, hint, 0) + if !deleted { + return tr.empty, false + } + if len(tr.root.items) == 0 && !tr.root.leaf() { + tr.root = (*tr.root.children)[0] + } + tr.count-- + if tr.count == 0 { + tr.root = nil + } + return prev, true +} + +func (tr *BTreeG[T]) delete(cn **node[T], max bool, key T, + hint *PathHint, depth int, +) (T, bool) { + n := tr.isoLoad(cn, true) + var i int + var found bool + if max { + i, found = len(n.items)-1, true + } else { + i, found = tr.find(n, key, hint, depth) + } + if n.leaf() { + if found { + // found the items at the leaf, remove it and return. + prev := n.items[i] + copy(n.items[i:], n.items[i+1:]) + n.items[len(n.items)-1] = tr.empty + n.items = n.items[:len(n.items)-1] + n.count-- + return prev, true + } + return tr.empty, false + } + + var prev T + var deleted bool + if found { + if max { + i++ + prev, deleted = tr.delete(&(*n.children)[i], true, tr.empty, nil, 0) + } else { + prev = n.items[i] + maxItem, _ := tr.delete(&(*n.children)[i], true, tr.empty, nil, 0) + deleted = true + n.items[i] = maxItem + } + } else { + prev, deleted = tr.delete(&(*n.children)[i], max, key, hint, depth+1) + } + if !deleted { + return tr.empty, false + } + n.count-- + if len((*n.children)[i].items) < tr.min { + tr.nodeRebalance(n, i) + } + return prev, true +} + +// nodeRebalance rebalances the child nodes following a delete operation. +// Provide the index of the child node with the number of items that fell +// below minItems. +func (tr *BTreeG[T]) nodeRebalance(n *node[T], i int) { + if i == len(n.items) { + i-- + } + + // ensure copy-on-write + left := tr.isoLoad(&(*n.children)[i], true) + right := tr.isoLoad(&(*n.children)[i+1], true) + + if len(left.items)+len(right.items) < tr.max { + // Merges the left and right children nodes together as a single node + // that includes (left,item,right), and places the contents into the + // existing left node. Delete the right node altogether and move the + // following items and child nodes to the left by one slot. + + // merge (left,item,right) + left.items = append(left.items, n.items[i]) + left.items = append(left.items, right.items...) + if !left.leaf() { + *left.children = append(*left.children, *right.children...) + } + left.count += right.count + 1 + + // move the items over one slot + copy(n.items[i:], n.items[i+1:]) + n.items[len(n.items)-1] = tr.empty + n.items = n.items[:len(n.items)-1] + + // move the children over one slot + copy((*n.children)[i+1:], (*n.children)[i+2:]) + (*n.children)[len(*n.children)-1] = nil + (*n.children) = (*n.children)[:len(*n.children)-1] + } else if len(left.items) > len(right.items) { + // move left -> right over one slot + + // Move the item of the parent node at index into the right-node first + // slot, and move the left-node last item into the previously moved + // parent item slot. + right.items = append(right.items, tr.empty) + copy(right.items[1:], right.items) + right.items[0] = n.items[i] + right.count++ + n.items[i] = left.items[len(left.items)-1] + left.items[len(left.items)-1] = tr.empty + left.items = left.items[:len(left.items)-1] + left.count-- + + if !left.leaf() { + // move the left-node last child into the right-node first slot + *right.children = append(*right.children, nil) + copy((*right.children)[1:], *right.children) + (*right.children)[0] = (*left.children)[len(*left.children)-1] + (*left.children)[len(*left.children)-1] = nil + (*left.children) = (*left.children)[:len(*left.children)-1] + left.count -= (*right.children)[0].count + right.count += (*right.children)[0].count + } + } else { + // move left <- right over one slot + + // Same as above but the other direction + left.items = append(left.items, n.items[i]) + left.count++ + n.items[i] = right.items[0] + copy(right.items, right.items[1:]) + right.items[len(right.items)-1] = tr.empty + right.items = right.items[:len(right.items)-1] + right.count-- + + if !left.leaf() { + *left.children = append(*left.children, (*right.children)[0]) + copy(*right.children, (*right.children)[1:]) + (*right.children)[len(*right.children)-1] = nil + *right.children = (*right.children)[:len(*right.children)-1] + left.count += (*left.children)[len(*left.children)-1].count + right.count -= (*left.children)[len(*left.children)-1].count + } + } +} + +// Ascend the tree within the range [pivot, last] +// Pass nil for pivot to scan all item in ascending order +// Return false to stop iterating +func (tr *BTreeG[T]) Ascend(pivot T, iter func(item T) bool) { + tr.ascend(pivot, iter, false, nil) +} +func (tr *BTreeG[T]) AscendMut(pivot T, iter func(item T) bool) { + tr.ascend(pivot, iter, true, nil) +} +func (tr *BTreeG[T]) ascend(pivot T, iter func(item T) bool, mut bool, + hint *PathHint, +) { + if tr.lock(mut) { + defer tr.unlock(mut) + } + if tr.root == nil { + return + } + tr.nodeAscend(&tr.root, pivot, hint, 0, iter, mut) +} +func (tr *BTreeG[T]) AscendHint(pivot T, iter func(item T) bool, hint *PathHint, +) { + tr.ascend(pivot, iter, false, hint) +} +func (tr *BTreeG[T]) AscendHintMut(pivot T, iter func(item T) bool, + hint *PathHint, +) { + tr.ascend(pivot, iter, true, hint) +} + +// The return value of this function determines whether we should keep iterating +// upon this functions return. +func (tr *BTreeG[T]) nodeAscend(cn **node[T], pivot T, hint *PathHint, + depth int, iter func(item T) bool, mut bool, +) bool { + n := tr.isoLoad(cn, mut) + i, found := tr.find(n, pivot, hint, depth) + if !found { + if !n.leaf() { + if !tr.nodeAscend(&(*n.children)[i], pivot, hint, depth+1, iter, + mut) { + return false + } + } + } + // We are either in the case that + // - node is found, we should iterate through it starting at `i`, + // the index it was located at. + // - node is not found, and TODO: fill in. + for ; i < len(n.items); i++ { + if !iter(n.items[i]) { + return false + } + if !n.leaf() { + if !tr.nodeScan(&(*n.children)[i+1], iter, mut) { + return false + } + } + } + return true +} + +func (tr *BTreeG[T]) Reverse(iter func(item T) bool) { + tr.reverse(iter, false) +} +func (tr *BTreeG[T]) ReverseMut(iter func(item T) bool) { + tr.reverse(iter, true) +} +func (tr *BTreeG[T]) reverse(iter func(item T) bool, mut bool) { + if tr.lock(mut) { + defer tr.unlock(mut) + } + if tr.root == nil { + return + } + tr.nodeReverse(&tr.root, iter, mut) +} + +func (tr *BTreeG[T]) nodeReverse(cn **node[T], iter func(item T) bool, mut bool, +) bool { + n := tr.isoLoad(cn, mut) + if n.leaf() { + for i := len(n.items) - 1; i >= 0; i-- { + if !iter(n.items[i]) { + return false + } + } + return true + } + if !tr.nodeReverse(&(*n.children)[len(*n.children)-1], iter, mut) { + return false + } + for i := len(n.items) - 1; i >= 0; i-- { + if !iter(n.items[i]) { + return false + } + if !tr.nodeReverse(&(*n.children)[i], iter, mut) { + return false + } + } + return true +} + +// Descend the tree within the range [pivot, first] +// Pass nil for pivot to scan all item in descending order +// Return false to stop iterating +func (tr *BTreeG[T]) Descend(pivot T, iter func(item T) bool) { + tr.descend(pivot, iter, false, nil) +} +func (tr *BTreeG[T]) DescendMut(pivot T, iter func(item T) bool) { + tr.descend(pivot, iter, true, nil) +} +func (tr *BTreeG[T]) descend(pivot T, iter func(item T) bool, mut bool, + hint *PathHint, +) { + if tr.lock(mut) { + defer tr.unlock(mut) + } + if tr.root == nil { + return + } + tr.nodeDescend(&tr.root, pivot, hint, 0, iter, mut) +} + +func (tr *BTreeG[T]) DescendHint(pivot T, iter func(item T) bool, + hint *PathHint, +) { + tr.descend(pivot, iter, false, hint) +} +func (tr *BTreeG[T]) DescendHintMut(pivot T, iter func(item T) bool, + hint *PathHint, +) { + tr.descend(pivot, iter, true, hint) +} + +func (tr *BTreeG[T]) nodeDescend(cn **node[T], pivot T, hint *PathHint, + depth int, iter func(item T) bool, mut bool, +) bool { + n := tr.isoLoad(cn, mut) + i, found := tr.find(n, pivot, hint, depth) + if !found { + if !n.leaf() { + if !tr.nodeDescend(&(*n.children)[i], pivot, hint, depth+1, iter, + mut) { + return false + } + } + i-- + } + for ; i >= 0; i-- { + if !iter(n.items[i]) { + return false + } + if !n.leaf() { + if !tr.nodeReverse(&(*n.children)[i], iter, mut) { + return false + } + } + } + return true +} + +// Load is for bulk loading pre-sorted items +func (tr *BTreeG[T]) Load(item T) (T, bool) { + if tr.lock(true) { + defer tr.unlock(true) + } + if tr.root == nil { + return tr.setHint(item, nil) + } + n := tr.isoLoad(&tr.root, true) + for { + n.count++ // optimistically update counts + if n.leaf() { + if len(n.items) < tr.max { + if tr.Less(n.items[len(n.items)-1], item) { + n.items = append(n.items, item) + tr.count++ + return tr.empty, false + } + } + break + } + n = tr.isoLoad(&(*n.children)[len(*n.children)-1], true) + } + // revert the counts + n = tr.root + for { + n.count-- + if n.leaf() { + break + } + n = (*n.children)[len(*n.children)-1] + } + return tr.setHint(item, nil) +} + +// Min returns the minimum item in tree. +// Returns nil if the treex has no items. +func (tr *BTreeG[T]) Min() (T, bool) { + return tr.minMut(false) +} + +func (tr *BTreeG[T]) MinMut() (T, bool) { + return tr.minMut(true) +} + +func (tr *BTreeG[T]) minMut(mut bool) (T, bool) { + if tr.lock(mut) { + defer tr.unlock(mut) + } + if tr.root == nil { + return tr.empty, false + } + n := tr.isoLoad(&tr.root, mut) + for { + if n.leaf() { + return n.items[0], true + } + n = tr.isoLoad(&(*n.children)[0], mut) + } +} + +// Max returns the maximum item in tree. +// Returns nil if the tree has no items. +func (tr *BTreeG[T]) Max() (T, bool) { + return tr.maxMut(false) +} + +func (tr *BTreeG[T]) MaxMut() (T, bool) { + return tr.maxMut(true) +} + +func (tr *BTreeG[T]) maxMut(mut bool) (T, bool) { + if tr.lock(mut) { + defer tr.unlock(mut) + } + if tr.root == nil { + return tr.empty, false + } + n := tr.isoLoad(&tr.root, mut) + for { + if n.leaf() { + return n.items[len(n.items)-1], true + } + n = tr.isoLoad(&(*n.children)[len(*n.children)-1], mut) + } +} + +// PopMin removes the minimum item in tree and returns it. +// Returns nil if the tree has no items. +func (tr *BTreeG[T]) PopMin() (T, bool) { + if tr.lock(true) { + defer tr.unlock(true) + } + if tr.root == nil { + return tr.empty, false + } + n := tr.isoLoad(&tr.root, true) + var item T + for { + n.count-- // optimistically update counts + if n.leaf() { + item = n.items[0] + if len(n.items) == tr.min { + break + } + copy(n.items[:], n.items[1:]) + n.items[len(n.items)-1] = tr.empty + n.items = n.items[:len(n.items)-1] + tr.count-- + if tr.count == 0 { + tr.root = nil + } + return item, true + } + n = tr.isoLoad(&(*n.children)[0], true) + } + // revert the counts + n = tr.root + for { + n.count++ + if n.leaf() { + break + } + n = (*n.children)[0] + } + return tr.deleteHint(item, nil) +} + +// PopMax removes the maximum item in tree and returns it. +// Returns nil if the tree has no items. +func (tr *BTreeG[T]) PopMax() (T, bool) { + if tr.lock(true) { + defer tr.unlock(true) + } + if tr.root == nil { + return tr.empty, false + } + n := tr.isoLoad(&tr.root, true) + var item T + for { + n.count-- // optimistically update counts + if n.leaf() { + item = n.items[len(n.items)-1] + if len(n.items) == tr.min { + break + } + n.items[len(n.items)-1] = tr.empty + n.items = n.items[:len(n.items)-1] + tr.count-- + if tr.count == 0 { + tr.root = nil + } + return item, true + } + n = tr.isoLoad(&(*n.children)[len(*n.children)-1], true) + } + // revert the counts + n = tr.root + for { + n.count++ + if n.leaf() { + break + } + n = (*n.children)[len(*n.children)-1] + } + return tr.deleteHint(item, nil) +} + +// GetAt returns the value at index. +// Return nil if the tree is empty or the index is out of bounds. +func (tr *BTreeG[T]) GetAt(index int) (T, bool) { + return tr.getAt(index, false) +} +func (tr *BTreeG[T]) GetAtMut(index int) (T, bool) { + return tr.getAt(index, true) +} +func (tr *BTreeG[T]) getAt(index int, mut bool) (T, bool) { + if tr.lock(mut) { + defer tr.unlock(mut) + } + if tr.root == nil || index < 0 || index >= tr.count { + return tr.empty, false + } + n := tr.isoLoad(&tr.root, mut) + for { + if n.leaf() { + return n.items[index], true + } + i := 0 + for ; i < len(n.items); i++ { + if index < (*n.children)[i].count { + break + } else if index == (*n.children)[i].count { + return n.items[i], true + } + index -= (*n.children)[i].count + 1 + } + n = tr.isoLoad(&(*n.children)[i], mut) + } +} + +// DeleteAt deletes the item at index. +// Return nil if the tree is empty or the index is out of bounds. +func (tr *BTreeG[T]) DeleteAt(index int) (T, bool) { + if tr.lock(true) { + defer tr.unlock(true) + } + if tr.root == nil || index < 0 || index >= tr.count { + return tr.empty, false + } + var pathbuf [8]uint8 // track the path + path := pathbuf[:0] + var item T + n := tr.isoLoad(&tr.root, true) +outer: + for { + n.count-- // optimistically update counts + if n.leaf() { + // the index is the item position + item = n.items[index] + if len(n.items) == tr.min { + path = append(path, uint8(index)) + break outer + } + copy(n.items[index:], n.items[index+1:]) + n.items[len(n.items)-1] = tr.empty + n.items = n.items[:len(n.items)-1] + tr.count-- + if tr.count == 0 { + tr.root = nil + } + return item, true + } + i := 0 + for ; i < len(n.items); i++ { + if index < (*n.children)[i].count { + break + } else if index == (*n.children)[i].count { + item = n.items[i] + path = append(path, uint8(i)) + break outer + } + index -= (*n.children)[i].count + 1 + } + path = append(path, uint8(i)) + n = tr.isoLoad(&(*n.children)[i], true) + } + // revert the counts + var hint PathHint + n = tr.root + for i := 0; i < len(path); i++ { + if i < len(hint.path) { + hint.path[i] = uint8(path[i]) + hint.used[i] = true + } + n.count++ + if !n.leaf() { + n = (*n.children)[uint8(path[i])] + } + } + return tr.deleteHint(item, &hint) +} + +// Height returns the height of the tree. +// Returns zero if tree has no items. +func (tr *BTreeG[T]) Height() int { + if tr.lock(false) { + defer tr.unlock(false) + } + var height int + if tr.root != nil { + n := tr.root + for { + height++ + if n.leaf() { + break + } + n = (*n.children)[0] + } + } + return height +} + +// Walk iterates over all items in tree, in order. +// The items param will contain one or more items. +func (tr *BTreeG[T]) Walk(iter func(item []T) bool) { + tr.walk(iter, false) +} +func (tr *BTreeG[T]) WalkMut(iter func(item []T) bool) { + tr.walk(iter, true) +} +func (tr *BTreeG[T]) walk(iter func(item []T) bool, mut bool) { + if tr.lock(mut) { + defer tr.unlock(mut) + } + if tr.root == nil { + return + } + tr.nodeWalk(&tr.root, iter, mut) +} + +func (tr *BTreeG[T]) nodeWalk(cn **node[T], iter func(item []T) bool, mut bool, +) bool { + n := tr.isoLoad(cn, mut) + if n.leaf() { + if !iter(n.items) { + return false + } + } else { + for i := 0; i < len(n.items); i++ { + if !tr.nodeWalk(&(*n.children)[i], iter, mut) { + return false + } + if !iter(n.items[i : i+1]) { + return false + } + } + if !tr.nodeWalk(&(*n.children)[len(n.items)], iter, mut) { + return false + } + } + return true +} + +// Copy the tree. This is a copy-on-write operation and is very fast because +// it only performs a shadowed copy. +func (tr *BTreeG[T]) Copy() *BTreeG[T] { + return tr.IsoCopy() +} + +func (tr *BTreeG[T]) IsoCopy() *BTreeG[T] { + if tr.lock(true) { + defer tr.unlock(true) + } + tr.isoid = newIsoID() + tr2 := new(BTreeG[T]) + *tr2 = *tr + tr2.mu = new(sync.RWMutex) + tr2.isoid = newIsoID() + return tr2 +} + +func (tr *BTreeG[T]) lock(write bool) bool { + if tr.locks { + if write { + tr.mu.Lock() + } else { + tr.mu.RLock() + } + } + return tr.locks +} + +func (tr *BTreeG[T]) unlock(write bool) { + if write { + tr.mu.Unlock() + } else { + tr.mu.RUnlock() + } +} + +// Iter represents an iterator +type IterG[T any] struct { + tr *BTreeG[T] + mut bool + locked bool + seeked bool + atstart bool + atend bool + stack0 [4]iterStackItemG[T] + stack []iterStackItemG[T] + item T +} + +type iterStackItemG[T any] struct { + n *node[T] + i int +} + +// Iter returns a read-only iterator. +// The Release method must be called finished with iterator. +func (tr *BTreeG[T]) Iter() IterG[T] { + return tr.iter(false) +} + +func (tr *BTreeG[T]) IterMut() IterG[T] { + return tr.iter(true) +} + +func (tr *BTreeG[T]) iter(mut bool) IterG[T] { + var iter IterG[T] + iter.tr = tr + iter.mut = mut + iter.locked = tr.lock(iter.mut) + iter.stack = iter.stack0[:0] + return iter +} + +// Seek to item greater-or-equal-to key. +// Returns false if there was no item found. +func (iter *IterG[T]) Seek(key T) bool { + return iter.seek(key, nil) +} + +func (iter *IterG[T]) SeekHint(key T, hint *PathHint) bool { + return iter.seek(key, hint) +} + +func (iter *IterG[T]) seek(key T, hint *PathHint) bool { + if iter.tr == nil { + return false + } + iter.seeked = true + iter.stack = iter.stack[:0] + if iter.tr.root == nil { + return false + } + n := iter.tr.isoLoad(&iter.tr.root, iter.mut) + var depth int + for { + i, found := iter.tr.find(n, key, hint, depth) + iter.stack = append(iter.stack, iterStackItemG[T]{n, i}) + if found { + iter.item = n.items[i] + return true + } + if n.leaf() { + iter.stack[len(iter.stack)-1].i-- + return iter.Next() + } + n = iter.tr.isoLoad(&(*n.children)[i], iter.mut) + depth++ + } +} + +// First moves iterator to first item in tree. +// Returns false if the tree is empty. +func (iter *IterG[T]) First() bool { + if iter.tr == nil { + return false + } + iter.atend = false + iter.atstart = false + iter.seeked = true + iter.stack = iter.stack[:0] + if iter.tr.root == nil { + return false + } + n := iter.tr.isoLoad(&iter.tr.root, iter.mut) + for { + iter.stack = append(iter.stack, iterStackItemG[T]{n, 0}) + if n.leaf() { + break + } + n = iter.tr.isoLoad(&(*n.children)[0], iter.mut) + } + s := &iter.stack[len(iter.stack)-1] + iter.item = s.n.items[s.i] + return true +} + +// Last moves iterator to last item in tree. +// Returns false if the tree is empty. +func (iter *IterG[T]) Last() bool { + if iter.tr == nil { + return false + } + iter.seeked = true + iter.stack = iter.stack[:0] + if iter.tr.root == nil { + return false + } + n := iter.tr.isoLoad(&iter.tr.root, iter.mut) + for { + iter.stack = append(iter.stack, iterStackItemG[T]{n, len(n.items)}) + if n.leaf() { + iter.stack[len(iter.stack)-1].i-- + break + } + n = iter.tr.isoLoad(&(*n.children)[len(n.items)], iter.mut) + } + s := &iter.stack[len(iter.stack)-1] + iter.item = s.n.items[s.i] + return true +} + +// Release the iterator. +func (iter *IterG[T]) Release() { + if iter.tr == nil { + return + } + if iter.locked { + iter.tr.unlock(iter.mut) + iter.locked = false + } + iter.stack = nil + iter.tr = nil +} + +// Next moves iterator to the next item in iterator. +// Returns false if the tree is empty or the iterator is at the end of +// the tree. +func (iter *IterG[T]) Next() bool { + if iter.tr == nil { + return false + } + if !iter.seeked { + return iter.First() + } + if len(iter.stack) == 0 { + if iter.atstart { + return iter.First() && iter.Next() + } + return false + } + s := &iter.stack[len(iter.stack)-1] + s.i++ + if s.n.leaf() { + if s.i == len(s.n.items) { + for { + iter.stack = iter.stack[:len(iter.stack)-1] + if len(iter.stack) == 0 { + iter.atend = true + return false + } + s = &iter.stack[len(iter.stack)-1] + if s.i < len(s.n.items) { + break + } + } + } + } else { + n := iter.tr.isoLoad(&(*s.n.children)[s.i], iter.mut) + for { + iter.stack = append(iter.stack, iterStackItemG[T]{n, 0}) + if n.leaf() { + break + } + n = iter.tr.isoLoad(&(*n.children)[0], iter.mut) + } + } + s = &iter.stack[len(iter.stack)-1] + iter.item = s.n.items[s.i] + return true +} + +// Prev moves iterator to the previous item in iterator. +// Returns false if the tree is empty or the iterator is at the beginning of +// the tree. +func (iter *IterG[T]) Prev() bool { + if iter.tr == nil { + return false + } + if !iter.seeked { + return false + } + if len(iter.stack) == 0 { + if iter.atend { + return iter.Last() && iter.Prev() + } + return false + } + s := &iter.stack[len(iter.stack)-1] + if s.n.leaf() { + s.i-- + if s.i == -1 { + for { + iter.stack = iter.stack[:len(iter.stack)-1] + if len(iter.stack) == 0 { + iter.atstart = true + return false + } + s = &iter.stack[len(iter.stack)-1] + s.i-- + if s.i > -1 { + break + } + } + } + } else { + n := iter.tr.isoLoad(&(*s.n.children)[s.i], iter.mut) + for { + iter.stack = append(iter.stack, iterStackItemG[T]{n, len(n.items)}) + if n.leaf() { + iter.stack[len(iter.stack)-1].i-- + break + } + n = iter.tr.isoLoad(&(*n.children)[len(n.items)], iter.mut) + } + } + s = &iter.stack[len(iter.stack)-1] + iter.item = s.n.items[s.i] + return true +} + +// Item returns the current iterator item. +func (iter *IterG[T]) Item() T { + return iter.item +} + +// Items returns all the items in order. +func (tr *BTreeG[T]) Items() []T { + return tr.items(false) +} + +func (tr *BTreeG[T]) ItemsMut() []T { + return tr.items(true) +} + +func (tr *BTreeG[T]) items(mut bool) []T { + if tr.lock(mut) { + defer tr.unlock(mut) + } + items := make([]T, 0, tr.Len()) + if tr.root != nil { + items = tr.nodeItems(&tr.root, items, mut) + } + return items +} + +func (tr *BTreeG[T]) nodeItems(cn **node[T], items []T, mut bool) []T { + n := tr.isoLoad(cn, mut) + if n.leaf() { + return append(items, n.items...) + } + for i := 0; i < len(n.items); i++ { + items = tr.nodeItems(&(*n.children)[i], items, mut) + items = append(items, n.items[i]) + } + return tr.nodeItems(&(*n.children)[len(*n.children)-1], items, mut) +} + +// Clear will delete all items. +func (tr *BTreeG[T]) Clear() { + if tr.lock(true) { + defer tr.unlock(true) + } + tr.root = nil + tr.count = 0 +} + +// Generic BTree +// +// Deprecated: use BTreeG +type Generic[T any] struct { + *BTreeG[T] +} + +// NewGeneric returns a generic BTree +// +// Deprecated: use NewBTreeG +func NewGeneric[T any](less func(a, b T) bool) *Generic[T] { + return &Generic[T]{NewBTreeGOptions(less, Options{})} +} + +// NewGenericOptions returns a generic BTree +// +// Deprecated: use NewBTreeGOptions +func NewGenericOptions[T any](less func(a, b T) bool, opts Options, +) *Generic[T] { + return &Generic[T]{NewBTreeGOptions(less, opts)} +} + +func (tr *Generic[T]) Copy() *Generic[T] { + return &Generic[T]{tr.BTreeG.Copy()} +} diff --git a/vendor/github.com/tidwall/btree/map.go b/vendor/github.com/tidwall/btree/map.go new file mode 100644 index 0000000000..a4d7c04ccc --- /dev/null +++ b/vendor/github.com/tidwall/btree/map.go @@ -0,0 +1,1212 @@ +// Copyright 2020 Joshua J Baker. All rights reserved. +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. +package btree + +import "sync/atomic" + +type ordered interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | ~string +} + +type copier[T any] interface { + Copy() T +} + +type isoCopier[T any] interface { + IsoCopy() T +} + +func degreeToMinMax(deg int) (min, max int) { + if deg <= 0 { + deg = 32 + } else if deg == 1 { + deg = 2 // must have at least 2 + } + max = deg*2 - 1 // max items per node. max children is +1 + min = max / 2 + return min, max +} + +var gisoid uint64 + +func newIsoID() uint64 { + return atomic.AddUint64(&gisoid, 1) +} + +type mapPair[K ordered, V any] struct { + // The `value` field should be before the `key` field because doing so + // allows for the Go compiler to optimize away the `value` field when + // it's a `struct{}`, which is the case for `btree.Set`. + value V + key K +} + +type Map[K ordered, V any] struct { + isoid uint64 + root *mapNode[K, V] + count int + empty mapPair[K, V] + min int // min items + max int // max items + copyValues bool + isoCopyValues bool +} + +func NewMap[K ordered, V any](degree int) *Map[K, V] { + m := new(Map[K, V]) + m.init(degree) + return m +} + +type mapNode[K ordered, V any] struct { + isoid uint64 + count int + items []mapPair[K, V] + children *[]*mapNode[K, V] +} + +// Copy the node for safe isolation. +func (tr *Map[K, V]) copy(n *mapNode[K, V]) *mapNode[K, V] { + n2 := new(mapNode[K, V]) + n2.isoid = tr.isoid + n2.count = n.count + n2.items = make([]mapPair[K, V], len(n.items), cap(n.items)) + copy(n2.items, n.items) + if tr.copyValues { + for i := 0; i < len(n2.items); i++ { + n2.items[i].value = + ((interface{})(n2.items[i].value)).(copier[V]).Copy() + } + } else if tr.isoCopyValues { + for i := 0; i < len(n2.items); i++ { + n2.items[i].value = + ((interface{})(n2.items[i].value)).(isoCopier[V]).IsoCopy() + } + } + if !n.leaf() { + n2.children = new([]*mapNode[K, V]) + *n2.children = make([]*mapNode[K, V], len(*n.children), tr.max+1) + copy(*n2.children, *n.children) + } + return n2 +} + +// isoLoad loads the provided node and, if needed, performs a copy-on-write. +func (tr *Map[K, V]) isoLoad(cn **mapNode[K, V], mut bool) *mapNode[K, V] { + if mut && (*cn).isoid != tr.isoid { + *cn = tr.copy(*cn) + } + return *cn +} + +func (tr *Map[K, V]) Copy() *Map[K, V] { + return tr.IsoCopy() +} + +func (tr *Map[K, V]) IsoCopy() *Map[K, V] { + tr2 := new(Map[K, V]) + *tr2 = *tr + tr2.isoid = newIsoID() + tr.isoid = newIsoID() + return tr2 +} + +func (tr *Map[K, V]) newNode(leaf bool) *mapNode[K, V] { + n := new(mapNode[K, V]) + n.isoid = tr.isoid + if !leaf { + n.children = new([]*mapNode[K, V]) + } + return n +} + +// leaf returns true if the node is a leaf. +func (n *mapNode[K, V]) leaf() bool { + return n.children == nil +} + +func (tr *Map[K, V]) search(n *mapNode[K, V], key K) (index int, found bool) { + low, high := 0, len(n.items) + for low < high { + h := (low + high) / 2 + if !(key < n.items[h].key) { + low = h + 1 + } else { + high = h + } + } + if low > 0 && !(n.items[low-1].key < key) { + return low - 1, true + } + return low, false +} + +func (tr *Map[K, V]) init(degree int) { + if tr.min != 0 { + return + } + tr.min, tr.max = degreeToMinMax(degree) + _, tr.copyValues = ((interface{})(tr.empty.value)).(copier[V]) + if !tr.copyValues { + _, tr.isoCopyValues = ((interface{})(tr.empty.value)).(isoCopier[V]) + } +} + +// Set or replace a value for a key +func (tr *Map[K, V]) Set(key K, value V) (V, bool) { + item := mapPair[K, V]{key: key, value: value} + if tr.root == nil { + tr.init(0) + tr.root = tr.newNode(true) + tr.root.items = append([]mapPair[K, V]{}, item) + tr.root.count = 1 + tr.count = 1 + return tr.empty.value, false + } + prev, replaced, split := tr.nodeSet(&tr.root, item) + if split { + left := tr.root + right, median := tr.nodeSplit(left) + tr.root = tr.newNode(false) + *tr.root.children = make([]*mapNode[K, V], 0, tr.max+1) + *tr.root.children = append([]*mapNode[K, V]{}, left, right) + tr.root.items = append([]mapPair[K, V]{}, median) + tr.root.updateCount() + return tr.Set(item.key, item.value) + } + if replaced { + return prev, true + } + tr.count++ + return tr.empty.value, false +} + +func (tr *Map[K, V]) nodeSplit(n *mapNode[K, V], +) (right *mapNode[K, V], median mapPair[K, V]) { + i := tr.max / 2 + median = n.items[i] + + // right node + right = tr.newNode(n.leaf()) + right.items = n.items[i+1:] + if !n.leaf() { + *right.children = (*n.children)[i+1:] + } + right.updateCount() + + // left node + n.items[i] = tr.empty + n.items = n.items[:i:i] + if !n.leaf() { + *n.children = (*n.children)[: i+1 : i+1] + } + n.updateCount() + return right, median +} + +func (n *mapNode[K, V]) updateCount() { + n.count = len(n.items) + if !n.leaf() { + for i := 0; i < len(*n.children); i++ { + n.count += (*n.children)[i].count + } + } +} + +func (tr *Map[K, V]) nodeSet(pn **mapNode[K, V], item mapPair[K, V], +) (prev V, replaced bool, split bool) { + n := tr.isoLoad(pn, true) + i, found := tr.search(n, item.key) + if found { + prev = n.items[i].value + n.items[i] = item + return prev, true, false + } + if n.leaf() { + if len(n.items) == tr.max { + return tr.empty.value, false, true + } + n.items = append(n.items, tr.empty) + copy(n.items[i+1:], n.items[i:]) + n.items[i] = item + n.count++ + return tr.empty.value, false, false + } + prev, replaced, split = tr.nodeSet(&(*n.children)[i], item) + if split { + if len(n.items) == tr.max { + return tr.empty.value, false, true + } + right, median := tr.nodeSplit((*n.children)[i]) + *n.children = append(*n.children, nil) + copy((*n.children)[i+1:], (*n.children)[i:]) + (*n.children)[i+1] = right + n.items = append(n.items, tr.empty) + copy(n.items[i+1:], n.items[i:]) + n.items[i] = median + return tr.nodeSet(&n, item) + } + if !replaced { + n.count++ + } + return prev, replaced, false +} + +func (tr *Map[K, V]) Scan(iter func(key K, value V) bool) { + tr.scan(iter, false) +} + +func (tr *Map[K, V]) ScanMut(iter func(key K, value V) bool) { + tr.scan(iter, true) +} + +func (tr *Map[K, V]) scan(iter func(key K, value V) bool, mut bool) { + if tr.root == nil { + return + } + tr.nodeScan(&tr.root, iter, mut) +} + +func (tr *Map[K, V]) nodeScan(cn **mapNode[K, V], + iter func(key K, value V) bool, mut bool, +) bool { + n := tr.isoLoad(cn, mut) + if n.leaf() { + for i := 0; i < len(n.items); i++ { + if !iter(n.items[i].key, n.items[i].value) { + return false + } + } + return true + } + for i := 0; i < len(n.items); i++ { + if !tr.nodeScan(&(*n.children)[i], iter, mut) { + return false + } + if !iter(n.items[i].key, n.items[i].value) { + return false + } + } + return tr.nodeScan(&(*n.children)[len(*n.children)-1], iter, mut) +} + +// Get a value for key. +func (tr *Map[K, V]) Get(key K) (V, bool) { + return tr.get(key, false) +} + +// GetMut gets a value for key. +// If needed, this may perform a copy the resulting value before returning. +// +// Mut methods are only useful when all of the following are true: +// - The interior data of the value requires changes. +// - The value is a pointer type. +// - The BTree has been copied using `Copy()` or `IsoCopy()`. +// - The value itself has a `Copy()` or `IsoCopy()` method. +// +// Mut methods may modify the tree structure and should have the same +// considerations as other mutable operations like Set, Delete, Clear, etc. +func (tr *Map[K, V]) GetMut(key K) (V, bool) { + return tr.get(key, true) +} + +func (tr *Map[K, V]) get(key K, mut bool) (V, bool) { + if tr.root == nil { + return tr.empty.value, false + } + n := tr.isoLoad(&tr.root, mut) + for { + i, found := tr.search(n, key) + if found { + return n.items[i].value, true + } + if n.leaf() { + return tr.empty.value, false + } + n = tr.isoLoad(&(*n.children)[i], mut) + } +} + +// Len returns the number of items in the tree +func (tr *Map[K, V]) Len() int { + return tr.count +} + +// Delete a value for a key and returns the deleted value. +// Returns false if there was no value by that key found. +func (tr *Map[K, V]) Delete(key K) (V, bool) { + if tr.root == nil { + return tr.empty.value, false + } + prev, deleted := tr.delete(&tr.root, false, key) + if !deleted { + return tr.empty.value, false + } + if len(tr.root.items) == 0 && !tr.root.leaf() { + tr.root = (*tr.root.children)[0] + } + tr.count-- + if tr.count == 0 { + tr.root = nil + } + return prev.value, true +} + +func (tr *Map[K, V]) delete(pn **mapNode[K, V], max bool, key K, +) (mapPair[K, V], bool) { + n := tr.isoLoad(pn, true) + var i int + var found bool + if max { + i, found = len(n.items)-1, true + } else { + i, found = tr.search(n, key) + } + if n.leaf() { + if found { + // found the items at the leaf, remove it and return. + prev := n.items[i] + copy(n.items[i:], n.items[i+1:]) + n.items[len(n.items)-1] = tr.empty + n.items = n.items[:len(n.items)-1] + n.count-- + return prev, true + } + return tr.empty, false + } + + var prev mapPair[K, V] + var deleted bool + if found { + if max { + i++ + prev, deleted = tr.delete(&(*n.children)[i], true, tr.empty.key) + } else { + prev = n.items[i] + maxItem, _ := tr.delete(&(*n.children)[i], true, tr.empty.key) + deleted = true + n.items[i] = maxItem + } + } else { + prev, deleted = tr.delete(&(*n.children)[i], max, key) + } + if !deleted { + return tr.empty, false + } + n.count-- + if len((*n.children)[i].items) < tr.min { + tr.nodeRebalance(n, i) + } + return prev, true +} + +// nodeRebalance rebalances the child nodes following a delete operation. +// Provide the index of the child node with the number of items that fell +// below minItems. +func (tr *Map[K, V]) nodeRebalance(n *mapNode[K, V], i int) { + if i == len(n.items) { + i-- + } + + // ensure copy-on-write + left := tr.isoLoad(&(*n.children)[i], true) + right := tr.isoLoad(&(*n.children)[i+1], true) + + if len(left.items)+len(right.items) < tr.max { + // Merges the left and right children nodes together as a single node + // that includes (left,item,right), and places the contents into the + // existing left node. Delete the right node altogether and move the + // following items and child nodes to the left by one slot. + + // merge (left,item,right) + left.items = append(left.items, n.items[i]) + left.items = append(left.items, right.items...) + if !left.leaf() { + *left.children = append(*left.children, *right.children...) + } + left.count += right.count + 1 + + // move the items over one slot + copy(n.items[i:], n.items[i+1:]) + n.items[len(n.items)-1] = tr.empty + n.items = n.items[:len(n.items)-1] + + // move the children over one slot + copy((*n.children)[i+1:], (*n.children)[i+2:]) + (*n.children)[len(*n.children)-1] = nil + (*n.children) = (*n.children)[:len(*n.children)-1] + } else if len(left.items) > len(right.items) { + // move left -> right over one slot + + // Move the item of the parent node at index into the right-node first + // slot, and move the left-node last item into the previously moved + // parent item slot. + right.items = append(right.items, tr.empty) + copy(right.items[1:], right.items) + right.items[0] = n.items[i] + right.count++ + n.items[i] = left.items[len(left.items)-1] + left.items[len(left.items)-1] = tr.empty + left.items = left.items[:len(left.items)-1] + left.count-- + + if !left.leaf() { + // move the left-node last child into the right-node first slot + *right.children = append(*right.children, nil) + copy((*right.children)[1:], *right.children) + (*right.children)[0] = (*left.children)[len(*left.children)-1] + (*left.children)[len(*left.children)-1] = nil + (*left.children) = (*left.children)[:len(*left.children)-1] + left.count -= (*right.children)[0].count + right.count += (*right.children)[0].count + } + } else { + // move left <- right over one slot + + // Same as above but the other direction + left.items = append(left.items, n.items[i]) + left.count++ + n.items[i] = right.items[0] + copy(right.items, right.items[1:]) + right.items[len(right.items)-1] = tr.empty + right.items = right.items[:len(right.items)-1] + right.count-- + + if !left.leaf() { + *left.children = append(*left.children, (*right.children)[0]) + copy(*right.children, (*right.children)[1:]) + (*right.children)[len(*right.children)-1] = nil + *right.children = (*right.children)[:len(*right.children)-1] + left.count += (*left.children)[len(*left.children)-1].count + right.count -= (*left.children)[len(*left.children)-1].count + } + } +} + +// Ascend the tree within the range [pivot, last] +// Pass nil for pivot to scan all item in ascending order +// Return false to stop iterating +func (tr *Map[K, V]) Ascend(pivot K, iter func(key K, value V) bool) { + tr.ascend(pivot, iter, false) +} + +func (tr *Map[K, V]) AscendMut(pivot K, iter func(key K, value V) bool) { + tr.ascend(pivot, iter, true) +} + +func (tr *Map[K, V]) ascend(pivot K, iter func(key K, value V) bool, mut bool) { + if tr.root == nil { + return + } + tr.nodeAscend(&tr.root, pivot, iter, mut) +} + +// The return value of this function determines whether we should keep iterating +// upon this functions return. +func (tr *Map[K, V]) nodeAscend(cn **mapNode[K, V], pivot K, + iter func(key K, value V) bool, mut bool, +) bool { + n := tr.isoLoad(cn, mut) + i, found := tr.search(n, pivot) + if !found { + if !n.leaf() { + if !tr.nodeAscend(&(*n.children)[i], pivot, iter, mut) { + return false + } + } + } + // We are either in the case that + // - node is found, we should iterate through it starting at `i`, + // the index it was located at. + // - node is not found, and TODO: fill in. + for ; i < len(n.items); i++ { + if !iter(n.items[i].key, n.items[i].value) { + return false + } + if !n.leaf() { + if !tr.nodeScan(&(*n.children)[i+1], iter, mut) { + return false + } + } + } + return true +} + +func (tr *Map[K, V]) Reverse(iter func(key K, value V) bool) { + tr.reverse(iter, false) +} + +func (tr *Map[K, V]) ReverseMut(iter func(key K, value V) bool) { + tr.reverse(iter, true) +} + +func (tr *Map[K, V]) reverse(iter func(key K, value V) bool, mut bool) { + if tr.root == nil { + return + } + tr.nodeReverse(&tr.root, iter, mut) +} + +func (tr *Map[K, V]) nodeReverse(cn **mapNode[K, V], + iter func(key K, value V) bool, mut bool, +) bool { + n := tr.isoLoad(cn, mut) + if n.leaf() { + for i := len(n.items) - 1; i >= 0; i-- { + if !iter(n.items[i].key, n.items[i].value) { + return false + } + } + return true + } + if !tr.nodeReverse(&(*n.children)[len(*n.children)-1], iter, mut) { + return false + } + for i := len(n.items) - 1; i >= 0; i-- { + if !iter(n.items[i].key, n.items[i].value) { + return false + } + if !tr.nodeReverse(&(*n.children)[i], iter, mut) { + return false + } + } + return true +} + +// Descend the tree within the range [pivot, first] +// Pass nil for pivot to scan all item in descending order +// Return false to stop iterating +func (tr *Map[K, V]) Descend(pivot K, iter func(key K, value V) bool) { + tr.descend(pivot, iter, false) +} + +func (tr *Map[K, V]) DescendMut(pivot K, iter func(key K, value V) bool) { + tr.descend(pivot, iter, true) +} + +func (tr *Map[K, V]) descend( + pivot K, + iter func(key K, value V) bool, + mut bool, +) { + if tr.root == nil { + return + } + tr.nodeDescend(&tr.root, pivot, iter, mut) +} + +func (tr *Map[K, V]) nodeDescend(cn **mapNode[K, V], pivot K, + iter func(key K, value V) bool, mut bool, +) bool { + n := tr.isoLoad(cn, mut) + i, found := tr.search(n, pivot) + if !found { + if !n.leaf() { + if !tr.nodeDescend(&(*n.children)[i], pivot, iter, mut) { + return false + } + } + i-- + } + for ; i >= 0; i-- { + if !iter(n.items[i].key, n.items[i].value) { + return false + } + if !n.leaf() { + if !tr.nodeReverse(&(*n.children)[i], iter, mut) { + return false + } + } + } + return true +} + +// Load is for bulk loading pre-sorted items +func (tr *Map[K, V]) Load(key K, value V) (V, bool) { + item := mapPair[K, V]{key: key, value: value} + if tr.root == nil { + return tr.Set(item.key, item.value) + } + n := tr.isoLoad(&tr.root, true) + for { + n.count++ // optimistically update counts + if n.leaf() { + if len(n.items) < tr.max { + if n.items[len(n.items)-1].key < item.key { + n.items = append(n.items, item) + tr.count++ + return tr.empty.value, false + } + } + break + } + n = tr.isoLoad(&(*n.children)[len(*n.children)-1], true) + } + // revert the counts + n = tr.root + for { + n.count-- + if n.leaf() { + break + } + n = (*n.children)[len(*n.children)-1] + } + return tr.Set(item.key, item.value) +} + +// Min returns the minimum item in tree. +// Returns nil if the treex has no items. +func (tr *Map[K, V]) Min() (K, V, bool) { + return tr.minMut(false) +} + +func (tr *Map[K, V]) MinMut() (K, V, bool) { + return tr.minMut(true) +} + +func (tr *Map[K, V]) minMut(mut bool) (key K, value V, ok bool) { + if tr.root == nil { + return key, value, false + } + n := tr.isoLoad(&tr.root, mut) + for { + if n.leaf() { + item := n.items[0] + return item.key, item.value, true + } + n = tr.isoLoad(&(*n.children)[0], mut) + } +} + +// Max returns the maximum item in tree. +// Returns nil if the tree has no items. +func (tr *Map[K, V]) Max() (K, V, bool) { + return tr.maxMut(false) +} + +func (tr *Map[K, V]) MaxMut() (K, V, bool) { + return tr.maxMut(true) +} + +func (tr *Map[K, V]) maxMut(mut bool) (K, V, bool) { + if tr.root == nil { + return tr.empty.key, tr.empty.value, false + } + n := tr.isoLoad(&tr.root, mut) + for { + if n.leaf() { + item := n.items[len(n.items)-1] + return item.key, item.value, true + } + n = tr.isoLoad(&(*n.children)[len(*n.children)-1], mut) + } +} + +// PopMin removes the minimum item in tree and returns it. +// Returns nil if the tree has no items. +func (tr *Map[K, V]) PopMin() (K, V, bool) { + if tr.root == nil { + return tr.empty.key, tr.empty.value, false + } + n := tr.isoLoad(&tr.root, true) + var item mapPair[K, V] + for { + n.count-- // optimistically update counts + if n.leaf() { + item = n.items[0] + if len(n.items) == tr.min { + break + } + copy(n.items[:], n.items[1:]) + n.items[len(n.items)-1] = tr.empty + n.items = n.items[:len(n.items)-1] + tr.count-- + if tr.count == 0 { + tr.root = nil + } + return item.key, item.value, true + } + n = tr.isoLoad(&(*n.children)[0], true) + } + // revert the counts + n = tr.root + for { + n.count++ + if n.leaf() { + break + } + n = (*n.children)[0] + } + value, deleted := tr.Delete(item.key) + if deleted { + return item.key, value, true + } + return tr.empty.key, tr.empty.value, false +} + +// PopMax removes the maximum item in tree and returns it. +// Returns nil if the tree has no items. +func (tr *Map[K, V]) PopMax() (K, V, bool) { + if tr.root == nil { + return tr.empty.key, tr.empty.value, false + } + n := tr.isoLoad(&tr.root, true) + var item mapPair[K, V] + for { + n.count-- // optimistically update counts + if n.leaf() { + item = n.items[len(n.items)-1] + if len(n.items) == tr.min { + break + } + n.items[len(n.items)-1] = tr.empty + n.items = n.items[:len(n.items)-1] + tr.count-- + if tr.count == 0 { + tr.root = nil + } + return item.key, item.value, true + } + n = tr.isoLoad(&(*n.children)[len(*n.children)-1], true) + } + // revert the counts + n = tr.root + for { + n.count++ + if n.leaf() { + break + } + n = (*n.children)[len(*n.children)-1] + } + value, deleted := tr.Delete(item.key) + if deleted { + return item.key, value, true + } + return tr.empty.key, tr.empty.value, false +} + +// GetAt returns the value at index. +// Return nil if the tree is empty or the index is out of bounds. +func (tr *Map[K, V]) GetAt(index int) (K, V, bool) { + return tr.getAt(index, false) +} + +func (tr *Map[K, V]) GetAtMut(index int) (K, V, bool) { + return tr.getAt(index, true) +} + +func (tr *Map[K, V]) getAt(index int, mut bool) (K, V, bool) { + if tr.root == nil || index < 0 || index >= tr.count { + return tr.empty.key, tr.empty.value, false + } + n := tr.isoLoad(&tr.root, mut) + for { + if n.leaf() { + return n.items[index].key, n.items[index].value, true + } + i := 0 + for ; i < len(n.items); i++ { + if index < (*n.children)[i].count { + break + } else if index == (*n.children)[i].count { + return n.items[i].key, n.items[i].value, true + } + index -= (*n.children)[i].count + 1 + } + n = tr.isoLoad(&(*n.children)[i], mut) + } +} + +// DeleteAt deletes the item at index. +// Return nil if the tree is empty or the index is out of bounds. +func (tr *Map[K, V]) DeleteAt(index int) (K, V, bool) { + if tr.root == nil || index < 0 || index >= tr.count { + return tr.empty.key, tr.empty.value, false + } + var pathbuf [8]uint8 // track the path + path := pathbuf[:0] + var item mapPair[K, V] + n := tr.isoLoad(&tr.root, true) +outer: + for { + n.count-- // optimistically update counts + if n.leaf() { + // the index is the item position + item = n.items[index] + if len(n.items) == tr.min { + path = append(path, uint8(index)) + break outer + } + copy(n.items[index:], n.items[index+1:]) + n.items[len(n.items)-1] = tr.empty + n.items = n.items[:len(n.items)-1] + tr.count-- + if tr.count == 0 { + tr.root = nil + } + return item.key, item.value, true + } + i := 0 + for ; i < len(n.items); i++ { + if index < (*n.children)[i].count { + break + } else if index == (*n.children)[i].count { + item = n.items[i] + path = append(path, uint8(i)) + break outer + } + index -= (*n.children)[i].count + 1 + } + path = append(path, uint8(i)) + n = tr.isoLoad(&(*n.children)[i], true) + } + // revert the counts + n = tr.root + for i := 0; i < len(path); i++ { + n.count++ + if !n.leaf() { + n = (*n.children)[uint8(path[i])] + } + } + value, deleted := tr.Delete(item.key) + if deleted { + return item.key, value, true + } + return tr.empty.key, tr.empty.value, false +} + +// Height returns the height of the tree. +// Returns zero if tree has no items. +func (tr *Map[K, V]) Height() int { + var height int + if tr.root != nil { + n := tr.root + for { + height++ + if n.leaf() { + break + } + n = (*n.children)[0] + } + } + return height +} + +// MapIter represents an iterator for btree.Map +type MapIter[K ordered, V any] struct { + tr *Map[K, V] + mut bool + seeked bool + atstart bool + atend bool + stack []mapIterStackItem[K, V] + item mapPair[K, V] +} + +type mapIterStackItem[K ordered, V any] struct { + n *mapNode[K, V] + i int +} + +// Iter returns a read-only iterator. +func (tr *Map[K, V]) Iter() MapIter[K, V] { + return tr.iter(false) +} + +func (tr *Map[K, V]) IterMut() MapIter[K, V] { + return tr.iter(true) +} + +func (tr *Map[K, V]) iter(mut bool) MapIter[K, V] { + var iter MapIter[K, V] + iter.tr = tr + iter.mut = mut + return iter +} + +// Seek to item greater-or-equal-to key. +// Returns false if there was no item found. +func (iter *MapIter[K, V]) Seek(key K) bool { + if iter.tr == nil { + return false + } + iter.seeked = true + iter.stack = iter.stack[:0] + if iter.tr.root == nil { + return false + } + n := iter.tr.isoLoad(&iter.tr.root, iter.mut) + for { + i, found := iter.tr.search(n, key) + iter.stack = append(iter.stack, mapIterStackItem[K, V]{n, i}) + if found { + iter.item = n.items[i] + return true + } + if n.leaf() { + iter.stack[len(iter.stack)-1].i-- + return iter.Next() + } + n = iter.tr.isoLoad(&(*n.children)[i], iter.mut) + } +} + +// First moves iterator to first item in tree. +// Returns false if the tree is empty. +func (iter *MapIter[K, V]) First() bool { + if iter.tr == nil { + return false + } + iter.atend = false + iter.atstart = false + iter.seeked = true + iter.stack = iter.stack[:0] + if iter.tr.root == nil { + return false + } + n := iter.tr.isoLoad(&iter.tr.root, iter.mut) + for { + iter.stack = append(iter.stack, mapIterStackItem[K, V]{n, 0}) + if n.leaf() { + break + } + n = iter.tr.isoLoad(&(*n.children)[0], iter.mut) + } + s := &iter.stack[len(iter.stack)-1] + iter.item = s.n.items[s.i] + return true +} + +// Last moves iterator to last item in tree. +// Returns false if the tree is empty. +func (iter *MapIter[K, V]) Last() bool { + if iter.tr == nil { + return false + } + iter.seeked = true + iter.stack = iter.stack[:0] + if iter.tr.root == nil { + return false + } + n := iter.tr.isoLoad(&iter.tr.root, iter.mut) + for { + iter.stack = append(iter.stack, mapIterStackItem[K, V]{n, len(n.items)}) + if n.leaf() { + iter.stack[len(iter.stack)-1].i-- + break + } + n = iter.tr.isoLoad(&(*n.children)[len(n.items)], iter.mut) + } + s := &iter.stack[len(iter.stack)-1] + iter.item = s.n.items[s.i] + return true +} + +// Next moves iterator to the next item in iterator. +// Returns false if the tree is empty or the iterator is at the end of +// the tree. +func (iter *MapIter[K, V]) Next() bool { + if iter.tr == nil { + return false + } + if !iter.seeked { + return iter.First() + } + if len(iter.stack) == 0 { + if iter.atstart { + return iter.First() && iter.Next() + } + return false + } + s := &iter.stack[len(iter.stack)-1] + s.i++ + if s.n.leaf() { + if s.i == len(s.n.items) { + for { + iter.stack = iter.stack[:len(iter.stack)-1] + if len(iter.stack) == 0 { + iter.atend = true + return false + } + s = &iter.stack[len(iter.stack)-1] + if s.i < len(s.n.items) { + break + } + } + } + } else { + n := iter.tr.isoLoad(&(*s.n.children)[s.i], iter.mut) + for { + iter.stack = append(iter.stack, mapIterStackItem[K, V]{n, 0}) + if n.leaf() { + break + } + n = iter.tr.isoLoad(&(*n.children)[0], iter.mut) + } + } + s = &iter.stack[len(iter.stack)-1] + iter.item = s.n.items[s.i] + return true +} + +// Prev moves iterator to the previous item in iterator. +// Returns false if the tree is empty or the iterator is at the beginning of +// the tree. +func (iter *MapIter[K, V]) Prev() bool { + if iter.tr == nil { + return false + } + if !iter.seeked { + return false + } + if len(iter.stack) == 0 { + if iter.atend { + return iter.Last() && iter.Prev() + } + return false + } + s := &iter.stack[len(iter.stack)-1] + if s.n.leaf() { + s.i-- + if s.i == -1 { + for { + iter.stack = iter.stack[:len(iter.stack)-1] + if len(iter.stack) == 0 { + iter.atstart = true + return false + } + s = &iter.stack[len(iter.stack)-1] + s.i-- + if s.i > -1 { + break + } + } + } + } else { + n := iter.tr.isoLoad(&(*s.n.children)[s.i], iter.mut) + for { + iter.stack = append(iter.stack, + mapIterStackItem[K, V]{n, len(n.items)}) + if n.leaf() { + iter.stack[len(iter.stack)-1].i-- + break + } + n = iter.tr.isoLoad(&(*n.children)[len(n.items)], iter.mut) + } + } + s = &iter.stack[len(iter.stack)-1] + iter.item = s.n.items[s.i] + return true +} + +// Key returns the current iterator item key. +func (iter *MapIter[K, V]) Key() K { + return iter.item.key +} + +// Value returns the current iterator item value. +func (iter *MapIter[K, V]) Value() V { + return iter.item.value +} + +// Values returns all the values in order. +func (tr *Map[K, V]) Values() []V { + return tr.values(false) +} + +func (tr *Map[K, V]) ValuesMut() []V { + return tr.values(true) +} + +func (tr *Map[K, V]) values(mut bool) []V { + values := make([]V, 0, tr.Len()) + if tr.root != nil { + values = tr.nodeValues(&tr.root, values, mut) + } + return values +} + +func (tr *Map[K, V]) nodeValues(cn **mapNode[K, V], values []V, mut bool) []V { + n := tr.isoLoad(cn, mut) + if n.leaf() { + for i := 0; i < len(n.items); i++ { + values = append(values, n.items[i].value) + } + return values + } + for i := 0; i < len(n.items); i++ { + values = tr.nodeValues(&(*n.children)[i], values, mut) + values = append(values, n.items[i].value) + } + return tr.nodeValues(&(*n.children)[len(*n.children)-1], values, mut) +} + +// Keys returns all the keys in order. +func (tr *Map[K, V]) Keys() []K { + keys := make([]K, 0, tr.Len()) + if tr.root != nil { + keys = tr.root.keys(keys) + } + return keys +} + +func (n *mapNode[K, V]) keys(keys []K) []K { + if n.leaf() { + for i := 0; i < len(n.items); i++ { + keys = append(keys, n.items[i].key) + } + return keys + } + for i := 0; i < len(n.items); i++ { + keys = (*n.children)[i].keys(keys) + keys = append(keys, n.items[i].key) + } + return (*n.children)[len(*n.children)-1].keys(keys) +} + +// KeyValues returns all the keys and values in order. +func (tr *Map[K, V]) KeyValues() ([]K, []V) { + return tr.keyValues(false) +} + +func (tr *Map[K, V]) KeyValuesMut() ([]K, []V) { + return tr.keyValues(true) +} + +func (tr *Map[K, V]) keyValues(mut bool) ([]K, []V) { + keys := make([]K, 0, tr.Len()) + values := make([]V, 0, tr.Len()) + if tr.root != nil { + keys, values = tr.nodeKeyValues(&tr.root, keys, values, mut) + } + return keys, values +} + +func (tr *Map[K, V]) nodeKeyValues(cn **mapNode[K, V], keys []K, values []V, + mut bool, +) ([]K, []V) { + n := tr.isoLoad(cn, mut) + if n.leaf() { + for i := 0; i < len(n.items); i++ { + keys = append(keys, n.items[i].key) + values = append(values, n.items[i].value) + } + return keys, values + } + for i := 0; i < len(n.items); i++ { + keys, values = tr.nodeKeyValues(&(*n.children)[i], keys, values, mut) + keys = append(keys, n.items[i].key) + values = append(values, n.items[i].value) + } + return tr.nodeKeyValues(&(*n.children)[len(*n.children)-1], keys, values, + mut) +} + +// Clear will delete all items. +func (tr *Map[K, V]) Clear() { + tr.count = 0 + tr.root = nil +} diff --git a/vendor/github.com/tidwall/btree/set.go b/vendor/github.com/tidwall/btree/set.go new file mode 100644 index 0000000000..42f3c867c8 --- /dev/null +++ b/vendor/github.com/tidwall/btree/set.go @@ -0,0 +1,179 @@ +package btree + +type Set[K ordered] struct { + base Map[K, struct{}] +} + +// Copy +func (tr *Set[K]) Copy() *Set[K] { + tr2 := new(Set[K]) + tr2.base = *tr.base.Copy() + return tr2 +} + +func (tr *Set[K]) IsoCopy() *Set[K] { + tr2 := new(Set[K]) + tr2.base = *tr.base.IsoCopy() + return tr2 +} + +// Insert an item +func (tr *Set[K]) Insert(key K) { + tr.base.Set(key, struct{}{}) +} + +func (tr *Set[K]) Scan(iter func(key K) bool) { + tr.base.Scan(func(key K, value struct{}) bool { + return iter(key) + }) +} + +// Get a value for key +func (tr *Set[K]) Contains(key K) bool { + _, ok := tr.base.Get(key) + return ok +} + +// Len returns the number of items in the tree +func (tr *Set[K]) Len() int { + return tr.base.Len() +} + +// Delete an item +func (tr *Set[K]) Delete(key K) { + tr.base.Delete(key) +} + +// Ascend the tree within the range [pivot, last] +// Pass nil for pivot to scan all item in ascending order +// Return false to stop iterating +func (tr *Set[K]) Ascend(pivot K, iter func(key K) bool) { + tr.base.Ascend(pivot, func(key K, value struct{}) bool { + return iter(key) + }) +} + +func (tr *Set[K]) Reverse(iter func(key K) bool) { + tr.base.Reverse(func(key K, value struct{}) bool { + return iter(key) + }) +} + +// Descend the tree within the range [pivot, first] +// Pass nil for pivot to scan all item in descending order +// Return false to stop iterating +func (tr *Set[K]) Descend(pivot K, iter func(key K) bool) { + tr.base.Descend(pivot, func(key K, value struct{}) bool { + return iter(key) + }) +} + +// Load is for bulk loading pre-sorted items +func (tr *Set[K]) Load(key K) { + tr.base.Load(key, struct{}{}) +} + +// Min returns the minimum item in tree. +// Returns nil if the treex has no items. +func (tr *Set[K]) Min() (K, bool) { + key, _, ok := tr.base.Min() + return key, ok +} + +// Max returns the maximum item in tree. +// Returns nil if the tree has no items. +func (tr *Set[K]) Max() (K, bool) { + key, _, ok := tr.base.Max() + return key, ok +} + +// PopMin removes the minimum item in tree and returns it. +// Returns nil if the tree has no items. +func (tr *Set[K]) PopMin() (K, bool) { + key, _, ok := tr.base.PopMin() + return key, ok +} + +// PopMax removes the maximum item in tree and returns it. +// Returns nil if the tree has no items. +func (tr *Set[K]) PopMax() (K, bool) { + key, _, ok := tr.base.PopMax() + return key, ok +} + +// GetAt returns the value at index. +// Return nil if the tree is empty or the index is out of bounds. +func (tr *Set[K]) GetAt(index int) (K, bool) { + key, _, ok := tr.base.GetAt(index) + return key, ok +} + +// DeleteAt deletes the item at index. +// Return nil if the tree is empty or the index is out of bounds. +func (tr *Set[K]) DeleteAt(index int) (K, bool) { + key, _, ok := tr.base.DeleteAt(index) + return key, ok +} + +// Height returns the height of the tree. +// Returns zero if tree has no items. +func (tr *Set[K]) Height() int { + return tr.base.Height() +} + +// SetIter represents an iterator for btree.Set +type SetIter[K ordered] struct { + base MapIter[K, struct{}] +} + +// Iter returns a read-only iterator. +func (tr *Set[K]) Iter() SetIter[K] { + return SetIter[K]{tr.base.Iter()} +} + +// Seek to item greater-or-equal-to key. +// Returns false if there was no item found. +func (iter *SetIter[K]) Seek(key K) bool { + return iter.base.Seek(key) +} + +// First moves iterator to first item in tree. +// Returns false if the tree is empty. +func (iter *SetIter[K]) First() bool { + return iter.base.First() +} + +// Last moves iterator to last item in tree. +// Returns false if the tree is empty. +func (iter *SetIter[K]) Last() bool { + return iter.base.Last() +} + +// Next moves iterator to the next item in iterator. +// Returns false if the tree is empty or the iterator is at the end of +// the tree. +func (iter *SetIter[K]) Next() bool { + return iter.base.Next() +} + +// Prev moves iterator to the previous item in iterator. +// Returns false if the tree is empty or the iterator is at the beginning of +// the tree. +func (iter *SetIter[K]) Prev() bool { + return iter.base.Prev() +} + +// Key returns the current iterator item key. +func (iter *SetIter[K]) Key() K { + return iter.base.Key() +} + +// Keys returns all the keys in order. +func (tr *Set[K]) Keys() []K { + return tr.base.Keys() +} + +// Clear will delete all items. +func (tr *Set[K]) Clear() { + tr.base.Clear() +} diff --git a/vendor/google.golang.org/grpc/reflection/README.md b/vendor/google.golang.org/grpc/reflection/README.md new file mode 100644 index 0000000000..9ace83ccb6 --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/README.md @@ -0,0 +1,18 @@ +# Reflection + +Package reflection implements server reflection service. + +The service implemented is defined in: https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1/reflection.proto. + +To register server reflection on a gRPC server: +```go +import "google.golang.org/grpc/reflection" + +s := grpc.NewServer() +pb.RegisterYourOwnServer(s, &server{}) + +// Register reflection service on gRPC server. +reflection.Register(s) + +s.Serve(lis) +``` diff --git a/vendor/google.golang.org/grpc/reflection/adapt.go b/vendor/google.golang.org/grpc/reflection/adapt.go new file mode 100644 index 0000000000..33b907a36d --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/adapt.go @@ -0,0 +1,187 @@ +/* + * + * Copyright 2023 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package reflection + +import ( + v1reflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1" + v1reflectionpb "google.golang.org/grpc/reflection/grpc_reflection_v1" + v1alphareflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" + v1alphareflectionpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" +) + +// asV1Alpha returns an implementation of the v1alpha version of the reflection +// interface that delegates all calls to the given v1 version. +func asV1Alpha(svr v1reflectiongrpc.ServerReflectionServer) v1alphareflectiongrpc.ServerReflectionServer { + return v1AlphaServerImpl{svr: svr} +} + +type v1AlphaServerImpl struct { + svr v1reflectiongrpc.ServerReflectionServer +} + +func (s v1AlphaServerImpl) ServerReflectionInfo(stream v1alphareflectiongrpc.ServerReflection_ServerReflectionInfoServer) error { + return s.svr.ServerReflectionInfo(v1AlphaServerStreamAdapter{stream}) +} + +type v1AlphaServerStreamAdapter struct { + v1alphareflectiongrpc.ServerReflection_ServerReflectionInfoServer +} + +func (s v1AlphaServerStreamAdapter) Send(response *v1reflectionpb.ServerReflectionResponse) error { + return s.ServerReflection_ServerReflectionInfoServer.Send(v1ToV1AlphaResponse(response)) +} + +func (s v1AlphaServerStreamAdapter) Recv() (*v1reflectionpb.ServerReflectionRequest, error) { + resp, err := s.ServerReflection_ServerReflectionInfoServer.Recv() + if err != nil { + return nil, err + } + return v1AlphaToV1Request(resp), nil +} + +func v1ToV1AlphaResponse(v1 *v1reflectionpb.ServerReflectionResponse) *v1alphareflectionpb.ServerReflectionResponse { + var v1alpha v1alphareflectionpb.ServerReflectionResponse + v1alpha.ValidHost = v1.ValidHost + if v1.OriginalRequest != nil { + v1alpha.OriginalRequest = v1ToV1AlphaRequest(v1.OriginalRequest) + } + switch mr := v1.MessageResponse.(type) { + case *v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse: + if mr != nil { + v1alpha.MessageResponse = &v1alphareflectionpb.ServerReflectionResponse_FileDescriptorResponse{ + FileDescriptorResponse: &v1alphareflectionpb.FileDescriptorResponse{ + FileDescriptorProto: mr.FileDescriptorResponse.GetFileDescriptorProto(), + }, + } + } + case *v1reflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse: + if mr != nil { + v1alpha.MessageResponse = &v1alphareflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse{ + AllExtensionNumbersResponse: &v1alphareflectionpb.ExtensionNumberResponse{ + BaseTypeName: mr.AllExtensionNumbersResponse.GetBaseTypeName(), + ExtensionNumber: mr.AllExtensionNumbersResponse.GetExtensionNumber(), + }, + } + } + case *v1reflectionpb.ServerReflectionResponse_ListServicesResponse: + if mr != nil { + svcs := make([]*v1alphareflectionpb.ServiceResponse, len(mr.ListServicesResponse.GetService())) + for i, svc := range mr.ListServicesResponse.GetService() { + svcs[i] = &v1alphareflectionpb.ServiceResponse{ + Name: svc.GetName(), + } + } + v1alpha.MessageResponse = &v1alphareflectionpb.ServerReflectionResponse_ListServicesResponse{ + ListServicesResponse: &v1alphareflectionpb.ListServiceResponse{ + Service: svcs, + }, + } + } + case *v1reflectionpb.ServerReflectionResponse_ErrorResponse: + if mr != nil { + v1alpha.MessageResponse = &v1alphareflectionpb.ServerReflectionResponse_ErrorResponse{ + ErrorResponse: &v1alphareflectionpb.ErrorResponse{ + ErrorCode: mr.ErrorResponse.GetErrorCode(), + ErrorMessage: mr.ErrorResponse.GetErrorMessage(), + }, + } + } + default: + // no value set + } + return &v1alpha +} + +func v1AlphaToV1Request(v1alpha *v1alphareflectionpb.ServerReflectionRequest) *v1reflectionpb.ServerReflectionRequest { + var v1 v1reflectionpb.ServerReflectionRequest + v1.Host = v1alpha.Host + switch mr := v1alpha.MessageRequest.(type) { + case *v1alphareflectionpb.ServerReflectionRequest_FileByFilename: + v1.MessageRequest = &v1reflectionpb.ServerReflectionRequest_FileByFilename{ + FileByFilename: mr.FileByFilename, + } + case *v1alphareflectionpb.ServerReflectionRequest_FileContainingSymbol: + v1.MessageRequest = &v1reflectionpb.ServerReflectionRequest_FileContainingSymbol{ + FileContainingSymbol: mr.FileContainingSymbol, + } + case *v1alphareflectionpb.ServerReflectionRequest_FileContainingExtension: + if mr.FileContainingExtension != nil { + v1.MessageRequest = &v1reflectionpb.ServerReflectionRequest_FileContainingExtension{ + FileContainingExtension: &v1reflectionpb.ExtensionRequest{ + ContainingType: mr.FileContainingExtension.GetContainingType(), + ExtensionNumber: mr.FileContainingExtension.GetExtensionNumber(), + }, + } + } + case *v1alphareflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType: + v1.MessageRequest = &v1reflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType{ + AllExtensionNumbersOfType: mr.AllExtensionNumbersOfType, + } + case *v1alphareflectionpb.ServerReflectionRequest_ListServices: + v1.MessageRequest = &v1reflectionpb.ServerReflectionRequest_ListServices{ + ListServices: mr.ListServices, + } + default: + // no value set + } + return &v1 +} + +func v1ToV1AlphaRequest(v1 *v1reflectionpb.ServerReflectionRequest) *v1alphareflectionpb.ServerReflectionRequest { + var v1alpha v1alphareflectionpb.ServerReflectionRequest + v1alpha.Host = v1.Host + switch mr := v1.MessageRequest.(type) { + case *v1reflectionpb.ServerReflectionRequest_FileByFilename: + if mr != nil { + v1alpha.MessageRequest = &v1alphareflectionpb.ServerReflectionRequest_FileByFilename{ + FileByFilename: mr.FileByFilename, + } + } + case *v1reflectionpb.ServerReflectionRequest_FileContainingSymbol: + if mr != nil { + v1alpha.MessageRequest = &v1alphareflectionpb.ServerReflectionRequest_FileContainingSymbol{ + FileContainingSymbol: mr.FileContainingSymbol, + } + } + case *v1reflectionpb.ServerReflectionRequest_FileContainingExtension: + if mr != nil { + v1alpha.MessageRequest = &v1alphareflectionpb.ServerReflectionRequest_FileContainingExtension{ + FileContainingExtension: &v1alphareflectionpb.ExtensionRequest{ + ContainingType: mr.FileContainingExtension.GetContainingType(), + ExtensionNumber: mr.FileContainingExtension.GetExtensionNumber(), + }, + } + } + case *v1reflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType: + if mr != nil { + v1alpha.MessageRequest = &v1alphareflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType{ + AllExtensionNumbersOfType: mr.AllExtensionNumbersOfType, + } + } + case *v1reflectionpb.ServerReflectionRequest_ListServices: + if mr != nil { + v1alpha.MessageRequest = &v1alphareflectionpb.ServerReflectionRequest_ListServices{ + ListServices: mr.ListServices, + } + } + default: + // no value set + } + return &v1alpha +} diff --git a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go new file mode 100644 index 0000000000..8953c9d8d6 --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go @@ -0,0 +1,953 @@ +// Copyright 2016 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Service exported by server reflection. A more complete description of how +// server reflection works can be found at +// https://github.com/grpc/grpc/blob/master/doc/server-reflection.md +// +// The canonical version of this proto can be found at +// https://github.com/grpc/grpc-proto/blob/master/grpc/reflection/v1/reflection.proto + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.2 +// source: grpc/reflection/v1/reflection.proto + +package grpc_reflection_v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// The message sent by the client when calling ServerReflectionInfo method. +type ServerReflectionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` + // To use reflection service, the client should set one of the following + // fields in message_request. The server distinguishes requests by their + // defined field and then handles them using corresponding methods. + // + // Types that are assignable to MessageRequest: + // + // *ServerReflectionRequest_FileByFilename + // *ServerReflectionRequest_FileContainingSymbol + // *ServerReflectionRequest_FileContainingExtension + // *ServerReflectionRequest_AllExtensionNumbersOfType + // *ServerReflectionRequest_ListServices + MessageRequest isServerReflectionRequest_MessageRequest `protobuf_oneof:"message_request"` +} + +func (x *ServerReflectionRequest) Reset() { + *x = ServerReflectionRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServerReflectionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerReflectionRequest) ProtoMessage() {} + +func (x *ServerReflectionRequest) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServerReflectionRequest.ProtoReflect.Descriptor instead. +func (*ServerReflectionRequest) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{0} +} + +func (x *ServerReflectionRequest) GetHost() string { + if x != nil { + return x.Host + } + return "" +} + +func (m *ServerReflectionRequest) GetMessageRequest() isServerReflectionRequest_MessageRequest { + if m != nil { + return m.MessageRequest + } + return nil +} + +func (x *ServerReflectionRequest) GetFileByFilename() string { + if x, ok := x.GetMessageRequest().(*ServerReflectionRequest_FileByFilename); ok { + return x.FileByFilename + } + return "" +} + +func (x *ServerReflectionRequest) GetFileContainingSymbol() string { + if x, ok := x.GetMessageRequest().(*ServerReflectionRequest_FileContainingSymbol); ok { + return x.FileContainingSymbol + } + return "" +} + +func (x *ServerReflectionRequest) GetFileContainingExtension() *ExtensionRequest { + if x, ok := x.GetMessageRequest().(*ServerReflectionRequest_FileContainingExtension); ok { + return x.FileContainingExtension + } + return nil +} + +func (x *ServerReflectionRequest) GetAllExtensionNumbersOfType() string { + if x, ok := x.GetMessageRequest().(*ServerReflectionRequest_AllExtensionNumbersOfType); ok { + return x.AllExtensionNumbersOfType + } + return "" +} + +func (x *ServerReflectionRequest) GetListServices() string { + if x, ok := x.GetMessageRequest().(*ServerReflectionRequest_ListServices); ok { + return x.ListServices + } + return "" +} + +type isServerReflectionRequest_MessageRequest interface { + isServerReflectionRequest_MessageRequest() +} + +type ServerReflectionRequest_FileByFilename struct { + // Find a proto file by the file name. + FileByFilename string `protobuf:"bytes,3,opt,name=file_by_filename,json=fileByFilename,proto3,oneof"` +} + +type ServerReflectionRequest_FileContainingSymbol struct { + // Find the proto file that declares the given fully-qualified symbol name. + // This field should be a fully-qualified symbol name + // (e.g. .[.] or .). + FileContainingSymbol string `protobuf:"bytes,4,opt,name=file_containing_symbol,json=fileContainingSymbol,proto3,oneof"` +} + +type ServerReflectionRequest_FileContainingExtension struct { + // Find the proto file which defines an extension extending the given + // message type with the given field number. + FileContainingExtension *ExtensionRequest `protobuf:"bytes,5,opt,name=file_containing_extension,json=fileContainingExtension,proto3,oneof"` +} + +type ServerReflectionRequest_AllExtensionNumbersOfType struct { + // Finds the tag numbers used by all known extensions of the given message + // type, and appends them to ExtensionNumberResponse in an undefined order. + // Its corresponding method is best-effort: it's not guaranteed that the + // reflection service will implement this method, and it's not guaranteed + // that this method will provide all extensions. Returns + // StatusCode::UNIMPLEMENTED if it's not implemented. + // This field should be a fully-qualified type name. The format is + // . + AllExtensionNumbersOfType string `protobuf:"bytes,6,opt,name=all_extension_numbers_of_type,json=allExtensionNumbersOfType,proto3,oneof"` +} + +type ServerReflectionRequest_ListServices struct { + // List the full names of registered services. The content will not be + // checked. + ListServices string `protobuf:"bytes,7,opt,name=list_services,json=listServices,proto3,oneof"` +} + +func (*ServerReflectionRequest_FileByFilename) isServerReflectionRequest_MessageRequest() {} + +func (*ServerReflectionRequest_FileContainingSymbol) isServerReflectionRequest_MessageRequest() {} + +func (*ServerReflectionRequest_FileContainingExtension) isServerReflectionRequest_MessageRequest() {} + +func (*ServerReflectionRequest_AllExtensionNumbersOfType) isServerReflectionRequest_MessageRequest() { +} + +func (*ServerReflectionRequest_ListServices) isServerReflectionRequest_MessageRequest() {} + +// The type name and extension number sent by the client when requesting +// file_containing_extension. +type ExtensionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Fully-qualified type name. The format should be . + ContainingType string `protobuf:"bytes,1,opt,name=containing_type,json=containingType,proto3" json:"containing_type,omitempty"` + ExtensionNumber int32 `protobuf:"varint,2,opt,name=extension_number,json=extensionNumber,proto3" json:"extension_number,omitempty"` +} + +func (x *ExtensionRequest) Reset() { + *x = ExtensionRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExtensionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtensionRequest) ProtoMessage() {} + +func (x *ExtensionRequest) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtensionRequest.ProtoReflect.Descriptor instead. +func (*ExtensionRequest) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{1} +} + +func (x *ExtensionRequest) GetContainingType() string { + if x != nil { + return x.ContainingType + } + return "" +} + +func (x *ExtensionRequest) GetExtensionNumber() int32 { + if x != nil { + return x.ExtensionNumber + } + return 0 +} + +// The message sent by the server to answer ServerReflectionInfo method. +type ServerReflectionResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ValidHost string `protobuf:"bytes,1,opt,name=valid_host,json=validHost,proto3" json:"valid_host,omitempty"` + OriginalRequest *ServerReflectionRequest `protobuf:"bytes,2,opt,name=original_request,json=originalRequest,proto3" json:"original_request,omitempty"` + // The server sets one of the following fields according to the message_request + // in the request. + // + // Types that are assignable to MessageResponse: + // + // *ServerReflectionResponse_FileDescriptorResponse + // *ServerReflectionResponse_AllExtensionNumbersResponse + // *ServerReflectionResponse_ListServicesResponse + // *ServerReflectionResponse_ErrorResponse + MessageResponse isServerReflectionResponse_MessageResponse `protobuf_oneof:"message_response"` +} + +func (x *ServerReflectionResponse) Reset() { + *x = ServerReflectionResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServerReflectionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerReflectionResponse) ProtoMessage() {} + +func (x *ServerReflectionResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServerReflectionResponse.ProtoReflect.Descriptor instead. +func (*ServerReflectionResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{2} +} + +func (x *ServerReflectionResponse) GetValidHost() string { + if x != nil { + return x.ValidHost + } + return "" +} + +func (x *ServerReflectionResponse) GetOriginalRequest() *ServerReflectionRequest { + if x != nil { + return x.OriginalRequest + } + return nil +} + +func (m *ServerReflectionResponse) GetMessageResponse() isServerReflectionResponse_MessageResponse { + if m != nil { + return m.MessageResponse + } + return nil +} + +func (x *ServerReflectionResponse) GetFileDescriptorResponse() *FileDescriptorResponse { + if x, ok := x.GetMessageResponse().(*ServerReflectionResponse_FileDescriptorResponse); ok { + return x.FileDescriptorResponse + } + return nil +} + +func (x *ServerReflectionResponse) GetAllExtensionNumbersResponse() *ExtensionNumberResponse { + if x, ok := x.GetMessageResponse().(*ServerReflectionResponse_AllExtensionNumbersResponse); ok { + return x.AllExtensionNumbersResponse + } + return nil +} + +func (x *ServerReflectionResponse) GetListServicesResponse() *ListServiceResponse { + if x, ok := x.GetMessageResponse().(*ServerReflectionResponse_ListServicesResponse); ok { + return x.ListServicesResponse + } + return nil +} + +func (x *ServerReflectionResponse) GetErrorResponse() *ErrorResponse { + if x, ok := x.GetMessageResponse().(*ServerReflectionResponse_ErrorResponse); ok { + return x.ErrorResponse + } + return nil +} + +type isServerReflectionResponse_MessageResponse interface { + isServerReflectionResponse_MessageResponse() +} + +type ServerReflectionResponse_FileDescriptorResponse struct { + // This message is used to answer file_by_filename, file_containing_symbol, + // file_containing_extension requests with transitive dependencies. + // As the repeated label is not allowed in oneof fields, we use a + // FileDescriptorResponse message to encapsulate the repeated fields. + // The reflection service is allowed to avoid sending FileDescriptorProtos + // that were previously sent in response to earlier requests in the stream. + FileDescriptorResponse *FileDescriptorResponse `protobuf:"bytes,4,opt,name=file_descriptor_response,json=fileDescriptorResponse,proto3,oneof"` +} + +type ServerReflectionResponse_AllExtensionNumbersResponse struct { + // This message is used to answer all_extension_numbers_of_type requests. + AllExtensionNumbersResponse *ExtensionNumberResponse `protobuf:"bytes,5,opt,name=all_extension_numbers_response,json=allExtensionNumbersResponse,proto3,oneof"` +} + +type ServerReflectionResponse_ListServicesResponse struct { + // This message is used to answer list_services requests. + ListServicesResponse *ListServiceResponse `protobuf:"bytes,6,opt,name=list_services_response,json=listServicesResponse,proto3,oneof"` +} + +type ServerReflectionResponse_ErrorResponse struct { + // This message is used when an error occurs. + ErrorResponse *ErrorResponse `protobuf:"bytes,7,opt,name=error_response,json=errorResponse,proto3,oneof"` +} + +func (*ServerReflectionResponse_FileDescriptorResponse) isServerReflectionResponse_MessageResponse() { +} + +func (*ServerReflectionResponse_AllExtensionNumbersResponse) isServerReflectionResponse_MessageResponse() { +} + +func (*ServerReflectionResponse_ListServicesResponse) isServerReflectionResponse_MessageResponse() {} + +func (*ServerReflectionResponse_ErrorResponse) isServerReflectionResponse_MessageResponse() {} + +// Serialized FileDescriptorProto messages sent by the server answering +// a file_by_filename, file_containing_symbol, or file_containing_extension +// request. +type FileDescriptorResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Serialized FileDescriptorProto messages. We avoid taking a dependency on + // descriptor.proto, which uses proto2 only features, by making them opaque + // bytes instead. + FileDescriptorProto [][]byte `protobuf:"bytes,1,rep,name=file_descriptor_proto,json=fileDescriptorProto,proto3" json:"file_descriptor_proto,omitempty"` +} + +func (x *FileDescriptorResponse) Reset() { + *x = FileDescriptorResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FileDescriptorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FileDescriptorResponse) ProtoMessage() {} + +func (x *FileDescriptorResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FileDescriptorResponse.ProtoReflect.Descriptor instead. +func (*FileDescriptorResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{3} +} + +func (x *FileDescriptorResponse) GetFileDescriptorProto() [][]byte { + if x != nil { + return x.FileDescriptorProto + } + return nil +} + +// A list of extension numbers sent by the server answering +// all_extension_numbers_of_type request. +type ExtensionNumberResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Full name of the base type, including the package name. The format + // is . + BaseTypeName string `protobuf:"bytes,1,opt,name=base_type_name,json=baseTypeName,proto3" json:"base_type_name,omitempty"` + ExtensionNumber []int32 `protobuf:"varint,2,rep,packed,name=extension_number,json=extensionNumber,proto3" json:"extension_number,omitempty"` +} + +func (x *ExtensionNumberResponse) Reset() { + *x = ExtensionNumberResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExtensionNumberResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtensionNumberResponse) ProtoMessage() {} + +func (x *ExtensionNumberResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtensionNumberResponse.ProtoReflect.Descriptor instead. +func (*ExtensionNumberResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{4} +} + +func (x *ExtensionNumberResponse) GetBaseTypeName() string { + if x != nil { + return x.BaseTypeName + } + return "" +} + +func (x *ExtensionNumberResponse) GetExtensionNumber() []int32 { + if x != nil { + return x.ExtensionNumber + } + return nil +} + +// A list of ServiceResponse sent by the server answering list_services request. +type ListServiceResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The information of each service may be expanded in the future, so we use + // ServiceResponse message to encapsulate it. + Service []*ServiceResponse `protobuf:"bytes,1,rep,name=service,proto3" json:"service,omitempty"` +} + +func (x *ListServiceResponse) Reset() { + *x = ListServiceResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListServiceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListServiceResponse) ProtoMessage() {} + +func (x *ListServiceResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListServiceResponse.ProtoReflect.Descriptor instead. +func (*ListServiceResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{5} +} + +func (x *ListServiceResponse) GetService() []*ServiceResponse { + if x != nil { + return x.Service + } + return nil +} + +// The information of a single service used by ListServiceResponse to answer +// list_services request. +type ServiceResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Full name of a registered service, including its package name. The format + // is . + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *ServiceResponse) Reset() { + *x = ServiceResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServiceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServiceResponse) ProtoMessage() {} + +func (x *ServiceResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServiceResponse.ProtoReflect.Descriptor instead. +func (*ServiceResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{6} +} + +func (x *ServiceResponse) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +// The error code and error message sent by the server when an error occurs. +type ErrorResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // This field uses the error codes defined in grpc::StatusCode. + ErrorCode int32 `protobuf:"varint,1,opt,name=error_code,json=errorCode,proto3" json:"error_code,omitempty"` + ErrorMessage string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` +} + +func (x *ErrorResponse) Reset() { + *x = ErrorResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ErrorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ErrorResponse) ProtoMessage() {} + +func (x *ErrorResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ErrorResponse.ProtoReflect.Descriptor instead. +func (*ErrorResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{7} +} + +func (x *ErrorResponse) GetErrorCode() int32 { + if x != nil { + return x.ErrorCode + } + return 0 +} + +func (x *ErrorResponse) GetErrorMessage() string { + if x != nil { + return x.ErrorMessage + } + return "" +} + +var File_grpc_reflection_v1_reflection_proto protoreflect.FileDescriptor + +var file_grpc_reflection_v1_reflection_proto_rawDesc = []byte{ + 0x0a, 0x23, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x22, 0xf3, 0x02, 0x0a, 0x17, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x66, 0x69, 0x6c, + 0x65, 0x5f, 0x62, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0e, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x79, 0x46, 0x69, 0x6c, + 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x16, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x14, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x12, 0x62, 0x0a, + 0x19, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, + 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x24, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x17, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x42, 0x0a, 0x1d, 0x61, 0x6c, 0x6c, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, + 0x6f, 0x6e, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x19, 0x61, 0x6c, 0x6c, 0x45, + 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x4f, + 0x66, 0x54, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x0d, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, + 0x6c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x42, 0x11, 0x0a, 0x0f, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, + 0x66, 0x0a, 0x10, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, + 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x29, 0x0a, 0x10, + 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, + 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0xae, 0x04, 0x0a, 0x18, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x68, 0x6f, + 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x48, + 0x6f, 0x73, 0x74, 0x12, 0x56, 0x0a, 0x10, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0f, 0x6f, 0x72, 0x69, 0x67, + 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x66, 0x0a, 0x18, 0x66, + 0x69, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x72, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x16, 0x66, 0x69, 0x6c, + 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x1e, 0x61, 0x6c, 0x6c, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x5f, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x1b, 0x61, 0x6c, 0x6c, 0x45, + 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x16, 0x6c, 0x69, 0x73, 0x74, 0x5f, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, + 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x48, 0x00, 0x52, 0x14, 0x6c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0e, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x21, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x12, 0x0a, 0x10, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4c, 0x0a, 0x16, 0x46, 0x69, 0x6c, 0x65, + 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0c, 0x52, 0x13, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, + 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6a, 0x0a, 0x17, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, + 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x61, 0x73, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x05, 0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x22, 0x54, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x07, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, + 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x25, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, + 0x53, 0x0a, 0x0d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, + 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x32, 0x89, 0x01, 0x0a, 0x10, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, + 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x75, 0x0a, 0x14, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x2b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, + 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, + 0x42, 0x66, 0x0a, 0x15, 0x69, 0x6f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x42, 0x15, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x34, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, + 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x72, 0x65, 0x66, 0x6c, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x72, 0x65, 0x66, 0x6c, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_grpc_reflection_v1_reflection_proto_rawDescOnce sync.Once + file_grpc_reflection_v1_reflection_proto_rawDescData = file_grpc_reflection_v1_reflection_proto_rawDesc +) + +func file_grpc_reflection_v1_reflection_proto_rawDescGZIP() []byte { + file_grpc_reflection_v1_reflection_proto_rawDescOnce.Do(func() { + file_grpc_reflection_v1_reflection_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_reflection_v1_reflection_proto_rawDescData) + }) + return file_grpc_reflection_v1_reflection_proto_rawDescData +} + +var file_grpc_reflection_v1_reflection_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_grpc_reflection_v1_reflection_proto_goTypes = []interface{}{ + (*ServerReflectionRequest)(nil), // 0: grpc.reflection.v1.ServerReflectionRequest + (*ExtensionRequest)(nil), // 1: grpc.reflection.v1.ExtensionRequest + (*ServerReflectionResponse)(nil), // 2: grpc.reflection.v1.ServerReflectionResponse + (*FileDescriptorResponse)(nil), // 3: grpc.reflection.v1.FileDescriptorResponse + (*ExtensionNumberResponse)(nil), // 4: grpc.reflection.v1.ExtensionNumberResponse + (*ListServiceResponse)(nil), // 5: grpc.reflection.v1.ListServiceResponse + (*ServiceResponse)(nil), // 6: grpc.reflection.v1.ServiceResponse + (*ErrorResponse)(nil), // 7: grpc.reflection.v1.ErrorResponse +} +var file_grpc_reflection_v1_reflection_proto_depIdxs = []int32{ + 1, // 0: grpc.reflection.v1.ServerReflectionRequest.file_containing_extension:type_name -> grpc.reflection.v1.ExtensionRequest + 0, // 1: grpc.reflection.v1.ServerReflectionResponse.original_request:type_name -> grpc.reflection.v1.ServerReflectionRequest + 3, // 2: grpc.reflection.v1.ServerReflectionResponse.file_descriptor_response:type_name -> grpc.reflection.v1.FileDescriptorResponse + 4, // 3: grpc.reflection.v1.ServerReflectionResponse.all_extension_numbers_response:type_name -> grpc.reflection.v1.ExtensionNumberResponse + 5, // 4: grpc.reflection.v1.ServerReflectionResponse.list_services_response:type_name -> grpc.reflection.v1.ListServiceResponse + 7, // 5: grpc.reflection.v1.ServerReflectionResponse.error_response:type_name -> grpc.reflection.v1.ErrorResponse + 6, // 6: grpc.reflection.v1.ListServiceResponse.service:type_name -> grpc.reflection.v1.ServiceResponse + 0, // 7: grpc.reflection.v1.ServerReflection.ServerReflectionInfo:input_type -> grpc.reflection.v1.ServerReflectionRequest + 2, // 8: grpc.reflection.v1.ServerReflection.ServerReflectionInfo:output_type -> grpc.reflection.v1.ServerReflectionResponse + 8, // [8:9] is the sub-list for method output_type + 7, // [7:8] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name +} + +func init() { file_grpc_reflection_v1_reflection_proto_init() } +func file_grpc_reflection_v1_reflection_proto_init() { + if File_grpc_reflection_v1_reflection_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_grpc_reflection_v1_reflection_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ServerReflectionRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_reflection_v1_reflection_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExtensionRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_reflection_v1_reflection_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ServerReflectionResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_reflection_v1_reflection_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FileDescriptorResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_reflection_v1_reflection_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExtensionNumberResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_reflection_v1_reflection_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListServiceResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_reflection_v1_reflection_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ServiceResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_reflection_v1_reflection_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ErrorResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_grpc_reflection_v1_reflection_proto_msgTypes[0].OneofWrappers = []interface{}{ + (*ServerReflectionRequest_FileByFilename)(nil), + (*ServerReflectionRequest_FileContainingSymbol)(nil), + (*ServerReflectionRequest_FileContainingExtension)(nil), + (*ServerReflectionRequest_AllExtensionNumbersOfType)(nil), + (*ServerReflectionRequest_ListServices)(nil), + } + file_grpc_reflection_v1_reflection_proto_msgTypes[2].OneofWrappers = []interface{}{ + (*ServerReflectionResponse_FileDescriptorResponse)(nil), + (*ServerReflectionResponse_AllExtensionNumbersResponse)(nil), + (*ServerReflectionResponse_ListServicesResponse)(nil), + (*ServerReflectionResponse_ErrorResponse)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_grpc_reflection_v1_reflection_proto_rawDesc, + NumEnums: 0, + NumMessages: 8, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_grpc_reflection_v1_reflection_proto_goTypes, + DependencyIndexes: file_grpc_reflection_v1_reflection_proto_depIdxs, + MessageInfos: file_grpc_reflection_v1_reflection_proto_msgTypes, + }.Build() + File_grpc_reflection_v1_reflection_proto = out.File + file_grpc_reflection_v1_reflection_proto_rawDesc = nil + file_grpc_reflection_v1_reflection_proto_goTypes = nil + file_grpc_reflection_v1_reflection_proto_depIdxs = nil +} diff --git a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go new file mode 100644 index 0000000000..d6cdd5b54c --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go @@ -0,0 +1,164 @@ +// Copyright 2016 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Service exported by server reflection. A more complete description of how +// server reflection works can be found at +// https://github.com/grpc/grpc/blob/master/doc/server-reflection.md +// +// The canonical version of this proto can be found at +// https://github.com/grpc/grpc-proto/blob/master/grpc/reflection/v1/reflection.proto + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v4.25.2 +// source: grpc/reflection/v1/reflection.proto + +package grpc_reflection_v1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + ServerReflection_ServerReflectionInfo_FullMethodName = "/grpc.reflection.v1.ServerReflection/ServerReflectionInfo" +) + +// ServerReflectionClient is the client API for ServerReflection service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type ServerReflectionClient interface { + // The reflection service is structured as a bidirectional stream, ensuring + // all related requests go to a single server. + ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (ServerReflection_ServerReflectionInfoClient, error) +} + +type serverReflectionClient struct { + cc grpc.ClientConnInterface +} + +func NewServerReflectionClient(cc grpc.ClientConnInterface) ServerReflectionClient { + return &serverReflectionClient{cc} +} + +func (c *serverReflectionClient) ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (ServerReflection_ServerReflectionInfoClient, error) { + stream, err := c.cc.NewStream(ctx, &ServerReflection_ServiceDesc.Streams[0], ServerReflection_ServerReflectionInfo_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &serverReflectionServerReflectionInfoClient{stream} + return x, nil +} + +type ServerReflection_ServerReflectionInfoClient interface { + Send(*ServerReflectionRequest) error + Recv() (*ServerReflectionResponse, error) + grpc.ClientStream +} + +type serverReflectionServerReflectionInfoClient struct { + grpc.ClientStream +} + +func (x *serverReflectionServerReflectionInfoClient) Send(m *ServerReflectionRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *serverReflectionServerReflectionInfoClient) Recv() (*ServerReflectionResponse, error) { + m := new(ServerReflectionResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// ServerReflectionServer is the server API for ServerReflection service. +// All implementations should embed UnimplementedServerReflectionServer +// for forward compatibility +type ServerReflectionServer interface { + // The reflection service is structured as a bidirectional stream, ensuring + // all related requests go to a single server. + ServerReflectionInfo(ServerReflection_ServerReflectionInfoServer) error +} + +// UnimplementedServerReflectionServer should be embedded to have forward compatible implementations. +type UnimplementedServerReflectionServer struct { +} + +func (UnimplementedServerReflectionServer) ServerReflectionInfo(ServerReflection_ServerReflectionInfoServer) error { + return status.Errorf(codes.Unimplemented, "method ServerReflectionInfo not implemented") +} + +// UnsafeServerReflectionServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ServerReflectionServer will +// result in compilation errors. +type UnsafeServerReflectionServer interface { + mustEmbedUnimplementedServerReflectionServer() +} + +func RegisterServerReflectionServer(s grpc.ServiceRegistrar, srv ServerReflectionServer) { + s.RegisterService(&ServerReflection_ServiceDesc, srv) +} + +func _ServerReflection_ServerReflectionInfo_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(ServerReflectionServer).ServerReflectionInfo(&serverReflectionServerReflectionInfoServer{stream}) +} + +type ServerReflection_ServerReflectionInfoServer interface { + Send(*ServerReflectionResponse) error + Recv() (*ServerReflectionRequest, error) + grpc.ServerStream +} + +type serverReflectionServerReflectionInfoServer struct { + grpc.ServerStream +} + +func (x *serverReflectionServerReflectionInfoServer) Send(m *ServerReflectionResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *serverReflectionServerReflectionInfoServer) Recv() (*ServerReflectionRequest, error) { + m := new(ServerReflectionRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// ServerReflection_ServiceDesc is the grpc.ServiceDesc for ServerReflection service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ServerReflection_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "grpc.reflection.v1.ServerReflection", + HandlerType: (*ServerReflectionServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "ServerReflectionInfo", + Handler: _ServerReflection_ServerReflectionInfo_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "grpc/reflection/v1/reflection.proto", +} diff --git a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go new file mode 100644 index 0000000000..929733e7bd --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go @@ -0,0 +1,1028 @@ +// Copyright 2016 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// Service exported by server reflection + +// Warning: this entire file is deprecated. Use this instead: +// https://github.com/grpc/grpc-proto/blob/master/grpc/reflection/v1/reflection.proto + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc v4.25.2 +// grpc/reflection/v1alpha/reflection.proto is a deprecated file. + +package grpc_reflection_v1alpha + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// The message sent by the client when calling ServerReflectionInfo method. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type ServerReflectionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` + // To use reflection service, the client should set one of the following + // fields in message_request. The server distinguishes requests by their + // defined field and then handles them using corresponding methods. + // + // Types that are assignable to MessageRequest: + // + // *ServerReflectionRequest_FileByFilename + // *ServerReflectionRequest_FileContainingSymbol + // *ServerReflectionRequest_FileContainingExtension + // *ServerReflectionRequest_AllExtensionNumbersOfType + // *ServerReflectionRequest_ListServices + MessageRequest isServerReflectionRequest_MessageRequest `protobuf_oneof:"message_request"` +} + +func (x *ServerReflectionRequest) Reset() { + *x = ServerReflectionRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServerReflectionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerReflectionRequest) ProtoMessage() {} + +func (x *ServerReflectionRequest) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServerReflectionRequest.ProtoReflect.Descriptor instead. +func (*ServerReflectionRequest) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{0} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionRequest) GetHost() string { + if x != nil { + return x.Host + } + return "" +} + +func (m *ServerReflectionRequest) GetMessageRequest() isServerReflectionRequest_MessageRequest { + if m != nil { + return m.MessageRequest + } + return nil +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionRequest) GetFileByFilename() string { + if x, ok := x.GetMessageRequest().(*ServerReflectionRequest_FileByFilename); ok { + return x.FileByFilename + } + return "" +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionRequest) GetFileContainingSymbol() string { + if x, ok := x.GetMessageRequest().(*ServerReflectionRequest_FileContainingSymbol); ok { + return x.FileContainingSymbol + } + return "" +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionRequest) GetFileContainingExtension() *ExtensionRequest { + if x, ok := x.GetMessageRequest().(*ServerReflectionRequest_FileContainingExtension); ok { + return x.FileContainingExtension + } + return nil +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionRequest) GetAllExtensionNumbersOfType() string { + if x, ok := x.GetMessageRequest().(*ServerReflectionRequest_AllExtensionNumbersOfType); ok { + return x.AllExtensionNumbersOfType + } + return "" +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionRequest) GetListServices() string { + if x, ok := x.GetMessageRequest().(*ServerReflectionRequest_ListServices); ok { + return x.ListServices + } + return "" +} + +type isServerReflectionRequest_MessageRequest interface { + isServerReflectionRequest_MessageRequest() +} + +type ServerReflectionRequest_FileByFilename struct { + // Find a proto file by the file name. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + FileByFilename string `protobuf:"bytes,3,opt,name=file_by_filename,json=fileByFilename,proto3,oneof"` +} + +type ServerReflectionRequest_FileContainingSymbol struct { + // Find the proto file that declares the given fully-qualified symbol name. + // This field should be a fully-qualified symbol name + // (e.g. .[.] or .). + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + FileContainingSymbol string `protobuf:"bytes,4,opt,name=file_containing_symbol,json=fileContainingSymbol,proto3,oneof"` +} + +type ServerReflectionRequest_FileContainingExtension struct { + // Find the proto file which defines an extension extending the given + // message type with the given field number. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + FileContainingExtension *ExtensionRequest `protobuf:"bytes,5,opt,name=file_containing_extension,json=fileContainingExtension,proto3,oneof"` +} + +type ServerReflectionRequest_AllExtensionNumbersOfType struct { + // Finds the tag numbers used by all known extensions of extendee_type, and + // appends them to ExtensionNumberResponse in an undefined order. + // Its corresponding method is best-effort: it's not guaranteed that the + // reflection service will implement this method, and it's not guaranteed + // that this method will provide all extensions. Returns + // StatusCode::UNIMPLEMENTED if it's not implemented. + // This field should be a fully-qualified type name. The format is + // . + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + AllExtensionNumbersOfType string `protobuf:"bytes,6,opt,name=all_extension_numbers_of_type,json=allExtensionNumbersOfType,proto3,oneof"` +} + +type ServerReflectionRequest_ListServices struct { + // List the full names of registered services. The content will not be + // checked. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ListServices string `protobuf:"bytes,7,opt,name=list_services,json=listServices,proto3,oneof"` +} + +func (*ServerReflectionRequest_FileByFilename) isServerReflectionRequest_MessageRequest() {} + +func (*ServerReflectionRequest_FileContainingSymbol) isServerReflectionRequest_MessageRequest() {} + +func (*ServerReflectionRequest_FileContainingExtension) isServerReflectionRequest_MessageRequest() {} + +func (*ServerReflectionRequest_AllExtensionNumbersOfType) isServerReflectionRequest_MessageRequest() { +} + +func (*ServerReflectionRequest_ListServices) isServerReflectionRequest_MessageRequest() {} + +// The type name and extension number sent by the client when requesting +// file_containing_extension. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type ExtensionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Fully-qualified type name. The format should be . + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ContainingType string `protobuf:"bytes,1,opt,name=containing_type,json=containingType,proto3" json:"containing_type,omitempty"` + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ExtensionNumber int32 `protobuf:"varint,2,opt,name=extension_number,json=extensionNumber,proto3" json:"extension_number,omitempty"` +} + +func (x *ExtensionRequest) Reset() { + *x = ExtensionRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExtensionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtensionRequest) ProtoMessage() {} + +func (x *ExtensionRequest) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtensionRequest.ProtoReflect.Descriptor instead. +func (*ExtensionRequest) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{1} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ExtensionRequest) GetContainingType() string { + if x != nil { + return x.ContainingType + } + return "" +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ExtensionRequest) GetExtensionNumber() int32 { + if x != nil { + return x.ExtensionNumber + } + return 0 +} + +// The message sent by the server to answer ServerReflectionInfo method. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type ServerReflectionResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ValidHost string `protobuf:"bytes,1,opt,name=valid_host,json=validHost,proto3" json:"valid_host,omitempty"` + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + OriginalRequest *ServerReflectionRequest `protobuf:"bytes,2,opt,name=original_request,json=originalRequest,proto3" json:"original_request,omitempty"` + // The server set one of the following fields according to the message_request + // in the request. + // + // Types that are assignable to MessageResponse: + // + // *ServerReflectionResponse_FileDescriptorResponse + // *ServerReflectionResponse_AllExtensionNumbersResponse + // *ServerReflectionResponse_ListServicesResponse + // *ServerReflectionResponse_ErrorResponse + MessageResponse isServerReflectionResponse_MessageResponse `protobuf_oneof:"message_response"` +} + +func (x *ServerReflectionResponse) Reset() { + *x = ServerReflectionResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServerReflectionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerReflectionResponse) ProtoMessage() {} + +func (x *ServerReflectionResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServerReflectionResponse.ProtoReflect.Descriptor instead. +func (*ServerReflectionResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{2} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionResponse) GetValidHost() string { + if x != nil { + return x.ValidHost + } + return "" +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionResponse) GetOriginalRequest() *ServerReflectionRequest { + if x != nil { + return x.OriginalRequest + } + return nil +} + +func (m *ServerReflectionResponse) GetMessageResponse() isServerReflectionResponse_MessageResponse { + if m != nil { + return m.MessageResponse + } + return nil +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionResponse) GetFileDescriptorResponse() *FileDescriptorResponse { + if x, ok := x.GetMessageResponse().(*ServerReflectionResponse_FileDescriptorResponse); ok { + return x.FileDescriptorResponse + } + return nil +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionResponse) GetAllExtensionNumbersResponse() *ExtensionNumberResponse { + if x, ok := x.GetMessageResponse().(*ServerReflectionResponse_AllExtensionNumbersResponse); ok { + return x.AllExtensionNumbersResponse + } + return nil +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionResponse) GetListServicesResponse() *ListServiceResponse { + if x, ok := x.GetMessageResponse().(*ServerReflectionResponse_ListServicesResponse); ok { + return x.ListServicesResponse + } + return nil +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionResponse) GetErrorResponse() *ErrorResponse { + if x, ok := x.GetMessageResponse().(*ServerReflectionResponse_ErrorResponse); ok { + return x.ErrorResponse + } + return nil +} + +type isServerReflectionResponse_MessageResponse interface { + isServerReflectionResponse_MessageResponse() +} + +type ServerReflectionResponse_FileDescriptorResponse struct { + // This message is used to answer file_by_filename, file_containing_symbol, + // file_containing_extension requests with transitive dependencies. As + // the repeated label is not allowed in oneof fields, we use a + // FileDescriptorResponse message to encapsulate the repeated fields. + // The reflection service is allowed to avoid sending FileDescriptorProtos + // that were previously sent in response to earlier requests in the stream. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + FileDescriptorResponse *FileDescriptorResponse `protobuf:"bytes,4,opt,name=file_descriptor_response,json=fileDescriptorResponse,proto3,oneof"` +} + +type ServerReflectionResponse_AllExtensionNumbersResponse struct { + // This message is used to answer all_extension_numbers_of_type requst. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + AllExtensionNumbersResponse *ExtensionNumberResponse `protobuf:"bytes,5,opt,name=all_extension_numbers_response,json=allExtensionNumbersResponse,proto3,oneof"` +} + +type ServerReflectionResponse_ListServicesResponse struct { + // This message is used to answer list_services request. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ListServicesResponse *ListServiceResponse `protobuf:"bytes,6,opt,name=list_services_response,json=listServicesResponse,proto3,oneof"` +} + +type ServerReflectionResponse_ErrorResponse struct { + // This message is used when an error occurs. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ErrorResponse *ErrorResponse `protobuf:"bytes,7,opt,name=error_response,json=errorResponse,proto3,oneof"` +} + +func (*ServerReflectionResponse_FileDescriptorResponse) isServerReflectionResponse_MessageResponse() { +} + +func (*ServerReflectionResponse_AllExtensionNumbersResponse) isServerReflectionResponse_MessageResponse() { +} + +func (*ServerReflectionResponse_ListServicesResponse) isServerReflectionResponse_MessageResponse() {} + +func (*ServerReflectionResponse_ErrorResponse) isServerReflectionResponse_MessageResponse() {} + +// Serialized FileDescriptorProto messages sent by the server answering +// a file_by_filename, file_containing_symbol, or file_containing_extension +// request. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type FileDescriptorResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Serialized FileDescriptorProto messages. We avoid taking a dependency on + // descriptor.proto, which uses proto2 only features, by making them opaque + // bytes instead. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + FileDescriptorProto [][]byte `protobuf:"bytes,1,rep,name=file_descriptor_proto,json=fileDescriptorProto,proto3" json:"file_descriptor_proto,omitempty"` +} + +func (x *FileDescriptorResponse) Reset() { + *x = FileDescriptorResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FileDescriptorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FileDescriptorResponse) ProtoMessage() {} + +func (x *FileDescriptorResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FileDescriptorResponse.ProtoReflect.Descriptor instead. +func (*FileDescriptorResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{3} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *FileDescriptorResponse) GetFileDescriptorProto() [][]byte { + if x != nil { + return x.FileDescriptorProto + } + return nil +} + +// A list of extension numbers sent by the server answering +// all_extension_numbers_of_type request. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type ExtensionNumberResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Full name of the base type, including the package name. The format + // is . + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + BaseTypeName string `protobuf:"bytes,1,opt,name=base_type_name,json=baseTypeName,proto3" json:"base_type_name,omitempty"` + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ExtensionNumber []int32 `protobuf:"varint,2,rep,packed,name=extension_number,json=extensionNumber,proto3" json:"extension_number,omitempty"` +} + +func (x *ExtensionNumberResponse) Reset() { + *x = ExtensionNumberResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExtensionNumberResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtensionNumberResponse) ProtoMessage() {} + +func (x *ExtensionNumberResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtensionNumberResponse.ProtoReflect.Descriptor instead. +func (*ExtensionNumberResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{4} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ExtensionNumberResponse) GetBaseTypeName() string { + if x != nil { + return x.BaseTypeName + } + return "" +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ExtensionNumberResponse) GetExtensionNumber() []int32 { + if x != nil { + return x.ExtensionNumber + } + return nil +} + +// A list of ServiceResponse sent by the server answering list_services request. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type ListServiceResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The information of each service may be expanded in the future, so we use + // ServiceResponse message to encapsulate it. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + Service []*ServiceResponse `protobuf:"bytes,1,rep,name=service,proto3" json:"service,omitempty"` +} + +func (x *ListServiceResponse) Reset() { + *x = ListServiceResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListServiceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListServiceResponse) ProtoMessage() {} + +func (x *ListServiceResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListServiceResponse.ProtoReflect.Descriptor instead. +func (*ListServiceResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{5} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ListServiceResponse) GetService() []*ServiceResponse { + if x != nil { + return x.Service + } + return nil +} + +// The information of a single service used by ListServiceResponse to answer +// list_services request. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type ServiceResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Full name of a registered service, including its package name. The format + // is . + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *ServiceResponse) Reset() { + *x = ServiceResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServiceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServiceResponse) ProtoMessage() {} + +func (x *ServiceResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServiceResponse.ProtoReflect.Descriptor instead. +func (*ServiceResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{6} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServiceResponse) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +// The error code and error message sent by the server when an error occurs. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type ErrorResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // This field uses the error codes defined in grpc::StatusCode. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ErrorCode int32 `protobuf:"varint,1,opt,name=error_code,json=errorCode,proto3" json:"error_code,omitempty"` + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ErrorMessage string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` +} + +func (x *ErrorResponse) Reset() { + *x = ErrorResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ErrorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ErrorResponse) ProtoMessage() {} + +func (x *ErrorResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ErrorResponse.ProtoReflect.Descriptor instead. +func (*ErrorResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{7} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ErrorResponse) GetErrorCode() int32 { + if x != nil { + return x.ErrorCode + } + return 0 +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ErrorResponse) GetErrorMessage() string { + if x != nil { + return x.ErrorMessage + } + return "" +} + +var File_grpc_reflection_v1alpha_reflection_proto protoreflect.FileDescriptor + +var file_grpc_reflection_v1alpha_reflection_proto_rawDesc = []byte{ + 0x0a, 0x28, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x22, 0xf8, 0x02, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, + 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, + 0x6f, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x62, 0x79, 0x5f, 0x66, + 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, + 0x0e, 0x66, 0x69, 0x6c, 0x65, 0x42, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x36, 0x0a, 0x16, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, + 0x6e, 0x67, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x00, 0x52, 0x14, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, + 0x67, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x12, 0x67, 0x0a, 0x19, 0x66, 0x69, 0x6c, 0x65, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x17, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x42, 0x0a, 0x1d, 0x61, 0x6c, 0x6c, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, + 0x6e, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x19, 0x61, 0x6c, 0x6c, 0x45, 0x78, + 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x4f, 0x66, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x0d, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x6c, + 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x42, 0x11, 0x0a, 0x0f, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x66, + 0x0a, 0x10, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x65, + 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, + 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0xc7, 0x04, 0x0a, 0x18, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x68, 0x6f, 0x73, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x48, 0x6f, + 0x73, 0x74, 0x12, 0x5b, 0x0a, 0x10, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x67, + 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, + 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0f, + 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x6b, 0x0a, 0x18, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x46, 0x69, 0x6c, 0x65, + 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x48, 0x00, 0x52, 0x16, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x1e, + 0x61, 0x6c, 0x6c, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, + 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x1b, 0x61, 0x6c, 0x6c, 0x45, 0x78, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, 0x0a, 0x16, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, + 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x14, 0x6c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0e, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0d, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x12, 0x0a, 0x10, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x4c, 0x0a, 0x16, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x66, 0x69, + 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x13, 0x66, 0x69, 0x6c, 0x65, 0x44, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6a, + 0x0a, 0x17, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x61, 0x73, + 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x62, 0x61, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x29, 0x0a, 0x10, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x59, 0x0a, 0x13, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x42, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x07, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x25, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x53, 0x0a, 0x0d, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, + 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x32, 0x93, 0x01, 0x0a, 0x10, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, 0x6c, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x7f, 0x0a, 0x14, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x30, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, + 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x73, 0x0a, 0x1a, 0x69, 0x6f, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x42, 0x15, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x66, + 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x39, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, + 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0xb8, 0x01, 0x01, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_grpc_reflection_v1alpha_reflection_proto_rawDescOnce sync.Once + file_grpc_reflection_v1alpha_reflection_proto_rawDescData = file_grpc_reflection_v1alpha_reflection_proto_rawDesc +) + +func file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP() []byte { + file_grpc_reflection_v1alpha_reflection_proto_rawDescOnce.Do(func() { + file_grpc_reflection_v1alpha_reflection_proto_rawDescData = protoimpl.X.CompressGZIP(file_grpc_reflection_v1alpha_reflection_proto_rawDescData) + }) + return file_grpc_reflection_v1alpha_reflection_proto_rawDescData +} + +var file_grpc_reflection_v1alpha_reflection_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_grpc_reflection_v1alpha_reflection_proto_goTypes = []interface{}{ + (*ServerReflectionRequest)(nil), // 0: grpc.reflection.v1alpha.ServerReflectionRequest + (*ExtensionRequest)(nil), // 1: grpc.reflection.v1alpha.ExtensionRequest + (*ServerReflectionResponse)(nil), // 2: grpc.reflection.v1alpha.ServerReflectionResponse + (*FileDescriptorResponse)(nil), // 3: grpc.reflection.v1alpha.FileDescriptorResponse + (*ExtensionNumberResponse)(nil), // 4: grpc.reflection.v1alpha.ExtensionNumberResponse + (*ListServiceResponse)(nil), // 5: grpc.reflection.v1alpha.ListServiceResponse + (*ServiceResponse)(nil), // 6: grpc.reflection.v1alpha.ServiceResponse + (*ErrorResponse)(nil), // 7: grpc.reflection.v1alpha.ErrorResponse +} +var file_grpc_reflection_v1alpha_reflection_proto_depIdxs = []int32{ + 1, // 0: grpc.reflection.v1alpha.ServerReflectionRequest.file_containing_extension:type_name -> grpc.reflection.v1alpha.ExtensionRequest + 0, // 1: grpc.reflection.v1alpha.ServerReflectionResponse.original_request:type_name -> grpc.reflection.v1alpha.ServerReflectionRequest + 3, // 2: grpc.reflection.v1alpha.ServerReflectionResponse.file_descriptor_response:type_name -> grpc.reflection.v1alpha.FileDescriptorResponse + 4, // 3: grpc.reflection.v1alpha.ServerReflectionResponse.all_extension_numbers_response:type_name -> grpc.reflection.v1alpha.ExtensionNumberResponse + 5, // 4: grpc.reflection.v1alpha.ServerReflectionResponse.list_services_response:type_name -> grpc.reflection.v1alpha.ListServiceResponse + 7, // 5: grpc.reflection.v1alpha.ServerReflectionResponse.error_response:type_name -> grpc.reflection.v1alpha.ErrorResponse + 6, // 6: grpc.reflection.v1alpha.ListServiceResponse.service:type_name -> grpc.reflection.v1alpha.ServiceResponse + 0, // 7: grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo:input_type -> grpc.reflection.v1alpha.ServerReflectionRequest + 2, // 8: grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo:output_type -> grpc.reflection.v1alpha.ServerReflectionResponse + 8, // [8:9] is the sub-list for method output_type + 7, // [7:8] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name +} + +func init() { file_grpc_reflection_v1alpha_reflection_proto_init() } +func file_grpc_reflection_v1alpha_reflection_proto_init() { + if File_grpc_reflection_v1alpha_reflection_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_grpc_reflection_v1alpha_reflection_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ServerReflectionRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_reflection_v1alpha_reflection_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExtensionRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_reflection_v1alpha_reflection_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ServerReflectionResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_reflection_v1alpha_reflection_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FileDescriptorResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_reflection_v1alpha_reflection_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExtensionNumberResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_reflection_v1alpha_reflection_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListServiceResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_reflection_v1alpha_reflection_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ServiceResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_grpc_reflection_v1alpha_reflection_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ErrorResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_grpc_reflection_v1alpha_reflection_proto_msgTypes[0].OneofWrappers = []interface{}{ + (*ServerReflectionRequest_FileByFilename)(nil), + (*ServerReflectionRequest_FileContainingSymbol)(nil), + (*ServerReflectionRequest_FileContainingExtension)(nil), + (*ServerReflectionRequest_AllExtensionNumbersOfType)(nil), + (*ServerReflectionRequest_ListServices)(nil), + } + file_grpc_reflection_v1alpha_reflection_proto_msgTypes[2].OneofWrappers = []interface{}{ + (*ServerReflectionResponse_FileDescriptorResponse)(nil), + (*ServerReflectionResponse_AllExtensionNumbersResponse)(nil), + (*ServerReflectionResponse_ListServicesResponse)(nil), + (*ServerReflectionResponse_ErrorResponse)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_grpc_reflection_v1alpha_reflection_proto_rawDesc, + NumEnums: 0, + NumMessages: 8, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_grpc_reflection_v1alpha_reflection_proto_goTypes, + DependencyIndexes: file_grpc_reflection_v1alpha_reflection_proto_depIdxs, + MessageInfos: file_grpc_reflection_v1alpha_reflection_proto_msgTypes, + }.Build() + File_grpc_reflection_v1alpha_reflection_proto = out.File + file_grpc_reflection_v1alpha_reflection_proto_rawDesc = nil + file_grpc_reflection_v1alpha_reflection_proto_goTypes = nil + file_grpc_reflection_v1alpha_reflection_proto_depIdxs = nil +} diff --git a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go new file mode 100644 index 0000000000..ef69140635 --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go @@ -0,0 +1,161 @@ +// Copyright 2016 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// Service exported by server reflection + +// Warning: this entire file is deprecated. Use this instead: +// https://github.com/grpc/grpc-proto/blob/master/grpc/reflection/v1/reflection.proto + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v4.25.2 +// grpc/reflection/v1alpha/reflection.proto is a deprecated file. + +package grpc_reflection_v1alpha + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + ServerReflection_ServerReflectionInfo_FullMethodName = "/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo" +) + +// ServerReflectionClient is the client API for ServerReflection service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type ServerReflectionClient interface { + // The reflection service is structured as a bidirectional stream, ensuring + // all related requests go to a single server. + ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (ServerReflection_ServerReflectionInfoClient, error) +} + +type serverReflectionClient struct { + cc grpc.ClientConnInterface +} + +func NewServerReflectionClient(cc grpc.ClientConnInterface) ServerReflectionClient { + return &serverReflectionClient{cc} +} + +func (c *serverReflectionClient) ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (ServerReflection_ServerReflectionInfoClient, error) { + stream, err := c.cc.NewStream(ctx, &ServerReflection_ServiceDesc.Streams[0], ServerReflection_ServerReflectionInfo_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &serverReflectionServerReflectionInfoClient{stream} + return x, nil +} + +type ServerReflection_ServerReflectionInfoClient interface { + Send(*ServerReflectionRequest) error + Recv() (*ServerReflectionResponse, error) + grpc.ClientStream +} + +type serverReflectionServerReflectionInfoClient struct { + grpc.ClientStream +} + +func (x *serverReflectionServerReflectionInfoClient) Send(m *ServerReflectionRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *serverReflectionServerReflectionInfoClient) Recv() (*ServerReflectionResponse, error) { + m := new(ServerReflectionResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// ServerReflectionServer is the server API for ServerReflection service. +// All implementations should embed UnimplementedServerReflectionServer +// for forward compatibility +type ServerReflectionServer interface { + // The reflection service is structured as a bidirectional stream, ensuring + // all related requests go to a single server. + ServerReflectionInfo(ServerReflection_ServerReflectionInfoServer) error +} + +// UnimplementedServerReflectionServer should be embedded to have forward compatible implementations. +type UnimplementedServerReflectionServer struct { +} + +func (UnimplementedServerReflectionServer) ServerReflectionInfo(ServerReflection_ServerReflectionInfoServer) error { + return status.Errorf(codes.Unimplemented, "method ServerReflectionInfo not implemented") +} + +// UnsafeServerReflectionServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ServerReflectionServer will +// result in compilation errors. +type UnsafeServerReflectionServer interface { + mustEmbedUnimplementedServerReflectionServer() +} + +func RegisterServerReflectionServer(s grpc.ServiceRegistrar, srv ServerReflectionServer) { + s.RegisterService(&ServerReflection_ServiceDesc, srv) +} + +func _ServerReflection_ServerReflectionInfo_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(ServerReflectionServer).ServerReflectionInfo(&serverReflectionServerReflectionInfoServer{stream}) +} + +type ServerReflection_ServerReflectionInfoServer interface { + Send(*ServerReflectionResponse) error + Recv() (*ServerReflectionRequest, error) + grpc.ServerStream +} + +type serverReflectionServerReflectionInfoServer struct { + grpc.ServerStream +} + +func (x *serverReflectionServerReflectionInfoServer) Send(m *ServerReflectionResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *serverReflectionServerReflectionInfoServer) Recv() (*ServerReflectionRequest, error) { + m := new(ServerReflectionRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// ServerReflection_ServiceDesc is the grpc.ServiceDesc for ServerReflection service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ServerReflection_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "grpc.reflection.v1alpha.ServerReflection", + HandlerType: (*ServerReflectionServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "ServerReflectionInfo", + Handler: _ServerReflection_ServerReflectionInfo_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "grpc/reflection/v1alpha/reflection.proto", +} diff --git a/vendor/google.golang.org/grpc/reflection/serverreflection.go b/vendor/google.golang.org/grpc/reflection/serverreflection.go new file mode 100644 index 0000000000..c3b408392f --- /dev/null +++ b/vendor/google.golang.org/grpc/reflection/serverreflection.go @@ -0,0 +1,360 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/* +Package reflection implements server reflection service. + +The service implemented is defined in: +https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto. + +To register server reflection on a gRPC server: + + import "google.golang.org/grpc/reflection" + + s := grpc.NewServer() + pb.RegisterYourOwnServer(s, &server{}) + + // Register reflection service on gRPC server. + reflection.Register(s) + + s.Serve(lis) +*/ +package reflection // import "google.golang.org/grpc/reflection" + +import ( + "io" + "sort" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protodesc" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" + + v1reflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1" + v1reflectionpb "google.golang.org/grpc/reflection/grpc_reflection_v1" + v1alphareflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" +) + +// GRPCServer is the interface provided by a gRPC server. It is implemented by +// *grpc.Server, but could also be implemented by other concrete types. It acts +// as a registry, for accumulating the services exposed by the server. +type GRPCServer interface { + grpc.ServiceRegistrar + ServiceInfoProvider +} + +var _ GRPCServer = (*grpc.Server)(nil) + +// Register registers the server reflection service on the given gRPC server. +// Both the v1 and v1alpha versions are registered. +func Register(s GRPCServer) { + svr := NewServerV1(ServerOptions{Services: s}) + v1alphareflectiongrpc.RegisterServerReflectionServer(s, asV1Alpha(svr)) + v1reflectiongrpc.RegisterServerReflectionServer(s, svr) +} + +// RegisterV1 registers only the v1 version of the server reflection service +// on the given gRPC server. Many clients may only support v1alpha so most +// users should use Register instead, at least until clients have upgraded. +func RegisterV1(s GRPCServer) { + svr := NewServerV1(ServerOptions{Services: s}) + v1reflectiongrpc.RegisterServerReflectionServer(s, svr) +} + +// ServiceInfoProvider is an interface used to retrieve metadata about the +// services to expose. +// +// The reflection service is only interested in the service names, but the +// signature is this way so that *grpc.Server implements it. So it is okay +// for a custom implementation to return zero values for the +// grpc.ServiceInfo values in the map. +// +// # Experimental +// +// Notice: This type is EXPERIMENTAL and may be changed or removed in a +// later release. +type ServiceInfoProvider interface { + GetServiceInfo() map[string]grpc.ServiceInfo +} + +// ExtensionResolver is the interface used to query details about extensions. +// This interface is satisfied by protoregistry.GlobalTypes. +// +// # Experimental +// +// Notice: This type is EXPERIMENTAL and may be changed or removed in a +// later release. +type ExtensionResolver interface { + protoregistry.ExtensionTypeResolver + RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool) +} + +// ServerOptions represents the options used to construct a reflection server. +// +// # Experimental +// +// Notice: This type is EXPERIMENTAL and may be changed or removed in a +// later release. +type ServerOptions struct { + // The source of advertised RPC services. If not specified, the reflection + // server will report an empty list when asked to list services. + // + // This value will typically be a *grpc.Server. But the set of advertised + // services can be customized by wrapping a *grpc.Server or using an + // alternate implementation that returns a custom set of service names. + Services ServiceInfoProvider + // Optional resolver used to load descriptors. If not specified, + // protoregistry.GlobalFiles will be used. + DescriptorResolver protodesc.Resolver + // Optional resolver used to query for known extensions. If not specified, + // protoregistry.GlobalTypes will be used. + ExtensionResolver ExtensionResolver +} + +// NewServer returns a reflection server implementation using the given options. +// This can be used to customize behavior of the reflection service. Most usages +// should prefer to use Register instead. For backwards compatibility reasons, +// this returns the v1alpha version of the reflection server. For a v1 version +// of the reflection server, see NewServerV1. +// +// # Experimental +// +// Notice: This function is EXPERIMENTAL and may be changed or removed in a +// later release. +func NewServer(opts ServerOptions) v1alphareflectiongrpc.ServerReflectionServer { + return asV1Alpha(NewServerV1(opts)) +} + +// NewServerV1 returns a reflection server implementation using the given options. +// This can be used to customize behavior of the reflection service. Most usages +// should prefer to use Register instead. +// +// # Experimental +// +// Notice: This function is EXPERIMENTAL and may be changed or removed in a +// later release. +func NewServerV1(opts ServerOptions) v1reflectiongrpc.ServerReflectionServer { + if opts.DescriptorResolver == nil { + opts.DescriptorResolver = protoregistry.GlobalFiles + } + if opts.ExtensionResolver == nil { + opts.ExtensionResolver = protoregistry.GlobalTypes + } + return &serverReflectionServer{ + s: opts.Services, + descResolver: opts.DescriptorResolver, + extResolver: opts.ExtensionResolver, + } +} + +type serverReflectionServer struct { + v1alphareflectiongrpc.UnimplementedServerReflectionServer + s ServiceInfoProvider + descResolver protodesc.Resolver + extResolver ExtensionResolver +} + +// fileDescWithDependencies returns a slice of serialized fileDescriptors in +// wire format ([]byte). The fileDescriptors will include fd and all the +// transitive dependencies of fd with names not in sentFileDescriptors. +func (s *serverReflectionServer) fileDescWithDependencies(fd protoreflect.FileDescriptor, sentFileDescriptors map[string]bool) ([][]byte, error) { + if fd.IsPlaceholder() { + // If the given root file is a placeholder, treat it + // as missing instead of serializing it. + return nil, protoregistry.NotFound + } + var r [][]byte + queue := []protoreflect.FileDescriptor{fd} + for len(queue) > 0 { + currentfd := queue[0] + queue = queue[1:] + if currentfd.IsPlaceholder() { + // Skip any missing files in the dependency graph. + continue + } + if sent := sentFileDescriptors[currentfd.Path()]; len(r) == 0 || !sent { + sentFileDescriptors[currentfd.Path()] = true + fdProto := protodesc.ToFileDescriptorProto(currentfd) + currentfdEncoded, err := proto.Marshal(fdProto) + if err != nil { + return nil, err + } + r = append(r, currentfdEncoded) + } + for i := 0; i < currentfd.Imports().Len(); i++ { + queue = append(queue, currentfd.Imports().Get(i)) + } + } + return r, nil +} + +// fileDescEncodingContainingSymbol finds the file descriptor containing the +// given symbol, finds all of its previously unsent transitive dependencies, +// does marshalling on them, and returns the marshalled result. The given symbol +// can be a type, a service or a method. +func (s *serverReflectionServer) fileDescEncodingContainingSymbol(name string, sentFileDescriptors map[string]bool) ([][]byte, error) { + d, err := s.descResolver.FindDescriptorByName(protoreflect.FullName(name)) + if err != nil { + return nil, err + } + return s.fileDescWithDependencies(d.ParentFile(), sentFileDescriptors) +} + +// fileDescEncodingContainingExtension finds the file descriptor containing +// given extension, finds all of its previously unsent transitive dependencies, +// does marshalling on them, and returns the marshalled result. +func (s *serverReflectionServer) fileDescEncodingContainingExtension(typeName string, extNum int32, sentFileDescriptors map[string]bool) ([][]byte, error) { + xt, err := s.extResolver.FindExtensionByNumber(protoreflect.FullName(typeName), protoreflect.FieldNumber(extNum)) + if err != nil { + return nil, err + } + return s.fileDescWithDependencies(xt.TypeDescriptor().ParentFile(), sentFileDescriptors) +} + +// allExtensionNumbersForTypeName returns all extension numbers for the given type. +func (s *serverReflectionServer) allExtensionNumbersForTypeName(name string) ([]int32, error) { + var numbers []int32 + s.extResolver.RangeExtensionsByMessage(protoreflect.FullName(name), func(xt protoreflect.ExtensionType) bool { + numbers = append(numbers, int32(xt.TypeDescriptor().Number())) + return true + }) + sort.Slice(numbers, func(i, j int) bool { + return numbers[i] < numbers[j] + }) + if len(numbers) == 0 { + // maybe return an error if given type name is not known + if _, err := s.descResolver.FindDescriptorByName(protoreflect.FullName(name)); err != nil { + return nil, err + } + } + return numbers, nil +} + +// listServices returns the names of services this server exposes. +func (s *serverReflectionServer) listServices() []*v1reflectionpb.ServiceResponse { + serviceInfo := s.s.GetServiceInfo() + resp := make([]*v1reflectionpb.ServiceResponse, 0, len(serviceInfo)) + for svc := range serviceInfo { + resp = append(resp, &v1reflectionpb.ServiceResponse{Name: svc}) + } + sort.Slice(resp, func(i, j int) bool { + return resp[i].Name < resp[j].Name + }) + return resp +} + +// ServerReflectionInfo is the reflection service handler. +func (s *serverReflectionServer) ServerReflectionInfo(stream v1reflectiongrpc.ServerReflection_ServerReflectionInfoServer) error { + sentFileDescriptors := make(map[string]bool) + for { + in, err := stream.Recv() + if err == io.EOF { + return nil + } + if err != nil { + return err + } + + out := &v1reflectionpb.ServerReflectionResponse{ + ValidHost: in.Host, + OriginalRequest: in, + } + switch req := in.MessageRequest.(type) { + case *v1reflectionpb.ServerReflectionRequest_FileByFilename: + var b [][]byte + fd, err := s.descResolver.FindFileByPath(req.FileByFilename) + if err == nil { + b, err = s.fileDescWithDependencies(fd, sentFileDescriptors) + } + if err != nil { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{ + ErrorResponse: &v1reflectionpb.ErrorResponse{ + ErrorCode: int32(codes.NotFound), + ErrorMessage: err.Error(), + }, + } + } else { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse{ + FileDescriptorResponse: &v1reflectionpb.FileDescriptorResponse{FileDescriptorProto: b}, + } + } + case *v1reflectionpb.ServerReflectionRequest_FileContainingSymbol: + b, err := s.fileDescEncodingContainingSymbol(req.FileContainingSymbol, sentFileDescriptors) + if err != nil { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{ + ErrorResponse: &v1reflectionpb.ErrorResponse{ + ErrorCode: int32(codes.NotFound), + ErrorMessage: err.Error(), + }, + } + } else { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse{ + FileDescriptorResponse: &v1reflectionpb.FileDescriptorResponse{FileDescriptorProto: b}, + } + } + case *v1reflectionpb.ServerReflectionRequest_FileContainingExtension: + typeName := req.FileContainingExtension.ContainingType + extNum := req.FileContainingExtension.ExtensionNumber + b, err := s.fileDescEncodingContainingExtension(typeName, extNum, sentFileDescriptors) + if err != nil { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{ + ErrorResponse: &v1reflectionpb.ErrorResponse{ + ErrorCode: int32(codes.NotFound), + ErrorMessage: err.Error(), + }, + } + } else { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse{ + FileDescriptorResponse: &v1reflectionpb.FileDescriptorResponse{FileDescriptorProto: b}, + } + } + case *v1reflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType: + extNums, err := s.allExtensionNumbersForTypeName(req.AllExtensionNumbersOfType) + if err != nil { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{ + ErrorResponse: &v1reflectionpb.ErrorResponse{ + ErrorCode: int32(codes.NotFound), + ErrorMessage: err.Error(), + }, + } + } else { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse{ + AllExtensionNumbersResponse: &v1reflectionpb.ExtensionNumberResponse{ + BaseTypeName: req.AllExtensionNumbersOfType, + ExtensionNumber: extNums, + }, + } + } + case *v1reflectionpb.ServerReflectionRequest_ListServices: + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ListServicesResponse{ + ListServicesResponse: &v1reflectionpb.ListServiceResponse{ + Service: s.listServices(), + }, + } + default: + return status.Errorf(codes.InvalidArgument, "invalid MessageRequest: %v", in.MessageRequest) + } + + if err := stream.Send(out); err != nil { + return err + } + } +} diff --git a/vendor/gopkg.in/warnings.v0/LICENSE b/vendor/gopkg.in/warnings.v0/LICENSE new file mode 100644 index 0000000000..d65f7e9d8c --- /dev/null +++ b/vendor/gopkg.in/warnings.v0/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2016 Péter Surányi. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/gopkg.in/warnings.v0/README b/vendor/gopkg.in/warnings.v0/README new file mode 100644 index 0000000000..974212ba1b --- /dev/null +++ b/vendor/gopkg.in/warnings.v0/README @@ -0,0 +1,77 @@ +Package warnings implements error handling with non-fatal errors (warnings). + +import path: "gopkg.in/warnings.v0" +package docs: https://godoc.org/gopkg.in/warnings.v0 +issues: https://github.com/go-warnings/warnings/issues +pull requests: https://github.com/go-warnings/warnings/pulls + +A recurring pattern in Go programming is the following: + + func myfunc(params) error { + if err := doSomething(...); err != nil { + return err + } + if err := doSomethingElse(...); err != nil { + return err + } + if ok := doAnotherThing(...); !ok { + return errors.New("my error") + } + ... + return nil + } + +This pattern allows interrupting the flow on any received error. But what if +there are errors that should be noted but still not fatal, for which the flow +should not be interrupted? Implementing such logic at each if statement would +make the code complex and the flow much harder to follow. + +Package warnings provides the Collector type and a clean and simple pattern +for achieving such logic. The Collector takes care of deciding when to break +the flow and when to continue, collecting any non-fatal errors (warnings) +along the way. The only requirement is that fatal and non-fatal errors can be +distinguished programmatically; that is a function such as + + IsFatal(error) bool + +must be implemented. The following is an example of what the above snippet +could look like using the warnings package: + + import "gopkg.in/warnings.v0" + + func isFatal(err error) bool { + _, ok := err.(WarningType) + return !ok + } + + func myfunc(params) error { + c := warnings.NewCollector(isFatal) + c.FatalWithWarnings = true + if err := c.Collect(doSomething()); err != nil { + return err + } + if err := c.Collect(doSomethingElse(...)); err != nil { + return err + } + if ok := doAnotherThing(...); !ok { + if err := c.Collect(errors.New("my error")); err != nil { + return err + } + } + ... + return c.Done() + } + +For an example of a non-trivial code base using this library, see +gopkg.in/gcfg.v1 + +Rules for using warnings + + - ensure that warnings are programmatically distinguishable from fatal + errors (i.e. implement an isFatal function and any necessary error types) + - ensure that there is a single Collector instance for a call of each + exported function + - ensure that all errors (fatal or warning) are fed through Collect + - ensure that every time an error is returned, it is one returned by a + Collector (from Collect or Done) + - ensure that Collect is never called after Done diff --git a/vendor/gopkg.in/warnings.v0/warnings.go b/vendor/gopkg.in/warnings.v0/warnings.go new file mode 100644 index 0000000000..b849d1e3d9 --- /dev/null +++ b/vendor/gopkg.in/warnings.v0/warnings.go @@ -0,0 +1,194 @@ +// Package warnings implements error handling with non-fatal errors (warnings). +// +// A recurring pattern in Go programming is the following: +// +// func myfunc(params) error { +// if err := doSomething(...); err != nil { +// return err +// } +// if err := doSomethingElse(...); err != nil { +// return err +// } +// if ok := doAnotherThing(...); !ok { +// return errors.New("my error") +// } +// ... +// return nil +// } +// +// This pattern allows interrupting the flow on any received error. But what if +// there are errors that should be noted but still not fatal, for which the flow +// should not be interrupted? Implementing such logic at each if statement would +// make the code complex and the flow much harder to follow. +// +// Package warnings provides the Collector type and a clean and simple pattern +// for achieving such logic. The Collector takes care of deciding when to break +// the flow and when to continue, collecting any non-fatal errors (warnings) +// along the way. The only requirement is that fatal and non-fatal errors can be +// distinguished programmatically; that is a function such as +// +// IsFatal(error) bool +// +// must be implemented. The following is an example of what the above snippet +// could look like using the warnings package: +// +// import "gopkg.in/warnings.v0" +// +// func isFatal(err error) bool { +// _, ok := err.(WarningType) +// return !ok +// } +// +// func myfunc(params) error { +// c := warnings.NewCollector(isFatal) +// c.FatalWithWarnings = true +// if err := c.Collect(doSomething()); err != nil { +// return err +// } +// if err := c.Collect(doSomethingElse(...)); err != nil { +// return err +// } +// if ok := doAnotherThing(...); !ok { +// if err := c.Collect(errors.New("my error")); err != nil { +// return err +// } +// } +// ... +// return c.Done() +// } +// +// For an example of a non-trivial code base using this library, see +// gopkg.in/gcfg.v1 +// +// Rules for using warnings +// +// - ensure that warnings are programmatically distinguishable from fatal +// errors (i.e. implement an isFatal function and any necessary error types) +// - ensure that there is a single Collector instance for a call of each +// exported function +// - ensure that all errors (fatal or warning) are fed through Collect +// - ensure that every time an error is returned, it is one returned by a +// Collector (from Collect or Done) +// - ensure that Collect is never called after Done +// +// TODO +// +// - optionally limit the number of warnings (e.g. stop after 20 warnings) (?) +// - consider interaction with contexts +// - go vet-style invocations verifier +// - semi-automatic code converter +// +package warnings // import "gopkg.in/warnings.v0" + +import ( + "bytes" + "fmt" +) + +// List holds a collection of warnings and optionally one fatal error. +type List struct { + Warnings []error + Fatal error +} + +// Error implements the error interface. +func (l List) Error() string { + b := bytes.NewBuffer(nil) + if l.Fatal != nil { + fmt.Fprintln(b, "fatal:") + fmt.Fprintln(b, l.Fatal) + } + switch len(l.Warnings) { + case 0: + // nop + case 1: + fmt.Fprintln(b, "warning:") + default: + fmt.Fprintln(b, "warnings:") + } + for _, err := range l.Warnings { + fmt.Fprintln(b, err) + } + return b.String() +} + +// A Collector collects errors up to the first fatal error. +type Collector struct { + // IsFatal distinguishes between warnings and fatal errors. + IsFatal func(error) bool + // FatalWithWarnings set to true means that a fatal error is returned as + // a List together with all warnings so far. The default behavior is to + // only return the fatal error and discard any warnings that have been + // collected. + FatalWithWarnings bool + + l List + done bool +} + +// NewCollector returns a new Collector; it uses isFatal to distinguish between +// warnings and fatal errors. +func NewCollector(isFatal func(error) bool) *Collector { + return &Collector{IsFatal: isFatal} +} + +// Collect collects a single error (warning or fatal). It returns nil if +// collection can continue (only warnings so far), or otherwise the errors +// collected. Collect mustn't be called after the first fatal error or after +// Done has been called. +func (c *Collector) Collect(err error) error { + if c.done { + panic("warnings.Collector already done") + } + if err == nil { + return nil + } + if c.IsFatal(err) { + c.done = true + c.l.Fatal = err + } else { + c.l.Warnings = append(c.l.Warnings, err) + } + if c.l.Fatal != nil { + return c.erorr() + } + return nil +} + +// Done ends collection and returns the collected error(s). +func (c *Collector) Done() error { + c.done = true + return c.erorr() +} + +func (c *Collector) erorr() error { + if !c.FatalWithWarnings && c.l.Fatal != nil { + return c.l.Fatal + } + if c.l.Fatal == nil && len(c.l.Warnings) == 0 { + return nil + } + // Note that a single warning is also returned as a List. This is to make it + // easier to determine fatal-ness of the returned error. + return c.l +} + +// FatalOnly returns the fatal error, if any, **in an error returned by a +// Collector**. It returns nil if and only if err is nil or err is a List +// with err.Fatal == nil. +func FatalOnly(err error) error { + l, ok := err.(List) + if !ok { + return err + } + return l.Fatal +} + +// WarningsOnly returns the warnings **in an error returned by a Collector**. +func WarningsOnly(err error) []error { + l, ok := err.(List) + if !ok { + return nil + } + return l.Warnings +} diff --git a/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/connection.go b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/connection.go new file mode 100644 index 0000000000..d4ceab84f0 --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/connection.go @@ -0,0 +1,204 @@ +/* +Copyright 2015 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package spdy + +import ( + "net" + "net/http" + "sync" + "time" + + "github.com/moby/spdystream" + "k8s.io/apimachinery/pkg/util/httpstream" + "k8s.io/klog/v2" +) + +// connection maintains state about a spdystream.Connection and its associated +// streams. +type connection struct { + conn *spdystream.Connection + streams map[uint32]httpstream.Stream + streamLock sync.Mutex + newStreamHandler httpstream.NewStreamHandler + ping func() (time.Duration, error) +} + +// NewClientConnection creates a new SPDY client connection. +func NewClientConnection(conn net.Conn) (httpstream.Connection, error) { + return NewClientConnectionWithPings(conn, 0) +} + +// NewClientConnectionWithPings creates a new SPDY client connection. +// +// If pingPeriod is non-zero, a background goroutine will send periodic Ping +// frames to the server. Use this to keep idle connections through certain load +// balancers alive longer. +func NewClientConnectionWithPings(conn net.Conn, pingPeriod time.Duration) (httpstream.Connection, error) { + spdyConn, err := spdystream.NewConnection(conn, false) + if err != nil { + defer conn.Close() + return nil, err + } + + return newConnection(spdyConn, httpstream.NoOpNewStreamHandler, pingPeriod, spdyConn.Ping), nil +} + +// NewServerConnection creates a new SPDY server connection. newStreamHandler +// will be invoked when the server receives a newly created stream from the +// client. +func NewServerConnection(conn net.Conn, newStreamHandler httpstream.NewStreamHandler) (httpstream.Connection, error) { + return NewServerConnectionWithPings(conn, newStreamHandler, 0) +} + +// NewServerConnectionWithPings creates a new SPDY server connection. +// newStreamHandler will be invoked when the server receives a newly created +// stream from the client. +// +// If pingPeriod is non-zero, a background goroutine will send periodic Ping +// frames to the server. Use this to keep idle connections through certain load +// balancers alive longer. +func NewServerConnectionWithPings(conn net.Conn, newStreamHandler httpstream.NewStreamHandler, pingPeriod time.Duration) (httpstream.Connection, error) { + spdyConn, err := spdystream.NewConnection(conn, true) + if err != nil { + defer conn.Close() + return nil, err + } + + return newConnection(spdyConn, newStreamHandler, pingPeriod, spdyConn.Ping), nil +} + +// newConnection returns a new connection wrapping conn. newStreamHandler +// will be invoked when the server receives a newly created stream from the +// client. +func newConnection(conn *spdystream.Connection, newStreamHandler httpstream.NewStreamHandler, pingPeriod time.Duration, pingFn func() (time.Duration, error)) httpstream.Connection { + c := &connection{ + conn: conn, + newStreamHandler: newStreamHandler, + ping: pingFn, + streams: make(map[uint32]httpstream.Stream), + } + go conn.Serve(c.newSpdyStream) + if pingPeriod > 0 && pingFn != nil { + go c.sendPings(pingPeriod) + } + return c +} + +// createStreamResponseTimeout indicates how long to wait for the other side to +// acknowledge the new stream before timing out. +const createStreamResponseTimeout = 30 * time.Second + +// Close first sends a reset for all of the connection's streams, and then +// closes the underlying spdystream.Connection. +func (c *connection) Close() error { + c.streamLock.Lock() + for _, s := range c.streams { + // calling Reset instead of Close ensures that all streams are fully torn down + s.Reset() + } + c.streams = make(map[uint32]httpstream.Stream, 0) + c.streamLock.Unlock() + + // now that all streams are fully torn down, it's safe to call close on the underlying connection, + // which should be able to terminate immediately at this point, instead of waiting for any + // remaining graceful stream termination. + return c.conn.Close() +} + +// RemoveStreams can be used to removes a set of streams from the Connection. +func (c *connection) RemoveStreams(streams ...httpstream.Stream) { + c.streamLock.Lock() + for _, stream := range streams { + // It may be possible that the provided stream is nil if timed out. + if stream != nil { + delete(c.streams, stream.Identifier()) + } + } + c.streamLock.Unlock() +} + +// CreateStream creates a new stream with the specified headers and registers +// it with the connection. +func (c *connection) CreateStream(headers http.Header) (httpstream.Stream, error) { + stream, err := c.conn.CreateStream(headers, nil, false) + if err != nil { + return nil, err + } + if err = stream.WaitTimeout(createStreamResponseTimeout); err != nil { + return nil, err + } + + c.registerStream(stream) + return stream, nil +} + +// registerStream adds the stream s to the connection's list of streams that +// it owns. +func (c *connection) registerStream(s httpstream.Stream) { + c.streamLock.Lock() + c.streams[s.Identifier()] = s + c.streamLock.Unlock() +} + +// CloseChan returns a channel that, when closed, indicates that the underlying +// spdystream.Connection has been closed. +func (c *connection) CloseChan() <-chan bool { + return c.conn.CloseChan() +} + +// newSpdyStream is the internal new stream handler used by spdystream.Connection.Serve. +// It calls connection's newStreamHandler, giving it the opportunity to accept or reject +// the stream. If newStreamHandler returns an error, the stream is rejected. If not, the +// stream is accepted and registered with the connection. +func (c *connection) newSpdyStream(stream *spdystream.Stream) { + replySent := make(chan struct{}) + err := c.newStreamHandler(stream, replySent) + rejectStream := (err != nil) + if rejectStream { + klog.Warningf("Stream rejected: %v", err) + stream.Reset() + return + } + + c.registerStream(stream) + stream.SendReply(http.Header{}, rejectStream) + close(replySent) +} + +// SetIdleTimeout sets the amount of time the connection may remain idle before +// it is automatically closed. +func (c *connection) SetIdleTimeout(timeout time.Duration) { + c.conn.SetIdleTimeout(timeout) +} + +func (c *connection) sendPings(period time.Duration) { + t := time.NewTicker(period) + defer t.Stop() + for { + select { + case <-c.conn.CloseChan(): + return + case <-t.C: + } + if _, err := c.ping(); err != nil { + klog.V(3).Infof("SPDY Ping failed: %v", err) + // Continue, in case this is a transient failure. + // c.conn.CloseChan above will tell us when the connection is + // actually closed. + } + } +} diff --git a/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go new file mode 100644 index 0000000000..c78326fa3b --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go @@ -0,0 +1,399 @@ +/* +Copyright 2015 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package spdy + +import ( + "bufio" + "context" + "crypto/tls" + "encoding/base64" + "errors" + "fmt" + "io" + "net" + "net/http" + "net/http/httputil" + "net/url" + "strings" + "time" + + "golang.org/x/net/proxy" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/util/httpstream" + utilnet "k8s.io/apimachinery/pkg/util/net" + apiproxy "k8s.io/apimachinery/pkg/util/proxy" + "k8s.io/apimachinery/third_party/forked/golang/netutil" +) + +// SpdyRoundTripper knows how to upgrade an HTTP request to one that supports +// multiplexed streams. After RoundTrip() is invoked, Conn will be set +// and usable. SpdyRoundTripper implements the UpgradeRoundTripper interface. +type SpdyRoundTripper struct { + //tlsConfig holds the TLS configuration settings to use when connecting + //to the remote server. + tlsConfig *tls.Config + + /* TODO according to http://golang.org/pkg/net/http/#RoundTripper, a RoundTripper + must be safe for use by multiple concurrent goroutines. If this is absolutely + necessary, we could keep a map from http.Request to net.Conn. In practice, + a client will create an http.Client, set the transport to a new insteace of + SpdyRoundTripper, and use it a single time, so this hopefully won't be an issue. + */ + // conn is the underlying network connection to the remote server. + conn net.Conn + + // Dialer is the dialer used to connect. Used if non-nil. + Dialer *net.Dialer + + // proxier knows which proxy to use given a request, defaults to http.ProxyFromEnvironment + // Used primarily for mocking the proxy discovery in tests. + proxier func(req *http.Request) (*url.URL, error) + + // pingPeriod is a period for sending Ping frames over established + // connections. + pingPeriod time.Duration + + // upgradeTransport is an optional substitute for dialing if present. This field is + // mutually exclusive with the "tlsConfig", "Dialer", and "proxier". + upgradeTransport http.RoundTripper +} + +var _ utilnet.TLSClientConfigHolder = &SpdyRoundTripper{} +var _ httpstream.UpgradeRoundTripper = &SpdyRoundTripper{} +var _ utilnet.Dialer = &SpdyRoundTripper{} + +// NewRoundTripper creates a new SpdyRoundTripper that will use the specified +// tlsConfig. +func NewRoundTripper(tlsConfig *tls.Config) (*SpdyRoundTripper, error) { + return NewRoundTripperWithConfig(RoundTripperConfig{ + TLS: tlsConfig, + UpgradeTransport: nil, + }) +} + +// NewRoundTripperWithProxy creates a new SpdyRoundTripper that will use the +// specified tlsConfig and proxy func. +func NewRoundTripperWithProxy(tlsConfig *tls.Config, proxier func(*http.Request) (*url.URL, error)) (*SpdyRoundTripper, error) { + return NewRoundTripperWithConfig(RoundTripperConfig{ + TLS: tlsConfig, + Proxier: proxier, + UpgradeTransport: nil, + }) +} + +// NewRoundTripperWithConfig creates a new SpdyRoundTripper with the specified +// configuration. Returns an error if the SpdyRoundTripper is misconfigured. +func NewRoundTripperWithConfig(cfg RoundTripperConfig) (*SpdyRoundTripper, error) { + // Process UpgradeTransport, which is mutually exclusive to TLSConfig and Proxier. + if cfg.UpgradeTransport != nil { + if cfg.TLS != nil || cfg.Proxier != nil { + return nil, fmt.Errorf("SpdyRoundTripper: UpgradeTransport is mutually exclusive to TLSConfig or Proxier") + } + tlsConfig, err := utilnet.TLSClientConfig(cfg.UpgradeTransport) + if err != nil { + return nil, fmt.Errorf("SpdyRoundTripper: Unable to retrieve TLSConfig from UpgradeTransport: %v", err) + } + cfg.TLS = tlsConfig + } + if cfg.Proxier == nil { + cfg.Proxier = utilnet.NewProxierWithNoProxyCIDR(http.ProxyFromEnvironment) + } + return &SpdyRoundTripper{ + tlsConfig: cfg.TLS, + proxier: cfg.Proxier, + pingPeriod: cfg.PingPeriod, + upgradeTransport: cfg.UpgradeTransport, + }, nil +} + +// RoundTripperConfig is a set of options for an SpdyRoundTripper. +type RoundTripperConfig struct { + // TLS configuration used by the round tripper if UpgradeTransport not present. + TLS *tls.Config + // Proxier is a proxy function invoked on each request. Optional. + Proxier func(*http.Request) (*url.URL, error) + // PingPeriod is a period for sending SPDY Pings on the connection. + // Optional. + PingPeriod time.Duration + // UpgradeTransport is a subtitute transport used for dialing. If set, + // this field will be used instead of "TLS" and "Proxier" for connection creation. + // Optional. + UpgradeTransport http.RoundTripper +} + +// TLSClientConfig implements pkg/util/net.TLSClientConfigHolder for proper TLS checking during +// proxying with a spdy roundtripper. +func (s *SpdyRoundTripper) TLSClientConfig() *tls.Config { + return s.tlsConfig +} + +// Dial implements k8s.io/apimachinery/pkg/util/net.Dialer. +func (s *SpdyRoundTripper) Dial(req *http.Request) (net.Conn, error) { + var conn net.Conn + var err error + if s.upgradeTransport != nil { + conn, err = apiproxy.DialURL(req.Context(), req.URL, s.upgradeTransport) + } else { + conn, err = s.dial(req) + } + if err != nil { + return nil, err + } + + if err := req.Write(conn); err != nil { + conn.Close() + return nil, err + } + + return conn, nil +} + +// dial dials the host specified by req, using TLS if appropriate, optionally +// using a proxy server if one is configured via environment variables. +func (s *SpdyRoundTripper) dial(req *http.Request) (net.Conn, error) { + proxyURL, err := s.proxier(req) + if err != nil { + return nil, err + } + + if proxyURL == nil { + return s.dialWithoutProxy(req.Context(), req.URL) + } + + switch proxyURL.Scheme { + case "socks5": + return s.dialWithSocks5Proxy(req, proxyURL) + case "https", "http", "": + return s.dialWithHttpProxy(req, proxyURL) + } + + return nil, fmt.Errorf("proxy URL scheme not supported: %s", proxyURL.Scheme) +} + +// dialWithHttpProxy dials the host specified by url through an http or an https proxy. +func (s *SpdyRoundTripper) dialWithHttpProxy(req *http.Request, proxyURL *url.URL) (net.Conn, error) { + // ensure we use a canonical host with proxyReq + targetHost := netutil.CanonicalAddr(req.URL) + + // proxying logic adapted from http://blog.h6t.eu/post/74098062923/golang-websocket-with-http-proxy-support + proxyReq := http.Request{ + Method: "CONNECT", + URL: &url.URL{}, + Host: targetHost, + } + + proxyReq = *proxyReq.WithContext(req.Context()) + + if pa := s.proxyAuth(proxyURL); pa != "" { + proxyReq.Header = http.Header{} + proxyReq.Header.Set("Proxy-Authorization", pa) + } + + proxyDialConn, err := s.dialWithoutProxy(proxyReq.Context(), proxyURL) + if err != nil { + return nil, err + } + + //nolint:staticcheck // SA1019 ignore deprecated httputil.NewProxyClientConn + proxyClientConn := httputil.NewProxyClientConn(proxyDialConn, nil) + response, err := proxyClientConn.Do(&proxyReq) + //nolint:staticcheck // SA1019 ignore deprecated httputil.ErrPersistEOF: it might be + // returned from the invocation of proxyClientConn.Do + if err != nil && err != httputil.ErrPersistEOF { + return nil, err + } + if response != nil && response.StatusCode >= 300 || response.StatusCode < 200 { + return nil, fmt.Errorf("CONNECT request to %s returned response: %s", proxyURL.Redacted(), response.Status) + } + + rwc, _ := proxyClientConn.Hijack() + + if req.URL.Scheme == "https" { + return s.tlsConn(proxyReq.Context(), rwc, targetHost) + } + return rwc, nil +} + +// dialWithSocks5Proxy dials the host specified by url through a socks5 proxy. +func (s *SpdyRoundTripper) dialWithSocks5Proxy(req *http.Request, proxyURL *url.URL) (net.Conn, error) { + // ensure we use a canonical host with proxyReq + targetHost := netutil.CanonicalAddr(req.URL) + proxyDialAddr := netutil.CanonicalAddr(proxyURL) + + var auth *proxy.Auth + if proxyURL.User != nil { + pass, _ := proxyURL.User.Password() + auth = &proxy.Auth{ + User: proxyURL.User.Username(), + Password: pass, + } + } + + dialer := s.Dialer + if dialer == nil { + dialer = &net.Dialer{ + Timeout: 30 * time.Second, + } + } + + proxyDialer, err := proxy.SOCKS5("tcp", proxyDialAddr, auth, dialer) + if err != nil { + return nil, err + } + + // According to the implementation of proxy.SOCKS5, the type assertion will always succeed + contextDialer, ok := proxyDialer.(proxy.ContextDialer) + if !ok { + return nil, errors.New("SOCKS5 Dialer must implement ContextDialer") + } + + proxyDialConn, err := contextDialer.DialContext(req.Context(), "tcp", targetHost) + if err != nil { + return nil, err + } + + if req.URL.Scheme == "https" { + return s.tlsConn(req.Context(), proxyDialConn, targetHost) + } + return proxyDialConn, nil +} + +// tlsConn returns a TLS client side connection using rwc as the underlying transport. +func (s *SpdyRoundTripper) tlsConn(ctx context.Context, rwc net.Conn, targetHost string) (net.Conn, error) { + + host, _, err := net.SplitHostPort(targetHost) + if err != nil { + return nil, err + } + + tlsConfig := s.tlsConfig + switch { + case tlsConfig == nil: + tlsConfig = &tls.Config{ServerName: host} + case len(tlsConfig.ServerName) == 0: + tlsConfig = tlsConfig.Clone() + tlsConfig.ServerName = host + } + + tlsConn := tls.Client(rwc, tlsConfig) + + if err := tlsConn.HandshakeContext(ctx); err != nil { + tlsConn.Close() + return nil, err + } + + return tlsConn, nil +} + +// dialWithoutProxy dials the host specified by url, using TLS if appropriate. +func (s *SpdyRoundTripper) dialWithoutProxy(ctx context.Context, url *url.URL) (net.Conn, error) { + dialAddr := netutil.CanonicalAddr(url) + dialer := s.Dialer + if dialer == nil { + dialer = &net.Dialer{} + } + + if url.Scheme == "http" { + return dialer.DialContext(ctx, "tcp", dialAddr) + } + + tlsDialer := tls.Dialer{ + NetDialer: dialer, + Config: s.tlsConfig, + } + return tlsDialer.DialContext(ctx, "tcp", dialAddr) +} + +// proxyAuth returns, for a given proxy URL, the value to be used for the Proxy-Authorization header +func (s *SpdyRoundTripper) proxyAuth(proxyURL *url.URL) string { + if proxyURL == nil || proxyURL.User == nil { + return "" + } + username := proxyURL.User.Username() + password, _ := proxyURL.User.Password() + auth := username + ":" + password + return "Basic " + base64.StdEncoding.EncodeToString([]byte(auth)) +} + +// RoundTrip executes the Request and upgrades it. After a successful upgrade, +// clients may call SpdyRoundTripper.Connection() to retrieve the upgraded +// connection. +func (s *SpdyRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + req = utilnet.CloneRequest(req) + req.Header.Add(httpstream.HeaderConnection, httpstream.HeaderUpgrade) + req.Header.Add(httpstream.HeaderUpgrade, HeaderSpdy31) + + conn, err := s.Dial(req) + if err != nil { + return nil, err + } + + responseReader := bufio.NewReader(conn) + + resp, err := http.ReadResponse(responseReader, nil) + if err != nil { + conn.Close() + return nil, err + } + + s.conn = conn + + return resp, nil +} + +// NewConnection validates the upgrade response, creating and returning a new +// httpstream.Connection if there were no errors. +func (s *SpdyRoundTripper) NewConnection(resp *http.Response) (httpstream.Connection, error) { + connectionHeader := strings.ToLower(resp.Header.Get(httpstream.HeaderConnection)) + upgradeHeader := strings.ToLower(resp.Header.Get(httpstream.HeaderUpgrade)) + if (resp.StatusCode != http.StatusSwitchingProtocols) || !strings.Contains(connectionHeader, strings.ToLower(httpstream.HeaderUpgrade)) || !strings.Contains(upgradeHeader, strings.ToLower(HeaderSpdy31)) { + defer resp.Body.Close() + responseError := "" + responseErrorBytes, err := io.ReadAll(resp.Body) + if err != nil { + responseError = "unable to read error from server response" + } else { + // TODO: I don't belong here, I should be abstracted from this class + if obj, _, err := statusCodecs.UniversalDecoder().Decode(responseErrorBytes, nil, &metav1.Status{}); err == nil { + if status, ok := obj.(*metav1.Status); ok { + return nil, &apierrors.StatusError{ErrStatus: *status} + } + } + responseError = string(responseErrorBytes) + responseError = strings.TrimSpace(responseError) + } + + return nil, fmt.Errorf("unable to upgrade connection: %s", responseError) + } + + return NewClientConnectionWithPings(s.conn, s.pingPeriod) +} + +// statusScheme is private scheme for the decoding here until someone fixes the TODO in NewConnection +var statusScheme = runtime.NewScheme() + +// ParameterCodec knows about query parameters used with the meta v1 API spec. +var statusCodecs = serializer.NewCodecFactory(statusScheme) + +func init() { + statusScheme.AddUnversionedTypes(metav1.SchemeGroupVersion, + &metav1.Status{}, + ) +} diff --git a/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/upgrade.go b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/upgrade.go new file mode 100644 index 0000000000..d30ae2fa3d --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/upgrade.go @@ -0,0 +1,120 @@ +/* +Copyright 2015 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package spdy + +import ( + "bufio" + "fmt" + "io" + "net" + "net/http" + "strings" + "sync/atomic" + "time" + + "k8s.io/apimachinery/pkg/util/httpstream" + "k8s.io/apimachinery/pkg/util/runtime" +) + +const HeaderSpdy31 = "SPDY/3.1" + +// responseUpgrader knows how to upgrade HTTP responses. It +// implements the httpstream.ResponseUpgrader interface. +type responseUpgrader struct { + pingPeriod time.Duration +} + +// connWrapper is used to wrap a hijacked connection and its bufio.Reader. All +// calls will be handled directly by the underlying net.Conn with the exception +// of Read and Close calls, which will consider data in the bufio.Reader. This +// ensures that data already inside the used bufio.Reader instance is also +// read. +type connWrapper struct { + net.Conn + closed int32 + bufReader *bufio.Reader +} + +func (w *connWrapper) Read(b []byte) (n int, err error) { + if atomic.LoadInt32(&w.closed) == 1 { + return 0, io.EOF + } + return w.bufReader.Read(b) +} + +func (w *connWrapper) Close() error { + err := w.Conn.Close() + atomic.StoreInt32(&w.closed, 1) + return err +} + +// NewResponseUpgrader returns a new httpstream.ResponseUpgrader that is +// capable of upgrading HTTP responses using SPDY/3.1 via the +// spdystream package. +func NewResponseUpgrader() httpstream.ResponseUpgrader { + return NewResponseUpgraderWithPings(0) +} + +// NewResponseUpgraderWithPings returns a new httpstream.ResponseUpgrader that +// is capable of upgrading HTTP responses using SPDY/3.1 via the spdystream +// package. +// +// If pingPeriod is non-zero, for each incoming connection a background +// goroutine will send periodic Ping frames to the server. Use this to keep +// idle connections through certain load balancers alive longer. +func NewResponseUpgraderWithPings(pingPeriod time.Duration) httpstream.ResponseUpgrader { + return responseUpgrader{pingPeriod: pingPeriod} +} + +// UpgradeResponse upgrades an HTTP response to one that supports multiplexed +// streams. newStreamHandler will be called synchronously whenever the +// other end of the upgraded connection creates a new stream. +func (u responseUpgrader) UpgradeResponse(w http.ResponseWriter, req *http.Request, newStreamHandler httpstream.NewStreamHandler) httpstream.Connection { + connectionHeader := strings.ToLower(req.Header.Get(httpstream.HeaderConnection)) + upgradeHeader := strings.ToLower(req.Header.Get(httpstream.HeaderUpgrade)) + if !strings.Contains(connectionHeader, strings.ToLower(httpstream.HeaderUpgrade)) || !strings.Contains(upgradeHeader, strings.ToLower(HeaderSpdy31)) { + errorMsg := fmt.Sprintf("unable to upgrade: missing upgrade headers in request: %#v", req.Header) + http.Error(w, errorMsg, http.StatusBadRequest) + return nil + } + + hijacker, ok := w.(http.Hijacker) + if !ok { + errorMsg := "unable to upgrade: unable to hijack response" + http.Error(w, errorMsg, http.StatusInternalServerError) + return nil + } + + w.Header().Add(httpstream.HeaderConnection, httpstream.HeaderUpgrade) + w.Header().Add(httpstream.HeaderUpgrade, HeaderSpdy31) + w.WriteHeader(http.StatusSwitchingProtocols) + + conn, bufrw, err := hijacker.Hijack() + if err != nil { + runtime.HandleError(fmt.Errorf("unable to upgrade: error hijacking response: %v", err)) + return nil + } + + connWithBuf := &connWrapper{Conn: conn, bufReader: bufrw.Reader} + spdyConn, err := NewServerConnectionWithPings(connWithBuf, newStreamHandler, u.pingPeriod) + if err != nil { + runtime.HandleError(fmt.Errorf("unable to upgrade: error creating SPDY server connection: %v", err)) + return nil + } + + return spdyConn +} diff --git a/vendor/k8s.io/apimachinery/pkg/util/proxy/dial.go b/vendor/k8s.io/apimachinery/pkg/util/proxy/dial.go new file mode 100644 index 0000000000..e5196d1ee8 --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/util/proxy/dial.go @@ -0,0 +1,122 @@ +/* +Copyright 2015 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package proxy + +import ( + "context" + "crypto/tls" + "fmt" + "net" + "net/http" + "net/url" + + utilnet "k8s.io/apimachinery/pkg/util/net" + "k8s.io/apimachinery/third_party/forked/golang/netutil" + "k8s.io/klog/v2" +) + +// DialURL will dial the specified URL using the underlying dialer held by the passed +// RoundTripper. The primary use of this method is to support proxying upgradable connections. +// For this reason this method will prefer to negotiate http/1.1 if the URL scheme is https. +// If you wish to ensure ALPN negotiates http2 then set NextProto=[]string{"http2"} in the +// TLSConfig of the http.Transport +func DialURL(ctx context.Context, url *url.URL, transport http.RoundTripper) (net.Conn, error) { + dialAddr := netutil.CanonicalAddr(url) + + dialer, err := utilnet.DialerFor(transport) + if err != nil { + klog.V(5).Infof("Unable to unwrap transport %T to get dialer: %v", transport, err) + } + + switch url.Scheme { + case "http": + if dialer != nil { + return dialer(ctx, "tcp", dialAddr) + } + var d net.Dialer + return d.DialContext(ctx, "tcp", dialAddr) + case "https": + // Get the tls config from the transport if we recognize it + tlsConfig, err := utilnet.TLSClientConfig(transport) + if err != nil { + klog.V(5).Infof("Unable to unwrap transport %T to get at TLS config: %v", transport, err) + } + + if dialer != nil { + // We have a dialer; use it to open the connection, then + // create a tls client using the connection. + netConn, err := dialer(ctx, "tcp", dialAddr) + if err != nil { + return nil, err + } + if tlsConfig == nil { + // tls.Client requires non-nil config + klog.Warning("using custom dialer with no TLSClientConfig. Defaulting to InsecureSkipVerify") + // tls.Handshake() requires ServerName or InsecureSkipVerify + tlsConfig = &tls.Config{ + InsecureSkipVerify: true, + } + } else if len(tlsConfig.ServerName) == 0 && !tlsConfig.InsecureSkipVerify { + // tls.HandshakeContext() requires ServerName or InsecureSkipVerify + // infer the ServerName from the hostname we're connecting to. + inferredHost := dialAddr + if host, _, err := net.SplitHostPort(dialAddr); err == nil { + inferredHost = host + } + // Make a copy to avoid polluting the provided config + tlsConfigCopy := tlsConfig.Clone() + tlsConfigCopy.ServerName = inferredHost + tlsConfig = tlsConfigCopy + } + + // Since this method is primarily used within a "Connection: Upgrade" call we assume the caller is + // going to write HTTP/1.1 request to the wire. http2 should not be allowed in the TLSConfig.NextProtos, + // so we explicitly set that here. We only do this check if the TLSConfig support http/1.1. + if supportsHTTP11(tlsConfig.NextProtos) { + tlsConfig = tlsConfig.Clone() + tlsConfig.NextProtos = []string{"http/1.1"} + } + + tlsConn := tls.Client(netConn, tlsConfig) + if err := tlsConn.HandshakeContext(ctx); err != nil { + netConn.Close() + return nil, err + } + return tlsConn, nil + } else { + // Dial. + tlsDialer := tls.Dialer{ + Config: tlsConfig, + } + return tlsDialer.DialContext(ctx, "tcp", dialAddr) + } + default: + return nil, fmt.Errorf("unknown scheme: %s", url.Scheme) + } +} + +func supportsHTTP11(nextProtos []string) bool { + if len(nextProtos) == 0 { + return true + } + for _, proto := range nextProtos { + if proto == "http/1.1" { + return true + } + } + return false +} diff --git a/vendor/k8s.io/apimachinery/pkg/util/proxy/doc.go b/vendor/k8s.io/apimachinery/pkg/util/proxy/doc.go new file mode 100644 index 0000000000..d14ecfad54 --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/util/proxy/doc.go @@ -0,0 +1,18 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package proxy provides transport and upgrade support for proxies. +package proxy // import "k8s.io/apimachinery/pkg/util/proxy" diff --git a/vendor/k8s.io/apimachinery/pkg/util/proxy/transport.go b/vendor/k8s.io/apimachinery/pkg/util/proxy/transport.go new file mode 100644 index 0000000000..5a2dd6e14c --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/util/proxy/transport.go @@ -0,0 +1,272 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package proxy + +import ( + "bytes" + "compress/flate" + "compress/gzip" + "fmt" + "io" + "net/http" + "net/url" + "path" + "strings" + + "golang.org/x/net/html" + "golang.org/x/net/html/atom" + "k8s.io/klog/v2" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/util/net" + "k8s.io/apimachinery/pkg/util/sets" +) + +// atomsToAttrs states which attributes of which tags require URL substitution. +// Sources: http://www.w3.org/TR/REC-html40/index/attributes.html +// +// http://www.w3.org/html/wg/drafts/html/master/index.html#attributes-1 +var atomsToAttrs = map[atom.Atom]sets.String{ + atom.A: sets.NewString("href"), + atom.Applet: sets.NewString("codebase"), + atom.Area: sets.NewString("href"), + atom.Audio: sets.NewString("src"), + atom.Base: sets.NewString("href"), + atom.Blockquote: sets.NewString("cite"), + atom.Body: sets.NewString("background"), + atom.Button: sets.NewString("formaction"), + atom.Command: sets.NewString("icon"), + atom.Del: sets.NewString("cite"), + atom.Embed: sets.NewString("src"), + atom.Form: sets.NewString("action"), + atom.Frame: sets.NewString("longdesc", "src"), + atom.Head: sets.NewString("profile"), + atom.Html: sets.NewString("manifest"), + atom.Iframe: sets.NewString("longdesc", "src"), + atom.Img: sets.NewString("longdesc", "src", "usemap"), + atom.Input: sets.NewString("src", "usemap", "formaction"), + atom.Ins: sets.NewString("cite"), + atom.Link: sets.NewString("href"), + atom.Object: sets.NewString("classid", "codebase", "data", "usemap"), + atom.Q: sets.NewString("cite"), + atom.Script: sets.NewString("src"), + atom.Source: sets.NewString("src"), + atom.Video: sets.NewString("poster", "src"), + + // TODO: css URLs hidden in style elements. +} + +// Transport is a transport for text/html content that replaces URLs in html +// content with the prefix of the proxy server +type Transport struct { + Scheme string + Host string + PathPrepend string + + http.RoundTripper +} + +// RoundTrip implements the http.RoundTripper interface +func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { + // Add reverse proxy headers. + forwardedURI := path.Join(t.PathPrepend, req.URL.EscapedPath()) + if strings.HasSuffix(req.URL.Path, "/") { + forwardedURI = forwardedURI + "/" + } + req.Header.Set("X-Forwarded-Uri", forwardedURI) + if len(t.Host) > 0 { + req.Header.Set("X-Forwarded-Host", t.Host) + } + if len(t.Scheme) > 0 { + req.Header.Set("X-Forwarded-Proto", t.Scheme) + } + + rt := t.RoundTripper + if rt == nil { + rt = http.DefaultTransport + } + resp, err := rt.RoundTrip(req) + + if err != nil { + return nil, errors.NewServiceUnavailable(fmt.Sprintf("error trying to reach service: %v", err)) + } + + if redirect := resp.Header.Get("Location"); redirect != "" { + targetURL, err := url.Parse(redirect) + if err != nil { + return nil, errors.NewInternalError(fmt.Errorf("error trying to parse Location header: %v", err)) + } + resp.Header.Set("Location", t.rewriteURL(targetURL, req.URL, req.Host)) + return resp, nil + } + + cType := resp.Header.Get("Content-Type") + cType = strings.TrimSpace(strings.SplitN(cType, ";", 2)[0]) + if cType != "text/html" { + // Do nothing, simply pass through + return resp, nil + } + + return t.rewriteResponse(req, resp) +} + +var _ = net.RoundTripperWrapper(&Transport{}) + +func (rt *Transport) WrappedRoundTripper() http.RoundTripper { + return rt.RoundTripper +} + +// rewriteURL rewrites a single URL to go through the proxy, if the URL refers +// to the same host as sourceURL, which is the page on which the target URL +// occurred, or if the URL matches the sourceRequestHost. +func (t *Transport) rewriteURL(url *url.URL, sourceURL *url.URL, sourceRequestHost string) string { + // Example: + // When API server processes a proxy request to a service (e.g. /api/v1/namespace/foo/service/bar/proxy/), + // the sourceURL.Host (i.e. req.URL.Host) is the endpoint IP address of the service. The + // sourceRequestHost (i.e. req.Host) is the Host header that specifies the host on which the + // URL is sought, which can be different from sourceURL.Host. For example, if user sends the + // request through "kubectl proxy" locally (i.e. localhost:8001/api/v1/namespace/foo/service/bar/proxy/), + // sourceRequestHost is "localhost:8001". + // + // If the service's response URL contains non-empty host, and url.Host is equal to either sourceURL.Host + // or sourceRequestHost, we should not consider the returned URL to be a completely different host. + // It's the API server's responsibility to rewrite a same-host-and-absolute-path URL and append the + // necessary URL prefix (i.e. /api/v1/namespace/foo/service/bar/proxy/). + isDifferentHost := url.Host != "" && url.Host != sourceURL.Host && url.Host != sourceRequestHost + isRelative := !strings.HasPrefix(url.Path, "/") + if isDifferentHost || isRelative { + return url.String() + } + + // Do not rewrite scheme and host if the Transport has empty scheme and host + // when targetURL already contains the sourceRequestHost + if !(url.Host == sourceRequestHost && t.Scheme == "" && t.Host == "") { + url.Scheme = t.Scheme + url.Host = t.Host + } + + origPath := url.Path + // Do not rewrite URL if the sourceURL already contains the necessary prefix. + if strings.HasPrefix(url.Path, t.PathPrepend) { + return url.String() + } + url.Path = path.Join(t.PathPrepend, url.Path) + if strings.HasSuffix(origPath, "/") { + // Add back the trailing slash, which was stripped by path.Join(). + url.Path += "/" + } + + return url.String() +} + +// rewriteHTML scans the HTML for tags with url-valued attributes, and updates +// those values with the urlRewriter function. The updated HTML is output to the +// writer. +func rewriteHTML(reader io.Reader, writer io.Writer, urlRewriter func(*url.URL) string) error { + // Note: This assumes the content is UTF-8. + tokenizer := html.NewTokenizer(reader) + + var err error + for err == nil { + tokenType := tokenizer.Next() + switch tokenType { + case html.ErrorToken: + err = tokenizer.Err() + case html.StartTagToken, html.SelfClosingTagToken: + token := tokenizer.Token() + if urlAttrs, ok := atomsToAttrs[token.DataAtom]; ok { + for i, attr := range token.Attr { + if urlAttrs.Has(attr.Key) { + url, err := url.Parse(attr.Val) + if err != nil { + // Do not rewrite the URL if it isn't valid. It is intended not + // to error here to prevent the inability to understand the + // content of the body to cause a fatal error. + continue + } + token.Attr[i].Val = urlRewriter(url) + } + } + } + _, err = writer.Write([]byte(token.String())) + default: + _, err = writer.Write(tokenizer.Raw()) + } + } + if err != io.EOF { + return err + } + return nil +} + +// rewriteResponse modifies an HTML response by updating absolute links referring +// to the original host to instead refer to the proxy transport. +func (t *Transport) rewriteResponse(req *http.Request, resp *http.Response) (*http.Response, error) { + origBody := resp.Body + defer origBody.Close() + + newContent := &bytes.Buffer{} + var reader io.Reader = origBody + var writer io.Writer = newContent + encoding := resp.Header.Get("Content-Encoding") + switch encoding { + case "gzip": + var err error + reader, err = gzip.NewReader(reader) + if err != nil { + return nil, fmt.Errorf("errorf making gzip reader: %v", err) + } + gzw := gzip.NewWriter(writer) + defer gzw.Close() + writer = gzw + case "deflate": + var err error + reader = flate.NewReader(reader) + flw, err := flate.NewWriter(writer, flate.BestCompression) + if err != nil { + return nil, fmt.Errorf("errorf making flate writer: %v", err) + } + defer func() { + flw.Close() + flw.Flush() + }() + writer = flw + case "": + // This is fine + default: + // Some encoding we don't understand-- don't try to parse this + klog.Errorf("Proxy encountered encoding %v for text/html; can't understand this so not fixing links.", encoding) + return resp, nil + } + + urlRewriter := func(targetUrl *url.URL) string { + return t.rewriteURL(targetUrl, req.URL, req.Host) + } + err := rewriteHTML(reader, writer, urlRewriter) + if err != nil { + klog.Errorf("Failed to rewrite URLs: %v", err) + return resp, err + } + + resp.Body = io.NopCloser(newContent) + // Update header node with new content-length + // TODO: Remove any hash/signature headers here? + resp.Header.Del("Content-Length") + resp.ContentLength = int64(newContent.Len()) + + return resp, err +} diff --git a/vendor/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go b/vendor/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go new file mode 100644 index 0000000000..8c30a366de --- /dev/null +++ b/vendor/k8s.io/apimachinery/pkg/util/proxy/upgradeaware.go @@ -0,0 +1,558 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package proxy + +import ( + "bufio" + "bytes" + "fmt" + "io" + "log" + "net" + "net/http" + "net/http/httputil" + "net/url" + "os" + "strings" + "time" + + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/util/httpstream" + utilnet "k8s.io/apimachinery/pkg/util/net" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + + "github.com/mxk/go-flowrate/flowrate" + + "k8s.io/klog/v2" +) + +// UpgradeRequestRoundTripper provides an additional method to decorate a request +// with any authentication or other protocol level information prior to performing +// an upgrade on the server. Any response will be handled by the intercepting +// proxy. +type UpgradeRequestRoundTripper interface { + http.RoundTripper + // WrapRequest takes a valid HTTP request and returns a suitably altered version + // of request with any HTTP level values required to complete the request half of + // an upgrade on the server. It does not get a chance to see the response and + // should bypass any request side logic that expects to see the response. + WrapRequest(*http.Request) (*http.Request, error) +} + +// UpgradeAwareHandler is a handler for proxy requests that may require an upgrade +type UpgradeAwareHandler struct { + // UpgradeRequired will reject non-upgrade connections if true. + UpgradeRequired bool + // Location is the location of the upstream proxy. It is used as the location to Dial on the upstream server + // for upgrade requests unless UseRequestLocationOnUpgrade is true. + Location *url.URL + // AppendLocationPath determines if the original path of the Location should be appended to the upstream proxy request path + AppendLocationPath bool + // Transport provides an optional round tripper to use to proxy. If nil, the default proxy transport is used + Transport http.RoundTripper + // UpgradeTransport, if specified, will be used as the backend transport when upgrade requests are provided. + // This allows clients to disable HTTP/2. + UpgradeTransport UpgradeRequestRoundTripper + // WrapTransport indicates whether the provided Transport should be wrapped with default proxy transport behavior (URL rewriting, X-Forwarded-* header setting) + WrapTransport bool + // UseRequestLocation will use the incoming request URL when talking to the backend server. + UseRequestLocation bool + // UseLocationHost overrides the HTTP host header in requests to the backend server to use the Host from Location. + // This will override the req.Host field of a request, while UseRequestLocation will override the req.URL field + // of a request. The req.URL.Host specifies the server to connect to, while the req.Host field + // specifies the Host header value to send in the HTTP request. If this is false, the incoming req.Host header will + // just be forwarded to the backend server. + UseLocationHost bool + // FlushInterval controls how often the standard HTTP proxy will flush content from the upstream. + FlushInterval time.Duration + // MaxBytesPerSec controls the maximum rate for an upstream connection. No rate is imposed if the value is zero. + MaxBytesPerSec int64 + // Responder is passed errors that occur while setting up proxying. + Responder ErrorResponder + // Reject to forward redirect response + RejectForwardingRedirects bool +} + +const defaultFlushInterval = 200 * time.Millisecond + +// ErrorResponder abstracts error reporting to the proxy handler to remove the need to hardcode a particular +// error format. +type ErrorResponder interface { + Error(w http.ResponseWriter, req *http.Request, err error) +} + +// SimpleErrorResponder is the legacy implementation of ErrorResponder for callers that only +// service a single request/response per proxy. +type SimpleErrorResponder interface { + Error(err error) +} + +func NewErrorResponder(r SimpleErrorResponder) ErrorResponder { + return simpleResponder{r} +} + +type simpleResponder struct { + responder SimpleErrorResponder +} + +func (r simpleResponder) Error(w http.ResponseWriter, req *http.Request, err error) { + r.responder.Error(err) +} + +// upgradeRequestRoundTripper implements proxy.UpgradeRequestRoundTripper. +type upgradeRequestRoundTripper struct { + http.RoundTripper + upgrader http.RoundTripper +} + +var ( + _ UpgradeRequestRoundTripper = &upgradeRequestRoundTripper{} + _ utilnet.RoundTripperWrapper = &upgradeRequestRoundTripper{} +) + +// WrappedRoundTripper returns the round tripper that a caller would use. +func (rt *upgradeRequestRoundTripper) WrappedRoundTripper() http.RoundTripper { + return rt.RoundTripper +} + +// WriteToRequest calls the nested upgrader and then copies the returned request +// fields onto the passed request. +func (rt *upgradeRequestRoundTripper) WrapRequest(req *http.Request) (*http.Request, error) { + resp, err := rt.upgrader.RoundTrip(req) + if err != nil { + return nil, err + } + return resp.Request, nil +} + +// onewayRoundTripper captures the provided request - which is assumed to have +// been modified by other round trippers - and then returns a fake response. +type onewayRoundTripper struct{} + +// RoundTrip returns a simple 200 OK response that captures the provided request. +func (onewayRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + return &http.Response{ + Status: "200 OK", + StatusCode: http.StatusOK, + Body: io.NopCloser(&bytes.Buffer{}), + Request: req, + }, nil +} + +// MirrorRequest is a round tripper that can be called to get back the calling request as +// the core round tripper in a chain. +var MirrorRequest http.RoundTripper = onewayRoundTripper{} + +// NewUpgradeRequestRoundTripper takes two round trippers - one for the underlying TCP connection, and +// one that is able to write headers to an HTTP request. The request rt is used to set the request headers +// and that is written to the underlying connection rt. +func NewUpgradeRequestRoundTripper(connection, request http.RoundTripper) UpgradeRequestRoundTripper { + return &upgradeRequestRoundTripper{ + RoundTripper: connection, + upgrader: request, + } +} + +// normalizeLocation returns the result of parsing the full URL, with scheme set to http if missing +func normalizeLocation(location *url.URL) *url.URL { + normalized, _ := url.Parse(location.String()) + if len(normalized.Scheme) == 0 { + normalized.Scheme = "http" + } + return normalized +} + +// NewUpgradeAwareHandler creates a new proxy handler with a default flush interval. Responder is required for returning +// errors to the caller. +func NewUpgradeAwareHandler(location *url.URL, transport http.RoundTripper, wrapTransport, upgradeRequired bool, responder ErrorResponder) *UpgradeAwareHandler { + return &UpgradeAwareHandler{ + Location: normalizeLocation(location), + Transport: transport, + WrapTransport: wrapTransport, + UpgradeRequired: upgradeRequired, + FlushInterval: defaultFlushInterval, + Responder: responder, + } +} + +func proxyRedirectsforRootPath(path string, w http.ResponseWriter, req *http.Request) bool { + redirect := false + method := req.Method + + // From pkg/genericapiserver/endpoints/handlers/proxy.go#ServeHTTP: + // Redirect requests with an empty path to a location that ends with a '/' + // This is essentially a hack for https://issue.k8s.io/4958. + // Note: Keep this code after tryUpgrade to not break that flow. + if len(path) == 0 && (method == http.MethodGet || method == http.MethodHead) { + var queryPart string + if len(req.URL.RawQuery) > 0 { + queryPart = "?" + req.URL.RawQuery + } + w.Header().Set("Location", req.URL.Path+"/"+queryPart) + w.WriteHeader(http.StatusMovedPermanently) + redirect = true + } + return redirect +} + +// ServeHTTP handles the proxy request +func (h *UpgradeAwareHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { + if h.tryUpgrade(w, req) { + return + } + if h.UpgradeRequired { + h.Responder.Error(w, req, errors.NewBadRequest("Upgrade request required")) + return + } + + loc := *h.Location + loc.RawQuery = req.URL.RawQuery + + // If original request URL ended in '/', append a '/' at the end of the + // of the proxy URL + if !strings.HasSuffix(loc.Path, "/") && strings.HasSuffix(req.URL.Path, "/") { + loc.Path += "/" + } + + proxyRedirect := proxyRedirectsforRootPath(loc.Path, w, req) + if proxyRedirect { + return + } + + if h.Transport == nil || h.WrapTransport { + h.Transport = h.defaultProxyTransport(req.URL, h.Transport) + } + + // WithContext creates a shallow clone of the request with the same context. + newReq := req.WithContext(req.Context()) + newReq.Header = utilnet.CloneHeader(req.Header) + if !h.UseRequestLocation { + newReq.URL = &loc + } + if h.UseLocationHost { + // exchanging req.Host with the backend location is necessary for backends that act on the HTTP host header (e.g. API gateways), + // because req.Host has preference over req.URL.Host in filling this header field + newReq.Host = h.Location.Host + } + + // create the target location to use for the reverse proxy + reverseProxyLocation := &url.URL{Scheme: h.Location.Scheme, Host: h.Location.Host} + if h.AppendLocationPath { + reverseProxyLocation.Path = h.Location.Path + } + + proxy := httputil.NewSingleHostReverseProxy(reverseProxyLocation) + proxy.Transport = h.Transport + proxy.FlushInterval = h.FlushInterval + proxy.ErrorLog = log.New(noSuppressPanicError{}, "", log.LstdFlags) + if h.RejectForwardingRedirects { + oldModifyResponse := proxy.ModifyResponse + proxy.ModifyResponse = func(response *http.Response) error { + code := response.StatusCode + if code >= 300 && code <= 399 && len(response.Header.Get("Location")) > 0 { + // close the original response + response.Body.Close() + msg := "the backend attempted to redirect this request, which is not permitted" + // replace the response + *response = http.Response{ + StatusCode: http.StatusBadGateway, + Status: fmt.Sprintf("%d %s", response.StatusCode, http.StatusText(response.StatusCode)), + Body: io.NopCloser(strings.NewReader(msg)), + ContentLength: int64(len(msg)), + } + } else { + if oldModifyResponse != nil { + if err := oldModifyResponse(response); err != nil { + return err + } + } + } + return nil + } + } + if h.Responder != nil { + // if an optional error interceptor/responder was provided wire it + // the custom responder might be used for providing a unified error reporting + // or supporting retry mechanisms by not sending non-fatal errors to the clients + proxy.ErrorHandler = h.Responder.Error + } + proxy.ServeHTTP(w, newReq) +} + +type noSuppressPanicError struct{} + +func (noSuppressPanicError) Write(p []byte) (n int, err error) { + // skip "suppressing panic for copyResponse error in test; copy error" error message + // that ends up in CI tests on each kube-apiserver termination as noise and + // everybody thinks this is fatal. + if strings.Contains(string(p), "suppressing panic") { + return len(p), nil + } + return os.Stderr.Write(p) +} + +// tryUpgrade returns true if the request was handled. +func (h *UpgradeAwareHandler) tryUpgrade(w http.ResponseWriter, req *http.Request) bool { + if !httpstream.IsUpgradeRequest(req) { + klog.V(6).Infof("Request was not an upgrade") + return false + } + + var ( + backendConn net.Conn + rawResponse []byte + err error + ) + + location := *h.Location + if h.UseRequestLocation { + location = *req.URL + location.Scheme = h.Location.Scheme + location.Host = h.Location.Host + if h.AppendLocationPath { + location.Path = singleJoiningSlash(h.Location.Path, location.Path) + } + } + + clone := utilnet.CloneRequest(req) + // Only append X-Forwarded-For in the upgrade path, since httputil.NewSingleHostReverseProxy + // handles this in the non-upgrade path. + utilnet.AppendForwardedForHeader(clone) + klog.V(6).Infof("Connecting to backend proxy (direct dial) %s\n Headers: %v", &location, clone.Header) + if h.UseLocationHost { + clone.Host = h.Location.Host + } + clone.URL = &location + klog.V(6).Infof("UpgradeAwareProxy: dialing for SPDY upgrade with headers: %v", clone.Header) + backendConn, err = h.DialForUpgrade(clone) + if err != nil { + klog.V(6).Infof("Proxy connection error: %v", err) + h.Responder.Error(w, req, err) + return true + } + defer backendConn.Close() + + // determine the http response code from the backend by reading from rawResponse+backendConn + backendHTTPResponse, headerBytes, err := getResponse(io.MultiReader(bytes.NewReader(rawResponse), backendConn)) + if err != nil { + klog.V(6).Infof("Proxy connection error: %v", err) + h.Responder.Error(w, req, err) + return true + } + if len(headerBytes) > len(rawResponse) { + // we read beyond the bytes stored in rawResponse, update rawResponse to the full set of bytes read from the backend + rawResponse = headerBytes + } + + // If the backend did not upgrade the request, return an error to the client. If the response was + // an error, the error is forwarded directly after the connection is hijacked. Otherwise, just + // return a generic error here. + if backendHTTPResponse.StatusCode != http.StatusSwitchingProtocols && backendHTTPResponse.StatusCode < 400 { + err := fmt.Errorf("invalid upgrade response: status code %d", backendHTTPResponse.StatusCode) + klog.Errorf("Proxy upgrade error: %v", err) + h.Responder.Error(w, req, err) + return true + } + + // Once the connection is hijacked, the ErrorResponder will no longer work, so + // hijacking should be the last step in the upgrade. + requestHijacker, ok := w.(http.Hijacker) + if !ok { + klog.Errorf("Unable to hijack response writer: %T", w) + h.Responder.Error(w, req, fmt.Errorf("request connection cannot be hijacked: %T", w)) + return true + } + requestHijackedConn, _, err := requestHijacker.Hijack() + if err != nil { + klog.Errorf("Unable to hijack response: %v", err) + h.Responder.Error(w, req, fmt.Errorf("error hijacking connection: %v", err)) + return true + } + defer requestHijackedConn.Close() + + if backendHTTPResponse.StatusCode != http.StatusSwitchingProtocols { + // If the backend did not upgrade the request, echo the response from the backend to the client and return, closing the connection. + klog.V(6).Infof("Proxy upgrade error, status code %d", backendHTTPResponse.StatusCode) + // set read/write deadlines + deadline := time.Now().Add(10 * time.Second) + backendConn.SetReadDeadline(deadline) + requestHijackedConn.SetWriteDeadline(deadline) + // write the response to the client + err := backendHTTPResponse.Write(requestHijackedConn) + if err != nil && !strings.Contains(err.Error(), "use of closed network connection") { + klog.Errorf("Error proxying data from backend to client: %v", err) + } + // Indicate we handled the request + return true + } + + // Forward raw response bytes back to client. + if len(rawResponse) > 0 { + klog.V(6).Infof("Writing %d bytes to hijacked connection", len(rawResponse)) + if _, err = requestHijackedConn.Write(rawResponse); err != nil { + utilruntime.HandleError(fmt.Errorf("Error proxying response from backend to client: %v", err)) + } + } + + // Proxy the connection. This is bidirectional, so we need a goroutine + // to copy in each direction. Once one side of the connection exits, we + // exit the function which performs cleanup and in the process closes + // the other half of the connection in the defer. + writerComplete := make(chan struct{}) + readerComplete := make(chan struct{}) + + go func() { + var writer io.WriteCloser + if h.MaxBytesPerSec > 0 { + writer = flowrate.NewWriter(backendConn, h.MaxBytesPerSec) + } else { + writer = backendConn + } + _, err := io.Copy(writer, requestHijackedConn) + if err != nil && !strings.Contains(err.Error(), "use of closed network connection") { + klog.Errorf("Error proxying data from client to backend: %v", err) + } + close(writerComplete) + }() + + go func() { + var reader io.ReadCloser + if h.MaxBytesPerSec > 0 { + reader = flowrate.NewReader(backendConn, h.MaxBytesPerSec) + } else { + reader = backendConn + } + _, err := io.Copy(requestHijackedConn, reader) + if err != nil && !strings.Contains(err.Error(), "use of closed network connection") { + klog.Errorf("Error proxying data from backend to client: %v", err) + } + close(readerComplete) + }() + + // Wait for one half the connection to exit. Once it does the defer will + // clean up the other half of the connection. + select { + case <-writerComplete: + case <-readerComplete: + } + klog.V(6).Infof("Disconnecting from backend proxy %s\n Headers: %v", &location, clone.Header) + + return true +} + +// FIXME: Taken from net/http/httputil/reverseproxy.go as singleJoiningSlash is not exported to be re-used. +// See-also: https://github.com/golang/go/issues/44290 +func singleJoiningSlash(a, b string) string { + aslash := strings.HasSuffix(a, "/") + bslash := strings.HasPrefix(b, "/") + switch { + case aslash && bslash: + return a + b[1:] + case !aslash && !bslash: + return a + "/" + b + } + return a + b +} + +func (h *UpgradeAwareHandler) DialForUpgrade(req *http.Request) (net.Conn, error) { + if h.UpgradeTransport == nil { + return dial(req, h.Transport) + } + updatedReq, err := h.UpgradeTransport.WrapRequest(req) + if err != nil { + return nil, err + } + return dial(updatedReq, h.UpgradeTransport) +} + +// getResponseCode reads a http response from the given reader, returns the response, +// the bytes read from the reader, and any error encountered +func getResponse(r io.Reader) (*http.Response, []byte, error) { + rawResponse := bytes.NewBuffer(make([]byte, 0, 256)) + // Save the bytes read while reading the response headers into the rawResponse buffer + resp, err := http.ReadResponse(bufio.NewReader(io.TeeReader(r, rawResponse)), nil) + if err != nil { + return nil, nil, err + } + // return the http response and the raw bytes consumed from the reader in the process + return resp, rawResponse.Bytes(), nil +} + +// dial dials the backend at req.URL and writes req to it. +func dial(req *http.Request, transport http.RoundTripper) (net.Conn, error) { + conn, err := DialURL(req.Context(), req.URL, transport) + if err != nil { + return nil, fmt.Errorf("error dialing backend: %v", err) + } + + if err = req.Write(conn); err != nil { + conn.Close() + return nil, fmt.Errorf("error sending request: %v", err) + } + + return conn, err +} + +func (h *UpgradeAwareHandler) defaultProxyTransport(url *url.URL, internalTransport http.RoundTripper) http.RoundTripper { + scheme := url.Scheme + host := url.Host + suffix := h.Location.Path + if strings.HasSuffix(url.Path, "/") && !strings.HasSuffix(suffix, "/") { + suffix += "/" + } + pathPrepend := strings.TrimSuffix(url.Path, suffix) + rewritingTransport := &Transport{ + Scheme: scheme, + Host: host, + PathPrepend: pathPrepend, + RoundTripper: internalTransport, + } + return &corsRemovingTransport{ + RoundTripper: rewritingTransport, + } +} + +// corsRemovingTransport is a wrapper for an internal transport. It removes CORS headers +// from the internal response. +// Implements pkg/util/net.RoundTripperWrapper +type corsRemovingTransport struct { + http.RoundTripper +} + +var _ = utilnet.RoundTripperWrapper(&corsRemovingTransport{}) + +func (rt *corsRemovingTransport) RoundTrip(req *http.Request) (*http.Response, error) { + resp, err := rt.RoundTripper.RoundTrip(req) + if err != nil { + return nil, err + } + removeCORSHeaders(resp) + return resp, nil +} + +func (rt *corsRemovingTransport) WrappedRoundTripper() http.RoundTripper { + return rt.RoundTripper +} + +// removeCORSHeaders strip CORS headers sent from the backend +// This should be called on all responses before returning +func removeCORSHeaders(resp *http.Response) { + resp.Header.Del("Access-Control-Allow-Credentials") + resp.Header.Del("Access-Control-Allow-Headers") + resp.Header.Del("Access-Control-Allow-Methods") + resp.Header.Del("Access-Control-Allow-Origin") +} diff --git a/vendor/k8s.io/apimachinery/third_party/forked/golang/netutil/addr.go b/vendor/k8s.io/apimachinery/third_party/forked/golang/netutil/addr.go new file mode 100644 index 0000000000..bd26f427e3 --- /dev/null +++ b/vendor/k8s.io/apimachinery/third_party/forked/golang/netutil/addr.go @@ -0,0 +1,28 @@ +package netutil + +import ( + "net/url" + "strings" +) + +// FROM: http://golang.org/src/net/http/client.go +// Given a string of the form "host", "host:port", or "[ipv6::address]:port", +// return true if the string includes a port. +func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") } + +// FROM: http://golang.org/src/net/http/transport.go +var portMap = map[string]string{ + "http": "80", + "https": "443", + "socks5": "1080", +} + +// FROM: http://golang.org/src/net/http/transport.go +// canonicalAddr returns url.Host but always with a ":port" suffix +func CanonicalAddr(url *url.URL) string { + addr := url.Host + if !hasPort(addr) { + return addr + ":" + portMap[url.Scheme] + } + return addr +} diff --git a/vendor/k8s.io/cli-runtime/LICENSE b/vendor/k8s.io/cli-runtime/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/discard.go b/vendor/k8s.io/cli-runtime/pkg/printers/discard.go new file mode 100644 index 0000000000..cd934976da --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/discard.go @@ -0,0 +1,30 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "io" + + "k8s.io/apimachinery/pkg/runtime" +) + +// NewDiscardingPrinter is a printer that discards all objects +func NewDiscardingPrinter() ResourcePrinterFunc { + return ResourcePrinterFunc(func(runtime.Object, io.Writer) error { + return nil + }) +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/doc.go b/vendor/k8s.io/cli-runtime/pkg/printers/doc.go new file mode 100644 index 0000000000..ee205371de --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/doc.go @@ -0,0 +1,19 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package printers is helper for formatting and printing runtime objects into +// primitives io.writer. +package printers // import "k8s.io/cli-runtime/pkg/printers" diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/interface.go b/vendor/k8s.io/cli-runtime/pkg/printers/interface.go new file mode 100644 index 0000000000..e88ff63ae6 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/interface.go @@ -0,0 +1,54 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "io" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// ResourcePrinterFunc is a function that can print objects +type ResourcePrinterFunc func(runtime.Object, io.Writer) error + +// PrintObj implements ResourcePrinter +func (fn ResourcePrinterFunc) PrintObj(obj runtime.Object, w io.Writer) error { + return fn(obj, w) +} + +// ResourcePrinter is an interface that knows how to print runtime objects. +type ResourcePrinter interface { + // PrintObj receives a runtime object, formats it and prints it to a writer. + PrintObj(runtime.Object, io.Writer) error +} + +// PrintOptions struct defines a struct for various print options +type PrintOptions struct { + NoHeaders bool + WithNamespace bool + WithKind bool + Wide bool + ShowLabels bool + Kind schema.GroupKind + ColumnLabels []string + + SortBy string + + // indicates if it is OK to ignore missing keys for rendering an output template. + AllowMissingKeys bool +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/json.go b/vendor/k8s.io/cli-runtime/pkg/printers/json.go new file mode 100644 index 0000000000..8ab2235f8b --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/json.go @@ -0,0 +1,79 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "reflect" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// JSONPrinter is an implementation of ResourcePrinter which outputs an object as JSON. +type JSONPrinter struct{} + +// PrintObj is an implementation of ResourcePrinter.PrintObj which simply writes the object to the Writer. +func (p *JSONPrinter) PrintObj(obj runtime.Object, w io.Writer) error { + // we use reflect.Indirect here in order to obtain the actual value from a pointer. + // we need an actual value in order to retrieve the package path for an object. + // using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers. + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + + switch obj := obj.(type) { + case *metav1.WatchEvent: + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj.Object.Object)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + data, err := json.Marshal(obj) + if err != nil { + return err + } + _, err = w.Write(data) + if err != nil { + return err + } + _, err = w.Write([]byte{'\n'}) + return err + case *runtime.Unknown: + var buf bytes.Buffer + err := json.Indent(&buf, obj.Raw, "", " ") + if err != nil { + return err + } + buf.WriteRune('\n') + _, err = buf.WriteTo(w) + return err + } + + if obj.GetObjectKind().GroupVersionKind().Empty() { + return fmt.Errorf("missing apiVersion or kind; try GetObjectKind().SetGroupVersionKind() if you know the type") + } + + data, err := json.MarshalIndent(obj, "", " ") + if err != nil { + return err + } + data = append(data, '\n') + _, err = w.Write(data) + return err +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/jsonpath.go b/vendor/k8s.io/cli-runtime/pkg/printers/jsonpath.go new file mode 100644 index 0000000000..769960d667 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/jsonpath.go @@ -0,0 +1,147 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "reflect" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/util/jsonpath" +) + +// exists returns true if it would be possible to call the index function +// with these arguments. +// +// TODO: how to document this for users? +// +// index returns the result of indexing its first argument by the following +// arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each +// indexed item must be a map, slice, or array. +func exists(item interface{}, indices ...interface{}) bool { + v := reflect.ValueOf(item) + for _, i := range indices { + index := reflect.ValueOf(i) + var isNil bool + if v, isNil = indirect(v); isNil { + return false + } + switch v.Kind() { + case reflect.Array, reflect.Slice, reflect.String: + var x int64 + switch index.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + x = index.Int() + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + x = int64(index.Uint()) + default: + return false + } + if x < 0 || x >= int64(v.Len()) { + return false + } + v = v.Index(int(x)) + case reflect.Map: + if !index.IsValid() { + index = reflect.Zero(v.Type().Key()) + } + if !index.Type().AssignableTo(v.Type().Key()) { + return false + } + if x := v.MapIndex(index); x.IsValid() { + v = x + } else { + v = reflect.Zero(v.Type().Elem()) + } + default: + return false + } + } + if _, isNil := indirect(v); isNil { + return false + } + return true +} + +// stolen from text/template +// indirect returns the item at the end of indirection, and a bool to indicate if it's nil. +// We indirect through pointers and empty interfaces (only) because +// non-empty interfaces have methods we might need. +func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { + for ; v.Kind() == reflect.Pointer || v.Kind() == reflect.Interface; v = v.Elem() { + if v.IsNil() { + return v, true + } + if v.Kind() == reflect.Interface && v.NumMethod() > 0 { + break + } + } + return v, false +} + +// JSONPathPrinter is an implementation of ResourcePrinter which formats data with jsonpath expression. +type JSONPathPrinter struct { + rawTemplate string + *jsonpath.JSONPath +} + +func NewJSONPathPrinter(tmpl string) (*JSONPathPrinter, error) { + j := jsonpath.New("out") + if err := j.Parse(tmpl); err != nil { + return nil, err + } + return &JSONPathPrinter{ + rawTemplate: tmpl, + JSONPath: j, + }, nil +} + +// PrintObj formats the obj with the JSONPath Template. +func (j *JSONPathPrinter) PrintObj(obj runtime.Object, w io.Writer) error { + // we use reflect.Indirect here in order to obtain the actual value from a pointer. + // we need an actual value in order to retrieve the package path for an object. + // using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers. + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + + var queryObj interface{} = obj + if unstructured, ok := obj.(runtime.Unstructured); ok { + queryObj = unstructured.UnstructuredContent() + } else { + data, err := json.Marshal(obj) + if err != nil { + return err + } + queryObj = map[string]interface{}{} + if err := json.Unmarshal(data, &queryObj); err != nil { + return err + } + } + + if err := j.JSONPath.Execute(w, queryObj); err != nil { + buf := bytes.NewBuffer(nil) + fmt.Fprintf(buf, "Error executing template: %v. Printing more information for debugging the template:\n", err) + fmt.Fprintf(buf, "\ttemplate was:\n\t\t%v\n", j.rawTemplate) + fmt.Fprintf(buf, "\tobject given to jsonpath engine was:\n\t\t%#v\n\n", queryObj) + return fmt.Errorf("error executing jsonpath %q: %v\n", j.rawTemplate, buf.String()) + } + return nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/managedfields.go b/vendor/k8s.io/cli-runtime/pkg/printers/managedfields.go new file mode 100644 index 0000000000..cab54d0584 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/managedfields.go @@ -0,0 +1,59 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "io" + + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/runtime" +) + +// OmitManagedFieldsPrinter wraps an existing printer and omits the managed fields from the object +// before printing it. +type OmitManagedFieldsPrinter struct { + Delegate ResourcePrinter +} + +var _ ResourcePrinter = (*OmitManagedFieldsPrinter)(nil) + +func omitManagedFields(o runtime.Object) runtime.Object { + a, err := meta.Accessor(o) + if err != nil { + // The object is not a `metav1.Object`, ignore it. + return o + } + a.SetManagedFields(nil) + return o +} + +// PrintObj copies the object and omits the managed fields from the copied object before printing it. +func (p *OmitManagedFieldsPrinter) PrintObj(obj runtime.Object, w io.Writer) error { + if obj == nil { + return p.Delegate.PrintObj(obj, w) + } + if meta.IsListType(obj) { + obj = obj.DeepCopyObject() + _ = meta.EachListItem(obj, func(item runtime.Object) error { + omitManagedFields(item) + return nil + }) + } else if _, err := meta.Accessor(obj); err == nil { + obj = omitManagedFields(obj.DeepCopyObject()) + } + return p.Delegate.PrintObj(obj, w) +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/name.go b/vendor/k8s.io/cli-runtime/pkg/printers/name.go new file mode 100644 index 0000000000..086166af27 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/name.go @@ -0,0 +1,130 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "fmt" + "io" + "reflect" + "strings" + + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// NamePrinter is an implementation of ResourcePrinter which outputs "resource/name" pair of an object. +type NamePrinter struct { + // ShortOutput indicates whether an operation should be + // printed along side the "resource/name" pair for an object. + ShortOutput bool + // Operation describes the name of the action that + // took place on an object, to be included in the + // finalized "successful" message. + Operation string +} + +// PrintObj is an implementation of ResourcePrinter.PrintObj which decodes the object +// and print "resource/name" pair. If the object is a List, print all items in it. +func (p *NamePrinter) PrintObj(obj runtime.Object, w io.Writer) error { + switch castObj := obj.(type) { + case *metav1.WatchEvent: + obj = castObj.Object.Object + } + + // we use reflect.Indirect here in order to obtain the actual value from a pointer. + // using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers. + // we need an actual value in order to retrieve the package path for an object. + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + + if meta.IsListType(obj) { + // we allow unstructured lists for now because they always contain the GVK information. We should chase down + // callers and stop them from passing unflattened lists + // TODO chase the caller that is setting this and remove it. + if _, ok := obj.(*unstructured.UnstructuredList); !ok { + return fmt.Errorf("list types are not supported by name printing: %T", obj) + } + + items, err := meta.ExtractList(obj) + if err != nil { + return err + } + for _, obj := range items { + if err := p.PrintObj(obj, w); err != nil { + return err + } + } + return nil + } + + if obj.GetObjectKind().GroupVersionKind().Empty() { + return fmt.Errorf("missing apiVersion or kind; try GetObjectKind().SetGroupVersionKind() if you know the type") + } + + name := "" + if acc, err := meta.Accessor(obj); err == nil { + if n := acc.GetName(); len(n) > 0 { + name = n + } + } + + return printObj(w, name, p.Operation, p.ShortOutput, GetObjectGroupKind(obj)) +} + +func GetObjectGroupKind(obj runtime.Object) schema.GroupKind { + if obj == nil { + return schema.GroupKind{Kind: ""} + } + groupVersionKind := obj.GetObjectKind().GroupVersionKind() + if len(groupVersionKind.Kind) > 0 { + return groupVersionKind.GroupKind() + } + + if uns, ok := obj.(*unstructured.Unstructured); ok { + if len(uns.GroupVersionKind().Kind) > 0 { + return uns.GroupVersionKind().GroupKind() + } + } + + return schema.GroupKind{Kind: ""} +} + +func printObj(w io.Writer, name string, operation string, shortOutput bool, groupKind schema.GroupKind) error { + if len(groupKind.Kind) == 0 { + return fmt.Errorf("missing kind for resource with name %v", name) + } + + if len(operation) > 0 { + operation = " " + operation + } + + if shortOutput { + operation = "" + } + + if len(groupKind.Group) == 0 { + fmt.Fprintf(w, "%s/%s%s\n", strings.ToLower(groupKind.Kind), name, operation) + return nil + } + + fmt.Fprintf(w, "%s.%s/%s%s\n", strings.ToLower(groupKind.Kind), groupKind.Group, name, operation) + return nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/sourcechecker.go b/vendor/k8s.io/cli-runtime/pkg/printers/sourcechecker.go new file mode 100644 index 0000000000..e360c8fe0b --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/sourcechecker.go @@ -0,0 +1,60 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "strings" +) + +var ( + InternalObjectPrinterErr = "a versioned object must be passed to a printer" + + // disallowedPackagePrefixes contains regular expression templates + // for object package paths that are not allowed by printers. + disallowedPackagePrefixes = []string{ + "k8s.io/kubernetes/pkg/apis/", + } +) + +var InternalObjectPreventer = &illegalPackageSourceChecker{disallowedPackagePrefixes} + +func IsInternalObjectError(err error) bool { + if err == nil { + return false + } + + return err.Error() == InternalObjectPrinterErr +} + +// illegalPackageSourceChecker compares a given +// object's package path, and determines if the +// object originates from a disallowed source. +type illegalPackageSourceChecker struct { + // disallowedPrefixes is a slice of disallowed package path + // prefixes for a given runtime.Object that we are printing. + disallowedPrefixes []string +} + +func (c *illegalPackageSourceChecker) IsForbidden(pkgPath string) bool { + for _, forbiddenPrefix := range c.disallowedPrefixes { + if strings.HasPrefix(pkgPath, forbiddenPrefix) || strings.Contains(pkgPath, "/vendor/"+forbiddenPrefix) { + return true + } + } + + return false +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/tableprinter.go b/vendor/k8s.io/cli-runtime/pkg/printers/tableprinter.go new file mode 100644 index 0000000000..548596659e --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/tableprinter.go @@ -0,0 +1,589 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "fmt" + "io" + "reflect" + "strings" + "time" + + "github.com/liggitt/tabwriter" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/duration" + "k8s.io/apimachinery/pkg/watch" +) + +var _ ResourcePrinter = &HumanReadablePrinter{} + +type printHandler struct { + columnDefinitions []metav1.TableColumnDefinition + printFunc reflect.Value +} + +var ( + statusHandlerEntry = &printHandler{ + columnDefinitions: statusColumnDefinitions, + printFunc: reflect.ValueOf(printStatus), + } + + statusColumnDefinitions = []metav1.TableColumnDefinition{ + {Name: "Status", Type: "string"}, + {Name: "Reason", Type: "string"}, + {Name: "Message", Type: "string"}, + } + + defaultHandlerEntry = &printHandler{ + columnDefinitions: objectMetaColumnDefinitions, + printFunc: reflect.ValueOf(printObjectMeta), + } + + objectMetaColumnDefinitions = []metav1.TableColumnDefinition{ + {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, + {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, + } + + withEventTypePrefixColumns = []string{"EVENT"} + withNamespacePrefixColumns = []string{"NAMESPACE"} // TODO(erictune): print cluster name too. +) + +// HumanReadablePrinter is an implementation of ResourcePrinter which attempts to provide +// more elegant output. It is not threadsafe, but you may call PrintObj repeatedly; headers +// will only be printed if the object type changes. This makes it useful for printing items +// received from watches. +type HumanReadablePrinter struct { + options PrintOptions + lastType interface{} + lastColumns []metav1.TableColumnDefinition + printedHeaders bool +} + +// NewTablePrinter creates a printer suitable for calling PrintObj(). +func NewTablePrinter(options PrintOptions) ResourcePrinter { + printer := &HumanReadablePrinter{ + options: options, + } + return printer +} + +func printHeader(columnNames []string, w io.Writer) error { + if _, err := fmt.Fprintf(w, "%s\n", strings.Join(columnNames, "\t")); err != nil { + return err + } + return nil +} + +// PrintObj prints the obj in a human-friendly format according to the type of the obj. +func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) error { + + if _, found := output.(*tabwriter.Writer); !found { + w := GetNewTabWriter(output) + output = w + defer w.Flush() + } + + var eventType string + if event, isEvent := obj.(*metav1.WatchEvent); isEvent { + eventType = event.Type + obj = event.Object.Object + } + + // Parameter "obj" is a table from server; print it. + // display tables following the rules of options + if table, ok := obj.(*metav1.Table); ok { + // Do not print headers if this table has no column definitions, or they are the same as the last ones we printed + localOptions := h.options + if h.printedHeaders && (len(table.ColumnDefinitions) == 0 || reflect.DeepEqual(table.ColumnDefinitions, h.lastColumns)) { + localOptions.NoHeaders = true + } + + if len(table.ColumnDefinitions) == 0 { + // If this table has no column definitions, use the columns from the last table we printed for decoration and layout. + // This is done when receiving tables in watch events to save bandwidth. + table.ColumnDefinitions = h.lastColumns + } else if !reflect.DeepEqual(table.ColumnDefinitions, h.lastColumns) { + // If this table has column definitions, remember them for future use. + h.lastColumns = table.ColumnDefinitions + h.printedHeaders = false + } + + if len(table.Rows) > 0 { + h.printedHeaders = true + } + + if err := decorateTable(table, localOptions); err != nil { + return err + } + if len(eventType) > 0 { + if err := addColumns(beginning, table, + []metav1.TableColumnDefinition{{Name: "Event", Type: "string"}}, + []cellValueFunc{func(metav1.TableRow) (interface{}, error) { return formatEventType(eventType), nil }}, + ); err != nil { + return err + } + } + return printTable(table, output, localOptions) + } + + // Could not find print handler for "obj"; use the default or status print handler. + // Print with the default or status handler, and use the columns from the last time + var handler *printHandler + if _, isStatus := obj.(*metav1.Status); isStatus { + handler = statusHandlerEntry + } else { + handler = defaultHandlerEntry + } + + includeHeaders := h.lastType != handler && !h.options.NoHeaders + + if h.lastType != nil && h.lastType != handler && !h.options.NoHeaders { + fmt.Fprintln(output) + } + + if err := printRowsForHandlerEntry(output, handler, eventType, obj, h.options, includeHeaders); err != nil { + return err + } + h.lastType = handler + + return nil +} + +// printTable prints a table to the provided output respecting the filtering rules for options +// for wide columns and filtered rows. It filters out rows that are Completed. You should call +// decorateTable if you receive a table from a remote server before calling printTable. +func printTable(table *metav1.Table, output io.Writer, options PrintOptions) error { + if !options.NoHeaders { + // avoid printing headers if we have no rows to display + if len(table.Rows) == 0 { + return nil + } + + first := true + for _, column := range table.ColumnDefinitions { + if !options.Wide && column.Priority != 0 { + continue + } + if first { + first = false + } else { + fmt.Fprint(output, "\t") + } + fmt.Fprint(output, strings.ToUpper(column.Name)) + } + fmt.Fprintln(output) + } + for _, row := range table.Rows { + first := true + for i, cell := range row.Cells { + if i >= len(table.ColumnDefinitions) { + // https://issue.k8s.io/66379 + // don't panic in case of bad output from the server, with more cells than column definitions + break + } + column := table.ColumnDefinitions[i] + if !options.Wide && column.Priority != 0 { + continue + } + if first { + first = false + } else { + fmt.Fprint(output, "\t") + } + if cell != nil { + switch val := cell.(type) { + case string: + print := val + truncated := false + // Truncate at the first newline, carriage return or formfeed + // (treated as a newline by tabwriter). + breakchar := strings.IndexAny(print, "\f\n\r") + if breakchar >= 0 { + truncated = true + print = print[:breakchar] + } + WriteEscaped(output, print) + if truncated { + fmt.Fprint(output, "...") + } + default: + WriteEscaped(output, fmt.Sprint(val)) + } + } + } + fmt.Fprintln(output) + } + return nil +} + +type cellValueFunc func(metav1.TableRow) (interface{}, error) + +type columnAddPosition int + +const ( + beginning columnAddPosition = 1 + end columnAddPosition = 2 +) + +func addColumns(pos columnAddPosition, table *metav1.Table, columns []metav1.TableColumnDefinition, valueFuncs []cellValueFunc) error { + if len(columns) != len(valueFuncs) { + return fmt.Errorf("cannot prepend columns, unmatched value functions") + } + if len(columns) == 0 { + return nil + } + + // Compute the new rows + newRows := make([][]interface{}, len(table.Rows)) + for i := range table.Rows { + newCells := make([]interface{}, 0, len(columns)+len(table.Rows[i].Cells)) + + if pos == end { + // If we're appending, start with the existing cells, + // then add nil cells to match the number of columns + newCells = append(newCells, table.Rows[i].Cells...) + for len(newCells) < len(table.ColumnDefinitions) { + newCells = append(newCells, nil) + } + } + + // Compute cells for new columns + for _, f := range valueFuncs { + newCell, err := f(table.Rows[i]) + if err != nil { + return err + } + newCells = append(newCells, newCell) + } + + if pos == beginning { + // If we're prepending, add existing cells + newCells = append(newCells, table.Rows[i].Cells...) + } + + // Remember the new cells for this row + newRows[i] = newCells + } + + // All cells successfully computed, now replace columns and rows + newColumns := make([]metav1.TableColumnDefinition, 0, len(columns)+len(table.ColumnDefinitions)) + switch pos { + case beginning: + newColumns = append(newColumns, columns...) + newColumns = append(newColumns, table.ColumnDefinitions...) + case end: + newColumns = append(newColumns, table.ColumnDefinitions...) + newColumns = append(newColumns, columns...) + default: + return fmt.Errorf("invalid column add position: %v", pos) + } + table.ColumnDefinitions = newColumns + for i := range table.Rows { + table.Rows[i].Cells = newRows[i] + } + + return nil +} + +// decorateTable takes a table and attempts to add label columns and the +// namespace column. It will fill empty columns with nil (if the object +// does not expose metadata). It returns an error if the table cannot +// be decorated. +func decorateTable(table *metav1.Table, options PrintOptions) error { + width := len(table.ColumnDefinitions) + len(options.ColumnLabels) + if options.WithNamespace { + width++ + } + if options.ShowLabels { + width++ + } + + columns := table.ColumnDefinitions + + nameColumn := -1 + if options.WithKind && !options.Kind.Empty() { + for i := range columns { + if columns[i].Format == "name" && columns[i].Type == "string" { + nameColumn = i + break + } + } + } + + if width != len(table.ColumnDefinitions) { + columns = make([]metav1.TableColumnDefinition, 0, width) + if options.WithNamespace { + columns = append(columns, metav1.TableColumnDefinition{ + Name: "Namespace", + Type: "string", + }) + } + columns = append(columns, table.ColumnDefinitions...) + for _, label := range formatLabelHeaders(options.ColumnLabels) { + columns = append(columns, metav1.TableColumnDefinition{ + Name: label, + Type: "string", + }) + } + if options.ShowLabels { + columns = append(columns, metav1.TableColumnDefinition{ + Name: "Labels", + Type: "string", + }) + } + } + + rows := table.Rows + + includeLabels := len(options.ColumnLabels) > 0 || options.ShowLabels + if includeLabels || options.WithNamespace || nameColumn != -1 { + for i := range rows { + row := rows[i] + + if nameColumn != -1 { + row.Cells[nameColumn] = fmt.Sprintf("%s/%s", strings.ToLower(options.Kind.String()), row.Cells[nameColumn]) + } + + var m metav1.Object + if obj := row.Object.Object; obj != nil { + if acc, err := meta.Accessor(obj); err == nil { + m = acc + } + } + // if we can't get an accessor, fill out the appropriate columns with empty spaces + if m == nil { + if options.WithNamespace { + r := make([]interface{}, 1, width) + row.Cells = append(r, row.Cells...) + } + for j := 0; j < width-len(row.Cells); j++ { + row.Cells = append(row.Cells, nil) + } + rows[i] = row + continue + } + + if options.WithNamespace { + r := make([]interface{}, 1, width) + r[0] = m.GetNamespace() + row.Cells = append(r, row.Cells...) + } + if includeLabels { + row.Cells = appendLabelCells(row.Cells, m.GetLabels(), options) + } + rows[i] = row + } + } + + table.ColumnDefinitions = columns + table.Rows = rows + return nil +} + +// printRowsForHandlerEntry prints the incremental table output (headers if the current type is +// different from lastType) including all the rows in the object. It returns the current type +// or an error, if any. +func printRowsForHandlerEntry(output io.Writer, handler *printHandler, eventType string, obj runtime.Object, options PrintOptions, includeHeaders bool) error { + var results []reflect.Value + + args := []reflect.Value{reflect.ValueOf(obj), reflect.ValueOf(options)} + results = handler.printFunc.Call(args) + if !results[1].IsNil() { + return results[1].Interface().(error) + } + + if includeHeaders { + var headers []string + for _, column := range handler.columnDefinitions { + if column.Priority != 0 && !options.Wide { + continue + } + headers = append(headers, strings.ToUpper(column.Name)) + } + headers = append(headers, formatLabelHeaders(options.ColumnLabels)...) + // LABELS is always the last column. + headers = append(headers, formatShowLabelsHeader(options.ShowLabels)...) + // prepend namespace header + if options.WithNamespace { + headers = append(withNamespacePrefixColumns, headers...) + } + // prepend event type header + if len(eventType) > 0 { + headers = append(withEventTypePrefixColumns, headers...) + } + printHeader(headers, output) + } + + if results[1].IsNil() { + rows := results[0].Interface().([]metav1.TableRow) + printRows(output, eventType, rows, options) + return nil + } + return results[1].Interface().(error) +} + +var formattedEventType = map[string]string{ + string(watch.Added): "ADDED ", + string(watch.Modified): "MODIFIED", + string(watch.Deleted): "DELETED ", + string(watch.Error): "ERROR ", +} + +func formatEventType(eventType string) string { + if formatted, ok := formattedEventType[eventType]; ok { + return formatted + } + return eventType +} + +// printRows writes the provided rows to output. +func printRows(output io.Writer, eventType string, rows []metav1.TableRow, options PrintOptions) { + for _, row := range rows { + if len(eventType) > 0 { + fmt.Fprint(output, formatEventType(eventType)) + fmt.Fprint(output, "\t") + } + if options.WithNamespace { + if obj := row.Object.Object; obj != nil { + if m, err := meta.Accessor(obj); err == nil { + fmt.Fprint(output, m.GetNamespace()) + } + } + fmt.Fprint(output, "\t") + } + + for i, cell := range row.Cells { + if i != 0 { + fmt.Fprint(output, "\t") + } else { + // TODO: remove this once we drop the legacy printers + if options.WithKind && !options.Kind.Empty() { + fmt.Fprintf(output, "%s/%s", strings.ToLower(options.Kind.String()), cell) + continue + } + } + fmt.Fprint(output, cell) + } + + hasLabels := len(options.ColumnLabels) > 0 + if obj := row.Object.Object; obj != nil && (hasLabels || options.ShowLabels) { + if m, err := meta.Accessor(obj); err == nil { + for _, value := range labelValues(m.GetLabels(), options) { + output.Write([]byte("\t")) + output.Write([]byte(value)) + } + } + } + + output.Write([]byte("\n")) + } +} + +func formatLabelHeaders(columnLabels []string) []string { + formHead := make([]string, len(columnLabels)) + for i, l := range columnLabels { + p := strings.Split(l, "/") + formHead[i] = strings.ToUpper(p[len(p)-1]) + } + return formHead +} + +// headers for --show-labels=true +func formatShowLabelsHeader(showLabels bool) []string { + if showLabels { + return []string{"LABELS"} + } + return nil +} + +// labelValues returns a slice of value columns matching the requested print options. +func labelValues(itemLabels map[string]string, opts PrintOptions) []string { + var values []string + for _, key := range opts.ColumnLabels { + values = append(values, itemLabels[key]) + } + if opts.ShowLabels { + values = append(values, labels.FormatLabels(itemLabels)) + } + return values +} + +// appendLabelCells returns a slice of value columns matching the requested print options. +// Intended for use with tables. +func appendLabelCells(values []interface{}, itemLabels map[string]string, opts PrintOptions) []interface{} { + for _, key := range opts.ColumnLabels { + values = append(values, itemLabels[key]) + } + if opts.ShowLabels { + values = append(values, labels.FormatLabels(itemLabels)) + } + return values +} + +func printStatus(obj runtime.Object, options PrintOptions) ([]metav1.TableRow, error) { + status, ok := obj.(*metav1.Status) + if !ok { + return nil, fmt.Errorf("expected *v1.Status, got %T", obj) + } + return []metav1.TableRow{{ + Object: runtime.RawExtension{Object: obj}, + Cells: []interface{}{status.Status, status.Reason, status.Message}, + }}, nil +} + +func printObjectMeta(obj runtime.Object, options PrintOptions) ([]metav1.TableRow, error) { + if meta.IsListType(obj) { + rows := make([]metav1.TableRow, 0, 16) + err := meta.EachListItem(obj, func(obj runtime.Object) error { + nestedRows, err := printObjectMeta(obj, options) + if err != nil { + return err + } + rows = append(rows, nestedRows...) + return nil + }) + if err != nil { + return nil, err + } + return rows, nil + } + + rows := make([]metav1.TableRow, 0, 1) + m, err := meta.Accessor(obj) + if err != nil { + return nil, err + } + row := metav1.TableRow{ + Object: runtime.RawExtension{Object: obj}, + } + row.Cells = append(row.Cells, m.GetName(), translateTimestampSince(m.GetCreationTimestamp())) + rows = append(rows, row) + return rows, nil +} + +// translateTimestampSince returns the elapsed time since timestamp in +// human-readable approximation. +func translateTimestampSince(timestamp metav1.Time) string { + if timestamp.IsZero() { + return "" + } + + return duration.HumanDuration(time.Since(timestamp.Time)) +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/tabwriter.go b/vendor/k8s.io/cli-runtime/pkg/printers/tabwriter.go new file mode 100644 index 0000000000..21d60e1c41 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/tabwriter.go @@ -0,0 +1,36 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "io" + + "github.com/liggitt/tabwriter" +) + +const ( + tabwriterMinWidth = 6 + tabwriterWidth = 4 + tabwriterPadding = 3 + tabwriterPadChar = ' ' + tabwriterFlags = tabwriter.RememberWidths +) + +// GetNewTabWriter returns a tabwriter that translates tabbed columns in input into properly aligned text. +func GetNewTabWriter(output io.Writer) *tabwriter.Writer { + return tabwriter.NewWriter(output, tabwriterMinWidth, tabwriterWidth, tabwriterPadding, tabwriterPadChar, tabwriterFlags) +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/template.go b/vendor/k8s.io/cli-runtime/pkg/printers/template.go new file mode 100644 index 0000000000..ccff542262 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/template.go @@ -0,0 +1,118 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "encoding/base64" + "fmt" + "io" + "reflect" + "text/template" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/json" +) + +// GoTemplatePrinter is an implementation of ResourcePrinter which formats data with a Go Template. +type GoTemplatePrinter struct { + rawTemplate string + template *template.Template +} + +func NewGoTemplatePrinter(tmpl []byte) (*GoTemplatePrinter, error) { + t, err := template.New("output"). + Funcs(template.FuncMap{ + "exists": exists, + "base64decode": base64decode, + }). + Parse(string(tmpl)) + if err != nil { + return nil, err + } + return &GoTemplatePrinter{ + rawTemplate: string(tmpl), + template: t, + }, nil +} + +// AllowMissingKeys tells the template engine if missing keys are allowed. +func (p *GoTemplatePrinter) AllowMissingKeys(allow bool) { + if allow { + p.template.Option("missingkey=default") + } else { + p.template.Option("missingkey=error") + } +} + +// PrintObj formats the obj with the Go Template. +func (p *GoTemplatePrinter) PrintObj(obj runtime.Object, w io.Writer) error { + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + + var data []byte + var err error + data, err = json.Marshal(obj) + if err != nil { + return err + } + + out := map[string]interface{}{} + if err := json.Unmarshal(data, &out); err != nil { + return err + } + if err = p.safeExecute(w, out); err != nil { + // It is way easier to debug this stuff when it shows up in + // stdout instead of just stdin. So in addition to returning + // a nice error, also print useful stuff with the writer. + fmt.Fprintf(w, "Error executing template: %v. Printing more information for debugging the template:\n", err) + fmt.Fprintf(w, "\ttemplate was:\n\t\t%v\n", p.rawTemplate) + fmt.Fprintf(w, "\traw data was:\n\t\t%v\n", string(data)) + fmt.Fprintf(w, "\tobject given to template engine was:\n\t\t%+v\n\n", out) + return fmt.Errorf("error executing template %q: %v", p.rawTemplate, err) + } + return nil +} + +// safeExecute tries to execute the template, but catches panics and returns an error +// should the template engine panic. +func (p *GoTemplatePrinter) safeExecute(w io.Writer, obj interface{}) error { + var panicErr error + // Sorry for the double anonymous function. There's probably a clever way + // to do this that has the defer'd func setting the value to be returned, but + // that would be even less obvious. + retErr := func() error { + defer func() { + if x := recover(); x != nil { + panicErr = fmt.Errorf("caught panic: %+v", x) + } + }() + return p.template.Execute(w, obj) + }() + if panicErr != nil { + return panicErr + } + return retErr +} + +func base64decode(v string) (string, error) { + data, err := base64.StdEncoding.DecodeString(v) + if err != nil { + return "", fmt.Errorf("base64 decode failed: %v", err) + } + return string(data), nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/terminal.go b/vendor/k8s.io/cli-runtime/pkg/printers/terminal.go new file mode 100644 index 0000000000..9dc904e59c --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/terminal.go @@ -0,0 +1,75 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "io" + "os" + "runtime" + "strings" + + "github.com/moby/term" +) + +// terminalEscaper replaces ANSI escape sequences and other terminal special +// characters to avoid terminal escape character attacks (issue #101695). +var terminalEscaper = strings.NewReplacer("\x1b", "^[", "\r", "\\r") + +// WriteEscaped replaces unsafe terminal characters with replacement strings +// and writes them to the given writer. +func WriteEscaped(writer io.Writer, output string) error { + _, err := terminalEscaper.WriteString(writer, output) + return err +} + +// EscapeTerminal escapes terminal special characters in a human readable (but +// non-reversible) format. +func EscapeTerminal(in string) string { + return terminalEscaper.Replace(in) +} + +// IsTerminal returns whether the passed object is a terminal or not +func IsTerminal(i interface{}) bool { + _, terminal := term.GetFdInfo(i) + return terminal +} + +// AllowsColorOutput returns true if the specified writer is a terminal and +// the process environment indicates color output is supported and desired. +func AllowsColorOutput(w io.Writer) bool { + if !IsTerminal(w) { + return false + } + + // https://en.wikipedia.org/wiki/Computer_terminal#Dumb_terminals + if os.Getenv("TERM") == "dumb" { + return false + } + + // https://no-color.org/ + if _, nocolor := os.LookupEnv("NO_COLOR"); nocolor { + return false + } + + // On Windows WT_SESSION is set by the modern terminal component. + // Older terminals have poor support for UTF-8, VT escape codes, etc. + if runtime.GOOS == "windows" && os.Getenv("WT_SESSION") == "" { + return false + } + + return true +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/typesetter.go b/vendor/k8s.io/cli-runtime/pkg/printers/typesetter.go new file mode 100644 index 0000000000..8d2d9b56ec --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/typesetter.go @@ -0,0 +1,95 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "fmt" + "io" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// TypeSetterPrinter is an implementation of ResourcePrinter wraps another printer with types set on the objects +type TypeSetterPrinter struct { + Delegate ResourcePrinter + + Typer runtime.ObjectTyper +} + +// NewTypeSetter constructs a wrapping printer with required params +func NewTypeSetter(typer runtime.ObjectTyper) *TypeSetterPrinter { + return &TypeSetterPrinter{Typer: typer} +} + +// PrintObj is an implementation of ResourcePrinter.PrintObj which sets type information on the obj for the duration +// of printing. It is NOT threadsafe. +func (p *TypeSetterPrinter) PrintObj(obj runtime.Object, w io.Writer) error { + if obj == nil { + return p.Delegate.PrintObj(obj, w) + } + if !obj.GetObjectKind().GroupVersionKind().Empty() { + return p.Delegate.PrintObj(obj, w) + } + + // we were empty coming in, make sure we're empty going out. This makes the call thread-unsafe + defer func() { + obj.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{}) + }() + + gvks, _, err := p.Typer.ObjectKinds(obj) + if err != nil { + // printers wrapped by us expect to find the type information present + return fmt.Errorf("missing apiVersion or kind and cannot assign it; %v", err) + } + + for _, gvk := range gvks { + if len(gvk.Kind) == 0 { + continue + } + if len(gvk.Version) == 0 || gvk.Version == runtime.APIVersionInternal { + continue + } + obj.GetObjectKind().SetGroupVersionKind(gvk) + break + } + + return p.Delegate.PrintObj(obj, w) +} + +// ToPrinter returns a printer (not threadsafe!) that has been wrapped +func (p *TypeSetterPrinter) ToPrinter(delegate ResourcePrinter) ResourcePrinter { + if p == nil { + return delegate + } + + p.Delegate = delegate + return p +} + +// WrapToPrinter wraps the common ToPrinter method +func (p *TypeSetterPrinter) WrapToPrinter(delegate ResourcePrinter, err error) (ResourcePrinter, error) { + if err != nil { + return delegate, err + } + if p == nil { + return delegate, nil + } + + p.Delegate = delegate + return p, nil +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/warningprinter.go b/vendor/k8s.io/cli-runtime/pkg/printers/warningprinter.go new file mode 100644 index 0000000000..b3a8264f78 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/warningprinter.go @@ -0,0 +1,55 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "fmt" + "io" +) + +const ( + yellowColor = "\u001b[33;1m" + resetColor = "\u001b[0m" +) + +type WarningPrinter struct { + // out is the writer to output warnings to + out io.Writer + // opts contains options controlling warning output + opts WarningPrinterOptions +} + +// WarningPrinterOptions controls the behavior of a WarningPrinter constructed using NewWarningPrinter() +type WarningPrinterOptions struct { + // Color indicates that warning output can include ANSI color codes + Color bool +} + +// NewWarningPrinter returns an implementation of warningPrinter that outputs warnings to the specified writer. +func NewWarningPrinter(out io.Writer, opts WarningPrinterOptions) *WarningPrinter { + h := &WarningPrinter{out: out, opts: opts} + return h +} + +// Print prints warnings to the configured writer. +func (w *WarningPrinter) Print(message string) { + if w.opts.Color { + fmt.Fprintf(w.out, "%sWarning:%s %s\n", yellowColor, resetColor, message) + } else { + fmt.Fprintf(w.out, "Warning: %s\n", message) + } +} diff --git a/vendor/k8s.io/cli-runtime/pkg/printers/yaml.go b/vendor/k8s.io/cli-runtime/pkg/printers/yaml.go new file mode 100644 index 0000000000..9c444bdc26 --- /dev/null +++ b/vendor/k8s.io/cli-runtime/pkg/printers/yaml.go @@ -0,0 +1,85 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package printers + +import ( + "fmt" + "io" + "reflect" + "sync/atomic" + + "sigs.k8s.io/yaml" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// YAMLPrinter is an implementation of ResourcePrinter which outputs an object as YAML. +// The input object is assumed to be in the internal version of an API and is converted +// to the given version first. +// If PrintObj() is called multiple times, objects are separated with a '---' separator. +type YAMLPrinter struct { + printCount int64 +} + +// PrintObj prints the data as YAML. +func (p *YAMLPrinter) PrintObj(obj runtime.Object, w io.Writer) error { + // we use reflect.Indirect here in order to obtain the actual value from a pointer. + // we need an actual value in order to retrieve the package path for an object. + // using reflect.Indirect indiscriminately is valid here, as all runtime.Objects are supposed to be pointers. + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + + count := atomic.AddInt64(&p.printCount, 1) + if count > 1 { + if _, err := w.Write([]byte("---\n")); err != nil { + return err + } + } + + switch obj := obj.(type) { + case *metav1.WatchEvent: + if InternalObjectPreventer.IsForbidden(reflect.Indirect(reflect.ValueOf(obj.Object.Object)).Type().PkgPath()) { + return fmt.Errorf(InternalObjectPrinterErr) + } + data, err := yaml.Marshal(obj) + if err != nil { + return err + } + _, err = w.Write(data) + return err + case *runtime.Unknown: + data, err := yaml.JSONToYAML(obj.Raw) + if err != nil { + return err + } + _, err = w.Write(data) + return err + } + + if obj.GetObjectKind().GroupVersionKind().Empty() { + return fmt.Errorf("missing apiVersion or kind; try GetObjectKind().SetGroupVersionKind() if you know the type") + } + + output, err := yaml.Marshal(obj) + if err != nil { + return err + } + _, err = fmt.Fprint(w, string(output)) + return err +} diff --git a/vendor/k8s.io/client-go/third_party/forked/golang/LICENSE b/vendor/k8s.io/client-go/third_party/forked/golang/LICENSE new file mode 100644 index 0000000000..6a66aea5ea --- /dev/null +++ b/vendor/k8s.io/client-go/third_party/forked/golang/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/k8s.io/client-go/third_party/forked/golang/PATENTS b/vendor/k8s.io/client-go/third_party/forked/golang/PATENTS new file mode 100644 index 0000000000..733099041f --- /dev/null +++ b/vendor/k8s.io/client-go/third_party/forked/golang/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/k8s.io/client-go/third_party/forked/golang/template/exec.go b/vendor/k8s.io/client-go/third_party/forked/golang/template/exec.go new file mode 100644 index 0000000000..7cf29524ce --- /dev/null +++ b/vendor/k8s.io/client-go/third_party/forked/golang/template/exec.go @@ -0,0 +1,52 @@ +//This package is copied from Go library text/template. +//The original private functions indirect and printableValue +//are exported as public functions. +package template + +import ( + "fmt" + "reflect" +) + +var ( + errorType = reflect.TypeOf((*error)(nil)).Elem() + fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() +) + +// Indirect returns the item at the end of indirection, and a bool to indicate if it's nil. +// We indirect through pointers and empty interfaces (only) because +// non-empty interfaces have methods we might need. +func Indirect(v reflect.Value) (rv reflect.Value, isNil bool) { + for ; v.Kind() == reflect.Pointer || v.Kind() == reflect.Interface; v = v.Elem() { + if v.IsNil() { + return v, true + } + if v.Kind() == reflect.Interface && v.NumMethod() > 0 { + break + } + } + return v, false +} + +// PrintableValue returns the, possibly indirected, interface value inside v that +// is best for a call to formatted printer. +func PrintableValue(v reflect.Value) (interface{}, bool) { + if v.Kind() == reflect.Pointer { + v, _ = Indirect(v) // fmt.Fprint handles nil. + } + if !v.IsValid() { + return "", true + } + + if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) { + if v.CanAddr() && (reflect.PointerTo(v.Type()).Implements(errorType) || reflect.PointerTo(v.Type()).Implements(fmtStringerType)) { + v = v.Addr() + } else { + switch v.Kind() { + case reflect.Chan, reflect.Func: + return nil, false + } + } + } + return v.Interface(), true +} diff --git a/vendor/k8s.io/client-go/third_party/forked/golang/template/funcs.go b/vendor/k8s.io/client-go/third_party/forked/golang/template/funcs.go new file mode 100644 index 0000000000..f0c8e712ca --- /dev/null +++ b/vendor/k8s.io/client-go/third_party/forked/golang/template/funcs.go @@ -0,0 +1,177 @@ +//This package is copied from Go library text/template. +//The original private functions eq, ge, gt, le, lt, and ne +//are exported as public functions. +package template + +import ( + "errors" + "reflect" +) + +var ( + errBadComparisonType = errors.New("invalid type for comparison") + errBadComparison = errors.New("incompatible types for comparison") + errNoComparison = errors.New("missing argument for comparison") +) + +type kind int + +const ( + invalidKind kind = iota + boolKind + complexKind + intKind + floatKind + integerKind + stringKind + uintKind +) + +func basicKind(v reflect.Value) (kind, error) { + switch v.Kind() { + case reflect.Bool: + return boolKind, nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return intKind, nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return uintKind, nil + case reflect.Float32, reflect.Float64: + return floatKind, nil + case reflect.Complex64, reflect.Complex128: + return complexKind, nil + case reflect.String: + return stringKind, nil + } + return invalidKind, errBadComparisonType +} + +// Equal evaluates the comparison a == b || a == c || ... +func Equal(arg1 interface{}, arg2 ...interface{}) (bool, error) { + v1 := reflect.ValueOf(arg1) + k1, err := basicKind(v1) + if err != nil { + return false, err + } + if len(arg2) == 0 { + return false, errNoComparison + } + for _, arg := range arg2 { + v2 := reflect.ValueOf(arg) + k2, err := basicKind(v2) + if err != nil { + return false, err + } + truth := false + if k1 != k2 { + // Special case: Can compare integer values regardless of type's sign. + switch { + case k1 == intKind && k2 == uintKind: + truth = v1.Int() >= 0 && uint64(v1.Int()) == v2.Uint() + case k1 == uintKind && k2 == intKind: + truth = v2.Int() >= 0 && v1.Uint() == uint64(v2.Int()) + default: + return false, errBadComparison + } + } else { + switch k1 { + case boolKind: + truth = v1.Bool() == v2.Bool() + case complexKind: + truth = v1.Complex() == v2.Complex() + case floatKind: + truth = v1.Float() == v2.Float() + case intKind: + truth = v1.Int() == v2.Int() + case stringKind: + truth = v1.String() == v2.String() + case uintKind: + truth = v1.Uint() == v2.Uint() + default: + panic("invalid kind") + } + } + if truth { + return true, nil + } + } + return false, nil +} + +// NotEqual evaluates the comparison a != b. +func NotEqual(arg1, arg2 interface{}) (bool, error) { + // != is the inverse of ==. + equal, err := Equal(arg1, arg2) + return !equal, err +} + +// Less evaluates the comparison a < b. +func Less(arg1, arg2 interface{}) (bool, error) { + v1 := reflect.ValueOf(arg1) + k1, err := basicKind(v1) + if err != nil { + return false, err + } + v2 := reflect.ValueOf(arg2) + k2, err := basicKind(v2) + if err != nil { + return false, err + } + truth := false + if k1 != k2 { + // Special case: Can compare integer values regardless of type's sign. + switch { + case k1 == intKind && k2 == uintKind: + truth = v1.Int() < 0 || uint64(v1.Int()) < v2.Uint() + case k1 == uintKind && k2 == intKind: + truth = v2.Int() >= 0 && v1.Uint() < uint64(v2.Int()) + default: + return false, errBadComparison + } + } else { + switch k1 { + case boolKind, complexKind: + return false, errBadComparisonType + case floatKind: + truth = v1.Float() < v2.Float() + case intKind: + truth = v1.Int() < v2.Int() + case stringKind: + truth = v1.String() < v2.String() + case uintKind: + truth = v1.Uint() < v2.Uint() + default: + panic("invalid kind") + } + } + return truth, nil +} + +// LessEqual evaluates the comparison <= b. +func LessEqual(arg1, arg2 interface{}) (bool, error) { + // <= is < or ==. + lessThan, err := Less(arg1, arg2) + if lessThan || err != nil { + return lessThan, err + } + return Equal(arg1, arg2) +} + +// Greater evaluates the comparison a > b. +func Greater(arg1, arg2 interface{}) (bool, error) { + // > is the inverse of <=. + lessOrEqual, err := LessEqual(arg1, arg2) + if err != nil { + return false, err + } + return !lessOrEqual, nil +} + +// GreaterEqual evaluates the comparison a >= b. +func GreaterEqual(arg1, arg2 interface{}) (bool, error) { + // >= is the inverse of <. + lessThan, err := Less(arg1, arg2) + if err != nil { + return false, err + } + return !lessThan, nil +} diff --git a/vendor/k8s.io/client-go/tools/remotecommand/OWNERS b/vendor/k8s.io/client-go/tools/remotecommand/OWNERS new file mode 100644 index 0000000000..3078483072 --- /dev/null +++ b/vendor/k8s.io/client-go/tools/remotecommand/OWNERS @@ -0,0 +1,10 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - aojea + - liggitt + - seans3 +reviewers: + - aojea + - liggitt + - seans3 diff --git a/vendor/k8s.io/client-go/tools/remotecommand/doc.go b/vendor/k8s.io/client-go/tools/remotecommand/doc.go new file mode 100644 index 0000000000..ac06a9cd37 --- /dev/null +++ b/vendor/k8s.io/client-go/tools/remotecommand/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2015 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package remotecommand adds support for executing commands in containers, +// with support for separate stdin, stdout, and stderr streams, as well as +// TTY. +package remotecommand // import "k8s.io/client-go/tools/remotecommand" diff --git a/vendor/k8s.io/client-go/tools/remotecommand/errorstream.go b/vendor/k8s.io/client-go/tools/remotecommand/errorstream.go new file mode 100644 index 0000000000..e60dd7cdc7 --- /dev/null +++ b/vendor/k8s.io/client-go/tools/remotecommand/errorstream.go @@ -0,0 +1,54 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remotecommand + +import ( + "fmt" + "io" + + "k8s.io/apimachinery/pkg/util/runtime" +) + +// errorStreamDecoder interprets the data on the error channel and creates a go error object from it. +type errorStreamDecoder interface { + decode(message []byte) error +} + +// watchErrorStream watches the errorStream for remote command error data, +// decodes it with the given errorStreamDecoder, sends the decoded error (or nil if the remote +// command exited successfully) to the returned error channel, and closes it. +// This function returns immediately. +func watchErrorStream(errorStream io.Reader, d errorStreamDecoder) chan error { + errorChan := make(chan error) + + go func() { + defer runtime.HandleCrash() + + message, err := io.ReadAll(errorStream) + switch { + case err != nil && err != io.EOF: + errorChan <- fmt.Errorf("error reading from error stream: %s", err) + case len(message) > 0: + errorChan <- d.decode(message) + default: + errorChan <- nil + } + close(errorChan) + }() + + return errorChan +} diff --git a/vendor/k8s.io/client-go/tools/remotecommand/fallback.go b/vendor/k8s.io/client-go/tools/remotecommand/fallback.go new file mode 100644 index 0000000000..3efde3c588 --- /dev/null +++ b/vendor/k8s.io/client-go/tools/remotecommand/fallback.go @@ -0,0 +1,57 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remotecommand + +import ( + "context" +) + +var _ Executor = &FallbackExecutor{} + +type FallbackExecutor struct { + primary Executor + secondary Executor + shouldFallback func(error) bool +} + +// NewFallbackExecutor creates an Executor that first attempts to use the +// WebSocketExecutor, falling back to the legacy SPDYExecutor if the initial +// websocket "StreamWithContext" call fails. +// func NewFallbackExecutor(config *restclient.Config, method string, url *url.URL) (Executor, error) { +func NewFallbackExecutor(primary, secondary Executor, shouldFallback func(error) bool) (Executor, error) { + return &FallbackExecutor{ + primary: primary, + secondary: secondary, + shouldFallback: shouldFallback, + }, nil +} + +// Stream is deprecated. Please use "StreamWithContext". +func (f *FallbackExecutor) Stream(options StreamOptions) error { + return f.StreamWithContext(context.Background(), options) +} + +// StreamWithContext initially attempts to call "StreamWithContext" using the +// primary executor, falling back to calling the secondary executor if the +// initial primary call to upgrade to a websocket connection fails. +func (f *FallbackExecutor) StreamWithContext(ctx context.Context, options StreamOptions) error { + err := f.primary.StreamWithContext(ctx, options) + if f.shouldFallback(err) { + return f.secondary.StreamWithContext(ctx, options) + } + return err +} diff --git a/vendor/k8s.io/client-go/tools/remotecommand/reader.go b/vendor/k8s.io/client-go/tools/remotecommand/reader.go new file mode 100644 index 0000000000..d1f1be34c9 --- /dev/null +++ b/vendor/k8s.io/client-go/tools/remotecommand/reader.go @@ -0,0 +1,41 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remotecommand + +import ( + "io" +) + +// readerWrapper delegates to an io.Reader so that only the io.Reader interface is implemented, +// to keep io.Copy from doing things we don't want when copying from the reader to the data stream. +// +// If the Stdin io.Reader provided to remotecommand implements a WriteTo function (like bytes.Buffer does[1]), +// io.Copy calls that method[2] to attempt to write the entire buffer to the stream in one call. +// That results in an oversized call to spdystream.Stream#Write [3], +// which results in a single oversized data frame[4] that is too large. +// +// [1] https://golang.org/pkg/bytes/#Buffer.WriteTo +// [2] https://golang.org/pkg/io/#Copy +// [3] https://github.com/kubernetes/kubernetes/blob/90295640ef87db9daa0144c5617afe889e7992b2/vendor/github.com/docker/spdystream/stream.go#L66-L73 +// [4] https://github.com/kubernetes/kubernetes/blob/90295640ef87db9daa0144c5617afe889e7992b2/vendor/github.com/docker/spdystream/spdy/write.go#L302-L304 +type readerWrapper struct { + reader io.Reader +} + +func (r readerWrapper) Read(p []byte) (int, error) { + return r.reader.Read(p) +} diff --git a/vendor/k8s.io/client-go/tools/remotecommand/remotecommand.go b/vendor/k8s.io/client-go/tools/remotecommand/remotecommand.go new file mode 100644 index 0000000000..1ae67729be --- /dev/null +++ b/vendor/k8s.io/client-go/tools/remotecommand/remotecommand.go @@ -0,0 +1,58 @@ +/* +Copyright 2015 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remotecommand + +import ( + "context" + "io" + "net/http" + + "k8s.io/apimachinery/pkg/util/httpstream" +) + +// StreamOptions holds information pertaining to the current streaming session: +// input/output streams, if the client is requesting a TTY, and a terminal size queue to +// support terminal resizing. +type StreamOptions struct { + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer + Tty bool + TerminalSizeQueue TerminalSizeQueue +} + +// Executor is an interface for transporting shell-style streams. +type Executor interface { + // Deprecated: use StreamWithContext instead to avoid possible resource leaks. + // See https://github.com/kubernetes/kubernetes/pull/103177 for details. + Stream(options StreamOptions) error + + // StreamWithContext initiates the transport of the standard shell streams. It will + // transport any non-nil stream to a remote system, and return an error if a problem + // occurs. If tty is set, the stderr stream is not used (raw TTY manages stdout and + // stderr over the stdout stream). + // The context controls the entire lifetime of stream execution. + StreamWithContext(ctx context.Context, options StreamOptions) error +} + +type streamCreator interface { + CreateStream(headers http.Header) (httpstream.Stream, error) +} + +type streamProtocolHandler interface { + stream(conn streamCreator) error +} diff --git a/vendor/k8s.io/client-go/tools/remotecommand/resize.go b/vendor/k8s.io/client-go/tools/remotecommand/resize.go new file mode 100644 index 0000000000..c838f21ba6 --- /dev/null +++ b/vendor/k8s.io/client-go/tools/remotecommand/resize.go @@ -0,0 +1,33 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remotecommand + +// TerminalSize and TerminalSizeQueue was a part of k8s.io/kubernetes/pkg/util/term +// and were moved in order to decouple client from other term dependencies + +// TerminalSize represents the width and height of a terminal. +type TerminalSize struct { + Width uint16 + Height uint16 +} + +// TerminalSizeQueue is capable of returning terminal resize events as they occur. +type TerminalSizeQueue interface { + // Next returns the new terminal size after the terminal has been resized. It returns nil when + // monitoring has been stopped. + Next() *TerminalSize +} diff --git a/vendor/k8s.io/client-go/tools/remotecommand/spdy.go b/vendor/k8s.io/client-go/tools/remotecommand/spdy.go new file mode 100644 index 0000000000..c2bfcf8a65 --- /dev/null +++ b/vendor/k8s.io/client-go/tools/remotecommand/spdy.go @@ -0,0 +1,171 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remotecommand + +import ( + "context" + "fmt" + "net/http" + "net/url" + + "k8s.io/apimachinery/pkg/util/httpstream" + "k8s.io/apimachinery/pkg/util/remotecommand" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/transport/spdy" + "k8s.io/klog/v2" +) + +// spdyStreamExecutor handles transporting standard shell streams over an httpstream connection. +type spdyStreamExecutor struct { + upgrader spdy.Upgrader + transport http.RoundTripper + + method string + url *url.URL + protocols []string + rejectRedirects bool // if true, receiving redirect from upstream is an error +} + +// NewSPDYExecutor connects to the provided server and upgrades the connection to +// multiplexed bidirectional streams. +func NewSPDYExecutor(config *restclient.Config, method string, url *url.URL) (Executor, error) { + wrapper, upgradeRoundTripper, err := spdy.RoundTripperFor(config) + if err != nil { + return nil, err + } + return NewSPDYExecutorForTransports(wrapper, upgradeRoundTripper, method, url) +} + +// NewSPDYExecutorRejectRedirects returns an Executor that will upgrade the future +// connection to a SPDY bi-directional streaming connection when calling "Stream" (deprecated) +// or "StreamWithContext" (preferred). Additionally, if the upstream server returns a redirect +// during the attempted upgrade in these "Stream" calls, an error is returned. +func NewSPDYExecutorRejectRedirects(transport http.RoundTripper, upgrader spdy.Upgrader, method string, url *url.URL) (Executor, error) { + executor, err := NewSPDYExecutorForTransports(transport, upgrader, method, url) + if err != nil { + return nil, err + } + spdyExecutor := executor.(*spdyStreamExecutor) + spdyExecutor.rejectRedirects = true + return spdyExecutor, nil +} + +// NewSPDYExecutorForTransports connects to the provided server using the given transport, +// upgrades the response using the given upgrader to multiplexed bidirectional streams. +func NewSPDYExecutorForTransports(transport http.RoundTripper, upgrader spdy.Upgrader, method string, url *url.URL) (Executor, error) { + return NewSPDYExecutorForProtocols( + transport, upgrader, method, url, + remotecommand.StreamProtocolV5Name, + remotecommand.StreamProtocolV4Name, + remotecommand.StreamProtocolV3Name, + remotecommand.StreamProtocolV2Name, + remotecommand.StreamProtocolV1Name, + ) +} + +// NewSPDYExecutorForProtocols connects to the provided server and upgrades the connection to +// multiplexed bidirectional streams using only the provided protocols. Exposed for testing, most +// callers should use NewSPDYExecutor or NewSPDYExecutorForTransports. +func NewSPDYExecutorForProtocols(transport http.RoundTripper, upgrader spdy.Upgrader, method string, url *url.URL, protocols ...string) (Executor, error) { + return &spdyStreamExecutor{ + upgrader: upgrader, + transport: transport, + method: method, + url: url, + protocols: protocols, + }, nil +} + +// Stream opens a protocol streamer to the server and streams until a client closes +// the connection or the server disconnects. +func (e *spdyStreamExecutor) Stream(options StreamOptions) error { + return e.StreamWithContext(context.Background(), options) +} + +// newConnectionAndStream creates a new SPDY connection and a stream protocol handler upon it. +func (e *spdyStreamExecutor) newConnectionAndStream(ctx context.Context, options StreamOptions) (httpstream.Connection, streamProtocolHandler, error) { + req, err := http.NewRequestWithContext(ctx, e.method, e.url.String(), nil) + if err != nil { + return nil, nil, fmt.Errorf("error creating request: %v", err) + } + + client := http.Client{Transport: e.transport} + if e.rejectRedirects { + client.CheckRedirect = func(req *http.Request, via []*http.Request) error { + return fmt.Errorf("redirect not allowed") + } + } + conn, protocol, err := spdy.Negotiate( + e.upgrader, + &client, + req, + e.protocols..., + ) + if err != nil { + return nil, nil, err + } + + var streamer streamProtocolHandler + + switch protocol { + case remotecommand.StreamProtocolV5Name: + streamer = newStreamProtocolV5(options) + case remotecommand.StreamProtocolV4Name: + streamer = newStreamProtocolV4(options) + case remotecommand.StreamProtocolV3Name: + streamer = newStreamProtocolV3(options) + case remotecommand.StreamProtocolV2Name: + streamer = newStreamProtocolV2(options) + case "": + klog.V(4).Infof("The server did not negotiate a streaming protocol version. Falling back to %s", remotecommand.StreamProtocolV1Name) + fallthrough + case remotecommand.StreamProtocolV1Name: + streamer = newStreamProtocolV1(options) + } + + return conn, streamer, nil +} + +// StreamWithContext opens a protocol streamer to the server and streams until a client closes +// the connection or the server disconnects or the context is done. +func (e *spdyStreamExecutor) StreamWithContext(ctx context.Context, options StreamOptions) error { + conn, streamer, err := e.newConnectionAndStream(ctx, options) + if err != nil { + return err + } + defer conn.Close() + + panicChan := make(chan any, 1) + errorChan := make(chan error, 1) + go func() { + defer func() { + if p := recover(); p != nil { + panicChan <- p + } + }() + errorChan <- streamer.stream(conn) + }() + + select { + case p := <-panicChan: + panic(p) + case err := <-errorChan: + return err + case <-ctx.Done(): + return ctx.Err() + } +} diff --git a/vendor/k8s.io/client-go/tools/remotecommand/v1.go b/vendor/k8s.io/client-go/tools/remotecommand/v1.go new file mode 100644 index 0000000000..efa9a6c990 --- /dev/null +++ b/vendor/k8s.io/client-go/tools/remotecommand/v1.go @@ -0,0 +1,159 @@ +/* +Copyright 2015 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remotecommand + +import ( + "fmt" + "io" + "net/http" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/httpstream" + "k8s.io/klog/v2" +) + +// streamProtocolV1 implements the first version of the streaming exec & attach +// protocol. This version has some bugs, such as not being able to detect when +// non-interactive stdin data has ended. See https://issues.k8s.io/13394 and +// https://issues.k8s.io/13395 for more details. +type streamProtocolV1 struct { + StreamOptions + + errorStream httpstream.Stream + remoteStdin httpstream.Stream + remoteStdout httpstream.Stream + remoteStderr httpstream.Stream +} + +var _ streamProtocolHandler = &streamProtocolV1{} + +func newStreamProtocolV1(options StreamOptions) streamProtocolHandler { + return &streamProtocolV1{ + StreamOptions: options, + } +} + +func (p *streamProtocolV1) stream(conn streamCreator) error { + doneChan := make(chan struct{}, 2) + errorChan := make(chan error) + + cp := func(s string, dst io.Writer, src io.Reader) { + klog.V(6).Infof("Copying %s", s) + defer klog.V(6).Infof("Done copying %s", s) + if _, err := io.Copy(dst, src); err != nil && err != io.EOF { + klog.Errorf("Error copying %s: %v", s, err) + } + if s == v1.StreamTypeStdout || s == v1.StreamTypeStderr { + doneChan <- struct{}{} + } + } + + // set up all the streams first + var err error + headers := http.Header{} + headers.Set(v1.StreamType, v1.StreamTypeError) + p.errorStream, err = conn.CreateStream(headers) + if err != nil { + return err + } + defer p.errorStream.Reset() + + // Create all the streams first, then start the copy goroutines. The server doesn't start its copy + // goroutines until it's received all of the streams. If the client creates the stdin stream and + // immediately begins copying stdin data to the server, it's possible to overwhelm and wedge the + // spdy frame handler in the server so that it is full of unprocessed frames. The frames aren't + // getting processed because the server hasn't started its copying, and it won't do that until it + // gets all the streams. By creating all the streams first, we ensure that the server is ready to + // process data before the client starts sending any. See https://issues.k8s.io/16373 for more info. + if p.Stdin != nil { + headers.Set(v1.StreamType, v1.StreamTypeStdin) + p.remoteStdin, err = conn.CreateStream(headers) + if err != nil { + return err + } + defer p.remoteStdin.Reset() + } + + if p.Stdout != nil { + headers.Set(v1.StreamType, v1.StreamTypeStdout) + p.remoteStdout, err = conn.CreateStream(headers) + if err != nil { + return err + } + defer p.remoteStdout.Reset() + } + + if p.Stderr != nil && !p.Tty { + headers.Set(v1.StreamType, v1.StreamTypeStderr) + p.remoteStderr, err = conn.CreateStream(headers) + if err != nil { + return err + } + defer p.remoteStderr.Reset() + } + + // now that all the streams have been created, proceed with reading & copying + + // always read from errorStream + go func() { + message, err := io.ReadAll(p.errorStream) + if err != nil && err != io.EOF { + errorChan <- fmt.Errorf("Error reading from error stream: %s", err) + return + } + if len(message) > 0 { + errorChan <- fmt.Errorf("Error executing remote command: %s", message) + return + } + }() + + if p.Stdin != nil { + // TODO this goroutine will never exit cleanly (the io.Copy never unblocks) + // because stdin is not closed until the process exits. If we try to call + // stdin.Close(), it returns no error but doesn't unblock the copy. It will + // exit when the process exits, instead. + go cp(v1.StreamTypeStdin, p.remoteStdin, readerWrapper{p.Stdin}) + } + + waitCount := 0 + completedStreams := 0 + + if p.Stdout != nil { + waitCount++ + go cp(v1.StreamTypeStdout, p.Stdout, p.remoteStdout) + } + + if p.Stderr != nil && !p.Tty { + waitCount++ + go cp(v1.StreamTypeStderr, p.Stderr, p.remoteStderr) + } + +Loop: + for { + select { + case <-doneChan: + completedStreams++ + if completedStreams == waitCount { + break Loop + } + case err := <-errorChan: + return err + } + } + + return nil +} diff --git a/vendor/k8s.io/client-go/tools/remotecommand/v2.go b/vendor/k8s.io/client-go/tools/remotecommand/v2.go new file mode 100644 index 0000000000..d54612f4c2 --- /dev/null +++ b/vendor/k8s.io/client-go/tools/remotecommand/v2.go @@ -0,0 +1,199 @@ +/* +Copyright 2015 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remotecommand + +import ( + "fmt" + "io" + "net/http" + "sync" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/runtime" +) + +// streamProtocolV2 implements version 2 of the streaming protocol for attach +// and exec. The original streaming protocol was metav1. As a result, this +// version is referred to as version 2, even though it is the first actual +// numbered version. +type streamProtocolV2 struct { + StreamOptions + + errorStream io.Reader + remoteStdin io.ReadWriteCloser + remoteStdout io.Reader + remoteStderr io.Reader +} + +var _ streamProtocolHandler = &streamProtocolV2{} + +func newStreamProtocolV2(options StreamOptions) streamProtocolHandler { + return &streamProtocolV2{ + StreamOptions: options, + } +} + +func (p *streamProtocolV2) createStreams(conn streamCreator) error { + var err error + headers := http.Header{} + + // set up error stream + headers.Set(v1.StreamType, v1.StreamTypeError) + p.errorStream, err = conn.CreateStream(headers) + if err != nil { + return err + } + + // set up stdin stream + if p.Stdin != nil { + headers.Set(v1.StreamType, v1.StreamTypeStdin) + p.remoteStdin, err = conn.CreateStream(headers) + if err != nil { + return err + } + } + + // set up stdout stream + if p.Stdout != nil { + headers.Set(v1.StreamType, v1.StreamTypeStdout) + p.remoteStdout, err = conn.CreateStream(headers) + if err != nil { + return err + } + } + + // set up stderr stream + if p.Stderr != nil && !p.Tty { + headers.Set(v1.StreamType, v1.StreamTypeStderr) + p.remoteStderr, err = conn.CreateStream(headers) + if err != nil { + return err + } + } + return nil +} + +func (p *streamProtocolV2) copyStdin() { + if p.Stdin != nil { + var once sync.Once + + // copy from client's stdin to container's stdin + go func() { + defer runtime.HandleCrash() + + // if p.stdin is noninteractive, p.g. `echo abc | kubectl exec -i -- cat`, make sure + // we close remoteStdin as soon as the copy from p.stdin to remoteStdin finishes. Otherwise + // the executed command will remain running. + defer once.Do(func() { p.remoteStdin.Close() }) + + if _, err := io.Copy(p.remoteStdin, readerWrapper{p.Stdin}); err != nil { + runtime.HandleError(err) + } + }() + + // read from remoteStdin until the stream is closed. this is essential to + // be able to exit interactive sessions cleanly and not leak goroutines or + // hang the client's terminal. + // + // TODO we aren't using go-dockerclient any more; revisit this to determine if it's still + // required by engine-api. + // + // go-dockerclient's current hijack implementation + // (https://github.com/fsouza/go-dockerclient/blob/89f3d56d93788dfe85f864a44f85d9738fca0670/client.go#L564) + // waits for all three streams (stdin/stdout/stderr) to finish copying + // before returning. When hijack finishes copying stdout/stderr, it calls + // Close() on its side of remoteStdin, which allows this copy to complete. + // When that happens, we must Close() on our side of remoteStdin, to + // allow the copy in hijack to complete, and hijack to return. + go func() { + defer runtime.HandleCrash() + defer once.Do(func() { p.remoteStdin.Close() }) + + // this "copy" doesn't actually read anything - it's just here to wait for + // the server to close remoteStdin. + if _, err := io.Copy(io.Discard, p.remoteStdin); err != nil { + runtime.HandleError(err) + } + }() + } +} + +func (p *streamProtocolV2) copyStdout(wg *sync.WaitGroup) { + if p.Stdout == nil { + return + } + + wg.Add(1) + go func() { + defer runtime.HandleCrash() + defer wg.Done() + // make sure, packet in queue can be consumed. + // block in queue may lead to deadlock in conn.server + // issue: https://github.com/kubernetes/kubernetes/issues/96339 + defer io.Copy(io.Discard, p.remoteStdout) + + if _, err := io.Copy(p.Stdout, p.remoteStdout); err != nil { + runtime.HandleError(err) + } + }() +} + +func (p *streamProtocolV2) copyStderr(wg *sync.WaitGroup) { + if p.Stderr == nil || p.Tty { + return + } + + wg.Add(1) + go func() { + defer runtime.HandleCrash() + defer wg.Done() + defer io.Copy(io.Discard, p.remoteStderr) + + if _, err := io.Copy(p.Stderr, p.remoteStderr); err != nil { + runtime.HandleError(err) + } + }() +} + +func (p *streamProtocolV2) stream(conn streamCreator) error { + if err := p.createStreams(conn); err != nil { + return err + } + + // now that all the streams have been created, proceed with reading & copying + + errorChan := watchErrorStream(p.errorStream, &errorDecoderV2{}) + + p.copyStdin() + + var wg sync.WaitGroup + p.copyStdout(&wg) + p.copyStderr(&wg) + + // we're waiting for stdout/stderr to finish copying + wg.Wait() + + // waits for errorStream to finish reading with an error or nil + return <-errorChan +} + +// errorDecoderV2 interprets the error channel data as plain text. +type errorDecoderV2 struct{} + +func (d *errorDecoderV2) decode(message []byte) error { + return fmt.Errorf("error executing remote command: %s", message) +} diff --git a/vendor/k8s.io/client-go/tools/remotecommand/v3.go b/vendor/k8s.io/client-go/tools/remotecommand/v3.go new file mode 100644 index 0000000000..846dd24a5e --- /dev/null +++ b/vendor/k8s.io/client-go/tools/remotecommand/v3.go @@ -0,0 +1,111 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remotecommand + +import ( + "encoding/json" + "io" + "net/http" + "sync" + + "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/runtime" +) + +// streamProtocolV3 implements version 3 of the streaming protocol for attach +// and exec. This version adds support for resizing the container's terminal. +type streamProtocolV3 struct { + *streamProtocolV2 + + resizeStream io.Writer +} + +var _ streamProtocolHandler = &streamProtocolV3{} + +func newStreamProtocolV3(options StreamOptions) streamProtocolHandler { + return &streamProtocolV3{ + streamProtocolV2: newStreamProtocolV2(options).(*streamProtocolV2), + } +} + +func (p *streamProtocolV3) createStreams(conn streamCreator) error { + // set up the streams from v2 + if err := p.streamProtocolV2.createStreams(conn); err != nil { + return err + } + + // set up resize stream + if p.Tty { + headers := http.Header{} + headers.Set(v1.StreamType, v1.StreamTypeResize) + var err error + p.resizeStream, err = conn.CreateStream(headers) + if err != nil { + return err + } + } + + return nil +} + +func (p *streamProtocolV3) handleResizes() { + if p.resizeStream == nil || p.TerminalSizeQueue == nil { + return + } + go func() { + defer runtime.HandleCrash() + + encoder := json.NewEncoder(p.resizeStream) + for { + size := p.TerminalSizeQueue.Next() + if size == nil { + return + } + if err := encoder.Encode(&size); err != nil { + runtime.HandleError(err) + } + } + }() +} + +func (p *streamProtocolV3) stream(conn streamCreator) error { + if err := p.createStreams(conn); err != nil { + return err + } + + // now that all the streams have been created, proceed with reading & copying + + errorChan := watchErrorStream(p.errorStream, &errorDecoderV3{}) + + p.handleResizes() + + p.copyStdin() + + var wg sync.WaitGroup + p.copyStdout(&wg) + p.copyStderr(&wg) + + // we're waiting for stdout/stderr to finish copying + wg.Wait() + + // waits for errorStream to finish reading with an error or nil + return <-errorChan +} + +type errorDecoderV3 struct { + errorDecoderV2 +} diff --git a/vendor/k8s.io/client-go/tools/remotecommand/v4.go b/vendor/k8s.io/client-go/tools/remotecommand/v4.go new file mode 100644 index 0000000000..69ca934a0d --- /dev/null +++ b/vendor/k8s.io/client-go/tools/remotecommand/v4.go @@ -0,0 +1,119 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remotecommand + +import ( + "encoding/json" + "errors" + "fmt" + "strconv" + "sync" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/remotecommand" + "k8s.io/client-go/util/exec" +) + +// streamProtocolV4 implements version 4 of the streaming protocol for attach +// and exec. This version adds support for exit codes on the error stream through +// the use of metav1.Status instead of plain text messages. +type streamProtocolV4 struct { + *streamProtocolV3 +} + +var _ streamProtocolHandler = &streamProtocolV4{} + +func newStreamProtocolV4(options StreamOptions) streamProtocolHandler { + return &streamProtocolV4{ + streamProtocolV3: newStreamProtocolV3(options).(*streamProtocolV3), + } +} + +func (p *streamProtocolV4) createStreams(conn streamCreator) error { + return p.streamProtocolV3.createStreams(conn) +} + +func (p *streamProtocolV4) handleResizes() { + p.streamProtocolV3.handleResizes() +} + +func (p *streamProtocolV4) stream(conn streamCreator) error { + if err := p.createStreams(conn); err != nil { + return err + } + + // now that all the streams have been created, proceed with reading & copying + + errorChan := watchErrorStream(p.errorStream, &errorDecoderV4{}) + + p.handleResizes() + + p.copyStdin() + + var wg sync.WaitGroup + p.copyStdout(&wg) + p.copyStderr(&wg) + + // we're waiting for stdout/stderr to finish copying + wg.Wait() + + // waits for errorStream to finish reading with an error or nil + return <-errorChan +} + +// errorDecoderV4 interprets the json-marshaled metav1.Status on the error channel +// and creates an exec.ExitError from it. +type errorDecoderV4 struct{} + +func (d *errorDecoderV4) decode(message []byte) error { + status := metav1.Status{} + err := json.Unmarshal(message, &status) + if err != nil { + return fmt.Errorf("error stream protocol error: %v in %q", err, string(message)) + } + switch status.Status { + case metav1.StatusSuccess: + return nil + case metav1.StatusFailure: + if status.Reason == remotecommand.NonZeroExitCodeReason { + if status.Details == nil { + return errors.New("error stream protocol error: details must be set") + } + for i := range status.Details.Causes { + c := &status.Details.Causes[i] + if c.Type != remotecommand.ExitCodeCauseType { + continue + } + + rc, err := strconv.ParseUint(c.Message, 10, 8) + if err != nil { + return fmt.Errorf("error stream protocol error: invalid exit code value %q", c.Message) + } + return exec.CodeExitError{ + Err: fmt.Errorf("command terminated with exit code %d", rc), + Code: int(rc), + } + } + + return fmt.Errorf("error stream protocol error: no %s cause given", remotecommand.ExitCodeCauseType) + } + default: + return errors.New("error stream protocol error: unknown error") + } + + return fmt.Errorf(status.Message) +} diff --git a/vendor/k8s.io/client-go/tools/remotecommand/v5.go b/vendor/k8s.io/client-go/tools/remotecommand/v5.go new file mode 100644 index 0000000000..4da7bfb139 --- /dev/null +++ b/vendor/k8s.io/client-go/tools/remotecommand/v5.go @@ -0,0 +1,35 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remotecommand + +// streamProtocolV5 add support for V5 of the remote command subprotocol. +// For the streamProtocolHandler, this version is the same as V4. +type streamProtocolV5 struct { + *streamProtocolV4 +} + +var _ streamProtocolHandler = &streamProtocolV5{} + +func newStreamProtocolV5(options StreamOptions) streamProtocolHandler { + return &streamProtocolV5{ + streamProtocolV4: newStreamProtocolV4(options).(*streamProtocolV4), + } +} + +func (p *streamProtocolV5) stream(conn streamCreator) error { + return p.streamProtocolV4.stream(conn) +} diff --git a/vendor/k8s.io/client-go/tools/remotecommand/websocket.go b/vendor/k8s.io/client-go/tools/remotecommand/websocket.go new file mode 100644 index 0000000000..1dc679cb1f --- /dev/null +++ b/vendor/k8s.io/client-go/tools/remotecommand/websocket.go @@ -0,0 +1,515 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package remotecommand + +import ( + "context" + "errors" + "fmt" + "io" + "net" + "net/http" + "sync" + "time" + + gwebsocket "github.com/gorilla/websocket" + + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/httpstream" + "k8s.io/apimachinery/pkg/util/remotecommand" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/transport/websocket" + "k8s.io/klog/v2" +) + +// writeDeadline defines the time that a client-side write to the websocket +// connection must complete before an i/o timeout occurs. +const writeDeadline = 60 * time.Second + +var ( + _ Executor = &wsStreamExecutor{} + _ streamCreator = &wsStreamCreator{} + _ httpstream.Stream = &stream{} + + streamType2streamID = map[string]byte{ + v1.StreamTypeStdin: remotecommand.StreamStdIn, + v1.StreamTypeStdout: remotecommand.StreamStdOut, + v1.StreamTypeStderr: remotecommand.StreamStdErr, + v1.StreamTypeError: remotecommand.StreamErr, + v1.StreamTypeResize: remotecommand.StreamResize, + } +) + +const ( + // pingPeriod defines how often a heartbeat "ping" message is sent. + pingPeriod = 5 * time.Second + // pingReadDeadline defines the time waiting for a response heartbeat + // "pong" message before a timeout error occurs for websocket reading. + // This duration must always be greater than the "pingPeriod". By defining + // this deadline in terms of the ping period, we are essentially saying + // we can drop "X" (e.g. 12) pings before firing the timeout. + pingReadDeadline = (pingPeriod * 12) + (1 * time.Second) +) + +// wsStreamExecutor handles transporting standard shell streams over an httpstream connection. +type wsStreamExecutor struct { + transport http.RoundTripper + upgrader websocket.ConnectionHolder + method string + url string + // requested protocols in priority order (e.g. v5.channel.k8s.io before v4.channel.k8s.io). + protocols []string + // selected protocol from the handshake process; could be empty string if handshake fails. + negotiated string + // period defines how often a "ping" heartbeat message is sent to the other endpoint. + heartbeatPeriod time.Duration + // deadline defines the amount of time before "pong" response must be received. + heartbeatDeadline time.Duration +} + +func NewWebSocketExecutor(config *restclient.Config, method, url string) (Executor, error) { + // Only supports V5 protocol for correct version skew functionality. + // Previous api servers will proxy upgrade requests to legacy websocket + // servers on container runtimes which support V1-V4. These legacy + // websocket servers will not handle the new CLOSE signal. + return NewWebSocketExecutorForProtocols(config, method, url, remotecommand.StreamProtocolV5Name) +} + +// NewWebSocketExecutorForProtocols allows to execute commands via a WebSocket connection. +func NewWebSocketExecutorForProtocols(config *restclient.Config, method, url string, protocols ...string) (Executor, error) { + transport, upgrader, err := websocket.RoundTripperFor(config) + if err != nil { + return nil, fmt.Errorf("error creating websocket transports: %v", err) + } + return &wsStreamExecutor{ + transport: transport, + upgrader: upgrader, + method: method, + url: url, + protocols: protocols, + heartbeatPeriod: pingPeriod, + heartbeatDeadline: pingReadDeadline, + }, nil +} + +// Deprecated: use StreamWithContext instead to avoid possible resource leaks. +// See https://github.com/kubernetes/kubernetes/pull/103177 for details. +func (e *wsStreamExecutor) Stream(options StreamOptions) error { + return e.StreamWithContext(context.Background(), options) +} + +// StreamWithContext upgrades an HTTPRequest to a WebSocket connection, and starts the various +// goroutines to implement the necessary streams over the connection. The "options" parameter +// defines which streams are requested. Returns an error if one occurred. This method is NOT +// safe to run concurrently with the same executor (because of the state stored in the upgrader). +func (e *wsStreamExecutor) StreamWithContext(ctx context.Context, options StreamOptions) error { + req, err := http.NewRequestWithContext(ctx, e.method, e.url, nil) + if err != nil { + return err + } + conn, err := websocket.Negotiate(e.transport, e.upgrader, req, e.protocols...) + if err != nil { + return err + } + if conn == nil { + panic(fmt.Errorf("websocket connection is nil")) + } + defer conn.Close() + e.negotiated = conn.Subprotocol() + klog.V(4).Infof("The subprotocol is %s", e.negotiated) + + var streamer streamProtocolHandler + switch e.negotiated { + case remotecommand.StreamProtocolV5Name: + streamer = newStreamProtocolV5(options) + case remotecommand.StreamProtocolV4Name: + streamer = newStreamProtocolV4(options) + case remotecommand.StreamProtocolV3Name: + streamer = newStreamProtocolV3(options) + case remotecommand.StreamProtocolV2Name: + streamer = newStreamProtocolV2(options) + case "": + klog.V(4).Infof("The server did not negotiate a streaming protocol version. Falling back to %s", remotecommand.StreamProtocolV1Name) + fallthrough + case remotecommand.StreamProtocolV1Name: + streamer = newStreamProtocolV1(options) + } + + panicChan := make(chan any, 1) + errorChan := make(chan error, 1) + go func() { + defer func() { + if p := recover(); p != nil { + panicChan <- p + } + }() + creator := newWSStreamCreator(conn) + go creator.readDemuxLoop( + e.upgrader.DataBufferSize(), + e.heartbeatPeriod, + e.heartbeatDeadline, + ) + errorChan <- streamer.stream(creator) + }() + + select { + case p := <-panicChan: + panic(p) + case err := <-errorChan: + return err + case <-ctx.Done(): + return ctx.Err() + } +} + +type wsStreamCreator struct { + conn *gwebsocket.Conn + // Protects writing to websocket connection; reading is lock-free + connWriteLock sync.Mutex + // map of stream id to stream; multiple streams read/write the connection + streams map[byte]*stream + streamsMu sync.Mutex + // setStreamErr holds the error to return to anyone calling setStreams. + // this is populated in closeAllStreamReaders + setStreamErr error +} + +func newWSStreamCreator(conn *gwebsocket.Conn) *wsStreamCreator { + return &wsStreamCreator{ + conn: conn, + streams: map[byte]*stream{}, + } +} + +func (c *wsStreamCreator) getStream(id byte) *stream { + c.streamsMu.Lock() + defer c.streamsMu.Unlock() + return c.streams[id] +} + +func (c *wsStreamCreator) setStream(id byte, s *stream) error { + c.streamsMu.Lock() + defer c.streamsMu.Unlock() + if c.setStreamErr != nil { + return c.setStreamErr + } + c.streams[id] = s + return nil +} + +// CreateStream uses id from passed headers to create a stream over "c.conn" connection. +// Returns a Stream structure or nil and an error if one occurred. +func (c *wsStreamCreator) CreateStream(headers http.Header) (httpstream.Stream, error) { + streamType := headers.Get(v1.StreamType) + id, ok := streamType2streamID[streamType] + if !ok { + return nil, fmt.Errorf("unknown stream type: %s", streamType) + } + if s := c.getStream(id); s != nil { + return nil, fmt.Errorf("duplicate stream for type %s", streamType) + } + reader, writer := io.Pipe() + s := &stream{ + headers: headers, + readPipe: reader, + writePipe: writer, + conn: c.conn, + connWriteLock: &c.connWriteLock, + id: id, + } + if err := c.setStream(id, s); err != nil { + _ = s.writePipe.Close() + _ = s.readPipe.Close() + return nil, err + } + return s, nil +} + +// readDemuxLoop is the lock-free reading processor for this endpoint of the websocket +// connection. This loop reads the connection, and demultiplexes the data +// into one of the individual stream pipes (by checking the stream id). This +// loop can *not* be run concurrently, because there can only be one websocket +// connection reader at a time (a read mutex would provide no benefit). +func (c *wsStreamCreator) readDemuxLoop(bufferSize int, period time.Duration, deadline time.Duration) { + // Initialize and start the ping/pong heartbeat. + h := newHeartbeat(c.conn, period, deadline) + // Set initial timeout for websocket connection reading. + if err := c.conn.SetReadDeadline(time.Now().Add(deadline)); err != nil { + klog.Errorf("Websocket initial setting read deadline failed %v", err) + return + } + go h.start() + // Buffer size must correspond to the same size allocated + // for the read buffer during websocket client creation. A + // difference can cause incomplete connection reads. + readBuffer := make([]byte, bufferSize) + for { + // NextReader() only returns data messages (BinaryMessage or Text + // Message). Even though this call will never return control frames + // such as ping, pong, or close, this call is necessary for these + // message types to be processed. There can only be one reader + // at a time, so this reader loop must *not* be run concurrently; + // there is no lock for reading. Calling "NextReader()" before the + // current reader has been processed will close the current reader. + // If the heartbeat read deadline times out, this "NextReader()" will + // return an i/o error, and error handling will clean up. + messageType, r, err := c.conn.NextReader() + if err != nil { + websocketErr, ok := err.(*gwebsocket.CloseError) + if ok && websocketErr.Code == gwebsocket.CloseNormalClosure { + err = nil // readers will get io.EOF as it's a normal closure + } else { + err = fmt.Errorf("next reader: %w", err) + } + c.closeAllStreamReaders(err) + return + } + // All remote command protocols send/receive only binary data messages. + if messageType != gwebsocket.BinaryMessage { + c.closeAllStreamReaders(fmt.Errorf("unexpected message type: %d", messageType)) + return + } + // It's ok to read just a single byte because the underlying library wraps the actual + // connection with a buffered reader anyway. + _, err = io.ReadFull(r, readBuffer[:1]) + if err != nil { + c.closeAllStreamReaders(fmt.Errorf("read stream id: %w", err)) + return + } + streamID := readBuffer[0] + s := c.getStream(streamID) + if s == nil { + klog.Errorf("Unknown stream id %d, discarding message", streamID) + continue + } + for { + nr, errRead := r.Read(readBuffer) + if nr > 0 { + // Write the data to the stream's pipe. This can block. + _, errWrite := s.writePipe.Write(readBuffer[:nr]) + if errWrite != nil { + // Pipe must have been closed by the stream user. + // Nothing to do, discard the message. + break + } + } + if errRead != nil { + if errRead == io.EOF { + break + } + c.closeAllStreamReaders(fmt.Errorf("read message: %w", err)) + return + } + } + } +} + +// closeAllStreamReaders closes readers in all streams. +// This unblocks all stream.Read() calls, and keeps any future streams from being created. +func (c *wsStreamCreator) closeAllStreamReaders(err error) { + c.streamsMu.Lock() + defer c.streamsMu.Unlock() + for _, s := range c.streams { + // Closing writePipe unblocks all readPipe.Read() callers and prevents any future writes. + _ = s.writePipe.CloseWithError(err) + } + // ensure callers to setStreams receive an error after this point + if err != nil { + c.setStreamErr = err + } else { + c.setStreamErr = fmt.Errorf("closed all streams") + } +} + +type stream struct { + headers http.Header + readPipe *io.PipeReader + writePipe *io.PipeWriter + // conn is used for writing directly into the connection. + // Is nil after Close() / Reset() to prevent future writes. + conn *gwebsocket.Conn + // connWriteLock protects conn against concurrent write operations. There must be a single writer and a single reader only. + // The mutex is shared across all streams because the underlying connection is shared. + connWriteLock *sync.Mutex + id byte +} + +func (s *stream) Read(p []byte) (n int, err error) { + return s.readPipe.Read(p) +} + +// Write writes directly to the underlying WebSocket connection. +func (s *stream) Write(p []byte) (n int, err error) { + klog.V(4).Infof("Write() on stream %d", s.id) + defer klog.V(4).Infof("Write() done on stream %d", s.id) + s.connWriteLock.Lock() + defer s.connWriteLock.Unlock() + if s.conn == nil { + return 0, fmt.Errorf("write on closed stream %d", s.id) + } + err = s.conn.SetWriteDeadline(time.Now().Add(writeDeadline)) + if err != nil { + klog.V(7).Infof("Websocket setting write deadline failed %v", err) + return 0, err + } + // Message writer buffers the message data, so we don't need to do that ourselves. + // Just write id and the data as two separate writes to avoid allocating an intermediate buffer. + w, err := s.conn.NextWriter(gwebsocket.BinaryMessage) + if err != nil { + return 0, err + } + defer func() { + if w != nil { + w.Close() + } + }() + _, err = w.Write([]byte{s.id}) + if err != nil { + return 0, err + } + n, err = w.Write(p) + if err != nil { + return n, err + } + err = w.Close() + w = nil + return n, err +} + +// Close half-closes the stream, indicating this side is finished with the stream. +func (s *stream) Close() error { + klog.V(4).Infof("Close() on stream %d", s.id) + defer klog.V(4).Infof("Close() done on stream %d", s.id) + s.connWriteLock.Lock() + defer s.connWriteLock.Unlock() + if s.conn == nil { + return fmt.Errorf("Close() on already closed stream %d", s.id) + } + // Communicate the CLOSE stream signal to the other websocket endpoint. + err := s.conn.WriteMessage(gwebsocket.BinaryMessage, []byte{remotecommand.StreamClose, s.id}) + s.conn = nil + return err +} + +func (s *stream) Reset() error { + klog.V(4).Infof("Reset() on stream %d", s.id) + defer klog.V(4).Infof("Reset() done on stream %d", s.id) + s.Close() + return s.writePipe.Close() +} + +func (s *stream) Headers() http.Header { + return s.headers +} + +func (s *stream) Identifier() uint32 { + return uint32(s.id) +} + +// heartbeat encasulates data necessary for the websocket ping/pong heartbeat. This +// heartbeat works by setting a read deadline on the websocket connection, then +// pushing this deadline into the future for every successful heartbeat. If the +// heartbeat "pong" fails to respond within the deadline, then the "NextReader()" call +// inside the "readDemuxLoop" will return an i/o error prompting a connection close +// and cleanup. +type heartbeat struct { + conn *gwebsocket.Conn + // period defines how often a "ping" heartbeat message is sent to the other endpoint + period time.Duration + // closing the "closer" channel will clean up the heartbeat timers + closer chan struct{} + // optional data to send with "ping" message + message []byte + // optionally received data message with "pong" message, same as sent with ping + pongMessage []byte +} + +// newHeartbeat creates heartbeat structure encapsulating fields necessary to +// run the websocket connection ping/pong mechanism and sets up handlers on +// the websocket connection. +func newHeartbeat(conn *gwebsocket.Conn, period time.Duration, deadline time.Duration) *heartbeat { + h := &heartbeat{ + conn: conn, + period: period, + closer: make(chan struct{}), + } + // Set up handler for receiving returned "pong" message from other endpoint + // by pushing the read deadline into the future. The "msg" received could + // be empty. + h.conn.SetPongHandler(func(msg string) error { + // Push the read deadline into the future. + klog.V(8).Infof("Pong message received (%s)--resetting read deadline", msg) + err := h.conn.SetReadDeadline(time.Now().Add(deadline)) + if err != nil { + klog.Errorf("Websocket setting read deadline failed %v", err) + return err + } + if len(msg) > 0 { + h.pongMessage = []byte(msg) + } + return nil + }) + // Set up handler to cleanup timers when this endpoint receives "Close" message. + closeHandler := h.conn.CloseHandler() + h.conn.SetCloseHandler(func(code int, text string) error { + close(h.closer) + return closeHandler(code, text) + }) + return h +} + +// setMessage is optional data sent with "ping" heartbeat. According to the websocket RFC +// this data sent with "ping" message should be returned in "pong" message. +func (h *heartbeat) setMessage(msg string) { + h.message = []byte(msg) +} + +// start the heartbeat by setting up necesssary handlers and looping by sending "ping" +// message every "period" until the "closer" channel is closed. +func (h *heartbeat) start() { + // Loop to continually send "ping" message through websocket connection every "period". + t := time.NewTicker(h.period) + defer t.Stop() + for { + select { + case <-h.closer: + klog.V(8).Infof("closed channel--returning") + return + case <-t.C: + // "WriteControl" does not need to be protected by a mutex. According to + // gorilla/websockets library docs: "The Close and WriteControl methods can + // be called concurrently with all other methods." + if err := h.conn.WriteControl(gwebsocket.PingMessage, h.message, time.Now().Add(pingReadDeadline)); err == nil { + klog.V(8).Infof("Websocket Ping succeeeded") + } else { + klog.Errorf("Websocket Ping failed: %v", err) + if errors.Is(err, gwebsocket.ErrCloseSent) { + // we continue because c.conn.CloseChan will manage closing the connection already + continue + } else if e, ok := err.(net.Error); ok && e.Timeout() { + // Continue, in case this is a transient failure. + // c.conn.CloseChan above will tell us when the connection is + // actually closed. + // If Temporary function hadn't been deprecated, we would have used it. + // But most of temporary errors are timeout errors anyway. + continue + } + return + } + } + } +} diff --git a/vendor/k8s.io/client-go/transport/spdy/spdy.go b/vendor/k8s.io/client-go/transport/spdy/spdy.go new file mode 100644 index 0000000000..9fddc6c5f2 --- /dev/null +++ b/vendor/k8s.io/client-go/transport/spdy/spdy.go @@ -0,0 +1,107 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package spdy + +import ( + "fmt" + "net/http" + "net/url" + "time" + + "k8s.io/apimachinery/pkg/util/httpstream" + "k8s.io/apimachinery/pkg/util/httpstream/spdy" + restclient "k8s.io/client-go/rest" +) + +// Upgrader validates a response from the server after a SPDY upgrade. +type Upgrader interface { + // NewConnection validates the response and creates a new Connection. + NewConnection(resp *http.Response) (httpstream.Connection, error) +} + +// RoundTripperFor returns a round tripper and upgrader to use with SPDY. +func RoundTripperFor(config *restclient.Config) (http.RoundTripper, Upgrader, error) { + tlsConfig, err := restclient.TLSConfigFor(config) + if err != nil { + return nil, nil, err + } + proxy := http.ProxyFromEnvironment + if config.Proxy != nil { + proxy = config.Proxy + } + upgradeRoundTripper, err := spdy.NewRoundTripperWithConfig(spdy.RoundTripperConfig{ + TLS: tlsConfig, + Proxier: proxy, + PingPeriod: time.Second * 5, + UpgradeTransport: nil, + }) + if err != nil { + return nil, nil, err + } + wrapper, err := restclient.HTTPWrappersForConfig(config, upgradeRoundTripper) + if err != nil { + return nil, nil, err + } + return wrapper, upgradeRoundTripper, nil +} + +// dialer implements the httpstream.Dialer interface. +type dialer struct { + client *http.Client + upgrader Upgrader + method string + url *url.URL +} + +var _ httpstream.Dialer = &dialer{} + +// NewDialer will create a dialer that connects to the provided URL and upgrades the connection to SPDY. +func NewDialer(upgrader Upgrader, client *http.Client, method string, url *url.URL) httpstream.Dialer { + return &dialer{ + client: client, + upgrader: upgrader, + method: method, + url: url, + } +} + +func (d *dialer) Dial(protocols ...string) (httpstream.Connection, string, error) { + req, err := http.NewRequest(d.method, d.url.String(), nil) + if err != nil { + return nil, "", fmt.Errorf("error creating request: %v", err) + } + return Negotiate(d.upgrader, d.client, req, protocols...) +} + +// Negotiate opens a connection to a remote server and attempts to negotiate +// a SPDY connection. Upon success, it returns the connection and the protocol selected by +// the server. The client transport must use the upgradeRoundTripper - see RoundTripperFor. +func Negotiate(upgrader Upgrader, client *http.Client, req *http.Request, protocols ...string) (httpstream.Connection, string, error) { + for i := range protocols { + req.Header.Add(httpstream.HeaderProtocolVersion, protocols[i]) + } + resp, err := client.Do(req) + if err != nil { + return nil, "", fmt.Errorf("error sending request: %v", err) + } + defer resp.Body.Close() + conn, err := upgrader.NewConnection(resp) + if err != nil { + return nil, "", err + } + return conn, resp.Header.Get(httpstream.HeaderProtocolVersion), nil +} diff --git a/vendor/k8s.io/client-go/transport/websocket/roundtripper.go b/vendor/k8s.io/client-go/transport/websocket/roundtripper.go new file mode 100644 index 0000000000..624dd5473a --- /dev/null +++ b/vendor/k8s.io/client-go/transport/websocket/roundtripper.go @@ -0,0 +1,182 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package websocket + +import ( + "crypto/tls" + "errors" + "fmt" + "net/http" + "net/url" + + gwebsocket "github.com/gorilla/websocket" + + "k8s.io/apimachinery/pkg/util/httpstream" + "k8s.io/apimachinery/pkg/util/httpstream/wsstream" + utilnet "k8s.io/apimachinery/pkg/util/net" + restclient "k8s.io/client-go/rest" + "k8s.io/client-go/transport" +) + +var ( + _ utilnet.TLSClientConfigHolder = &RoundTripper{} + _ http.RoundTripper = &RoundTripper{} +) + +// ConnectionHolder defines functions for structure providing +// access to the websocket connection. +type ConnectionHolder interface { + DataBufferSize() int + Connection() *gwebsocket.Conn +} + +// RoundTripper knows how to establish a connection to a remote WebSocket endpoint and make it available for use. +// RoundTripper must not be reused. +type RoundTripper struct { + // TLSConfig holds the TLS configuration settings to use when connecting + // to the remote server. + TLSConfig *tls.Config + + // Proxier specifies a function to return a proxy for a given + // Request. If the function returns a non-nil error, the + // request is aborted with the provided error. + // If Proxy is nil or returns a nil *URL, no proxy is used. + Proxier func(req *http.Request) (*url.URL, error) + + // Conn holds the WebSocket connection after a round trip. + Conn *gwebsocket.Conn +} + +// Connection returns the stored websocket connection. +func (rt *RoundTripper) Connection() *gwebsocket.Conn { + return rt.Conn +} + +// DataBufferSize returns the size of buffers for the +// websocket connection. +func (rt *RoundTripper) DataBufferSize() int { + return 32 * 1024 +} + +// TLSClientConfig implements pkg/util/net.TLSClientConfigHolder. +func (rt *RoundTripper) TLSClientConfig() *tls.Config { + return rt.TLSConfig +} + +// RoundTrip connects to the remote websocket using the headers in the request and the TLS +// configuration from the config +func (rt *RoundTripper) RoundTrip(request *http.Request) (retResp *http.Response, retErr error) { + defer func() { + if request.Body != nil { + err := request.Body.Close() + if retErr == nil { + retErr = err + } + } + }() + + // set the protocol version directly on the dialer from the header + protocolVersions := request.Header[wsstream.WebSocketProtocolHeader] + delete(request.Header, wsstream.WebSocketProtocolHeader) + + dialer := gwebsocket.Dialer{ + Proxy: rt.Proxier, + TLSClientConfig: rt.TLSConfig, + Subprotocols: protocolVersions, + ReadBufferSize: rt.DataBufferSize() + 1024, // add space for the protocol byte indicating which channel the data is for + WriteBufferSize: rt.DataBufferSize() + 1024, // add space for the protocol byte indicating which channel the data is for + } + switch request.URL.Scheme { + case "https": + request.URL.Scheme = "wss" + case "http": + request.URL.Scheme = "ws" + default: + return nil, fmt.Errorf("unknown url scheme: %s", request.URL.Scheme) + } + wsConn, resp, err := dialer.DialContext(request.Context(), request.URL.String(), request.Header) + if err != nil { + if errors.Is(err, gwebsocket.ErrBadHandshake) { + return nil, &httpstream.UpgradeFailureError{Cause: err} + } + return nil, err + } + + // Ensure we got back a protocol we understand + foundProtocol := false + for _, protocolVersion := range protocolVersions { + if protocolVersion == wsConn.Subprotocol() { + foundProtocol = true + break + } + } + if !foundProtocol { + wsConn.Close() // nolint:errcheck + return nil, &httpstream.UpgradeFailureError{Cause: fmt.Errorf("invalid protocol, expected one of %q, got %q", protocolVersions, wsConn.Subprotocol())} + } + + rt.Conn = wsConn + + return resp, nil +} + +// RoundTripperFor transforms the passed rest config into a wrapped roundtripper, as well +// as a pointer to the websocket RoundTripper. The websocket RoundTripper contains the +// websocket connection after RoundTrip() on the wrapper. Returns an error if there is +// a problem creating the round trippers. +func RoundTripperFor(config *restclient.Config) (http.RoundTripper, ConnectionHolder, error) { + transportCfg, err := config.TransportConfig() + if err != nil { + return nil, nil, err + } + tlsConfig, err := transport.TLSConfigFor(transportCfg) + if err != nil { + return nil, nil, err + } + proxy := config.Proxy + if proxy == nil { + proxy = utilnet.NewProxierWithNoProxyCIDR(http.ProxyFromEnvironment) + } + + upgradeRoundTripper := &RoundTripper{ + TLSConfig: tlsConfig, + Proxier: proxy, + } + wrapper, err := transport.HTTPWrappersForConfig(transportCfg, upgradeRoundTripper) + if err != nil { + return nil, nil, err + } + return wrapper, upgradeRoundTripper, nil +} + +// Negotiate opens a connection to a remote server and attempts to negotiate +// a WebSocket connection. Upon success, it returns the negotiated connection. +// The round tripper rt must use the WebSocket round tripper wsRt - see RoundTripperFor. +func Negotiate(rt http.RoundTripper, connectionInfo ConnectionHolder, req *http.Request, protocols ...string) (*gwebsocket.Conn, error) { + // Plumb protocols to RoundTripper#RoundTrip + req.Header[wsstream.WebSocketProtocolHeader] = protocols + resp, err := rt.RoundTrip(req) + if err != nil { + return nil, err + } + err = resp.Body.Close() + if err != nil { + connectionInfo.Connection().Close() + return nil, fmt.Errorf("error closing response body: %v", err) + } + return connectionInfo.Connection(), nil +} diff --git a/vendor/k8s.io/client-go/util/exec/exec.go b/vendor/k8s.io/client-go/util/exec/exec.go new file mode 100644 index 0000000000..d170badb60 --- /dev/null +++ b/vendor/k8s.io/client-go/util/exec/exec.go @@ -0,0 +1,52 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package exec + +// ExitError is an interface that presents an API similar to os.ProcessState, which is +// what ExitError from os/exec is. This is designed to make testing a bit easier and +// probably loses some of the cross-platform properties of the underlying library. +type ExitError interface { + String() string + Error() string + Exited() bool + ExitStatus() int +} + +// CodeExitError is an implementation of ExitError consisting of an error object +// and an exit code (the upper bits of os.exec.ExitStatus). +type CodeExitError struct { + Err error + Code int +} + +var _ ExitError = CodeExitError{} + +func (e CodeExitError) Error() string { + return e.Err.Error() +} + +func (e CodeExitError) String() string { + return e.Err.Error() +} + +func (e CodeExitError) Exited() bool { + return true +} + +func (e CodeExitError) ExitStatus() int { + return e.Code +} diff --git a/vendor/k8s.io/client-go/util/jsonpath/doc.go b/vendor/k8s.io/client-go/util/jsonpath/doc.go new file mode 100644 index 0000000000..0effb15c41 --- /dev/null +++ b/vendor/k8s.io/client-go/util/jsonpath/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2015 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// package jsonpath is a template engine using jsonpath syntax, +// which can be seen at http://goessner.net/articles/JsonPath/. +// In addition, it has {range} {end} function to iterate list and slice. +package jsonpath // import "k8s.io/client-go/util/jsonpath" diff --git a/vendor/k8s.io/client-go/util/jsonpath/jsonpath.go b/vendor/k8s.io/client-go/util/jsonpath/jsonpath.go new file mode 100644 index 0000000000..86a3d6dde9 --- /dev/null +++ b/vendor/k8s.io/client-go/util/jsonpath/jsonpath.go @@ -0,0 +1,582 @@ +/* +Copyright 2015 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package jsonpath + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "reflect" + "strings" + + "k8s.io/client-go/third_party/forked/golang/template" +) + +type JSONPath struct { + name string + parser *Parser + beginRange int + inRange int + endRange int + + lastEndNode *Node + + allowMissingKeys bool + outputJSON bool +} + +// New creates a new JSONPath with the given name. +func New(name string) *JSONPath { + return &JSONPath{ + name: name, + beginRange: 0, + inRange: 0, + endRange: 0, + } +} + +// AllowMissingKeys allows a caller to specify whether they want an error if a field or map key +// cannot be located, or simply an empty result. The receiver is returned for chaining. +func (j *JSONPath) AllowMissingKeys(allow bool) *JSONPath { + j.allowMissingKeys = allow + return j +} + +// Parse parses the given template and returns an error. +func (j *JSONPath) Parse(text string) error { + var err error + j.parser, err = Parse(j.name, text) + return err +} + +// Execute bounds data into template and writes the result. +func (j *JSONPath) Execute(wr io.Writer, data interface{}) error { + fullResults, err := j.FindResults(data) + if err != nil { + return err + } + for ix := range fullResults { + if err := j.PrintResults(wr, fullResults[ix]); err != nil { + return err + } + } + return nil +} + +func (j *JSONPath) FindResults(data interface{}) ([][]reflect.Value, error) { + if j.parser == nil { + return nil, fmt.Errorf("%s is an incomplete jsonpath template", j.name) + } + + cur := []reflect.Value{reflect.ValueOf(data)} + nodes := j.parser.Root.Nodes + fullResult := [][]reflect.Value{} + for i := 0; i < len(nodes); i++ { + node := nodes[i] + results, err := j.walk(cur, node) + if err != nil { + return nil, err + } + + // encounter an end node, break the current block + if j.endRange > 0 && j.endRange <= j.inRange { + j.endRange-- + j.lastEndNode = &nodes[i] + break + } + // encounter a range node, start a range loop + if j.beginRange > 0 { + j.beginRange-- + j.inRange++ + if len(results) > 0 { + for _, value := range results { + j.parser.Root.Nodes = nodes[i+1:] + nextResults, err := j.FindResults(value.Interface()) + if err != nil { + return nil, err + } + fullResult = append(fullResult, nextResults...) + } + } else { + // If the range has no results, we still need to process the nodes within the range + // so the position will advance to the end node + j.parser.Root.Nodes = nodes[i+1:] + _, err := j.FindResults(nil) + if err != nil { + return nil, err + } + } + j.inRange-- + + // Fast forward to resume processing after the most recent end node that was encountered + for k := i + 1; k < len(nodes); k++ { + if &nodes[k] == j.lastEndNode { + i = k + break + } + } + continue + } + fullResult = append(fullResult, results) + } + return fullResult, nil +} + +// EnableJSONOutput changes the PrintResults behavior to return a JSON array of results +func (j *JSONPath) EnableJSONOutput(v bool) { + j.outputJSON = v +} + +// PrintResults writes the results into writer +func (j *JSONPath) PrintResults(wr io.Writer, results []reflect.Value) error { + if j.outputJSON { + // convert the []reflect.Value to something that json + // will be able to marshal + r := make([]interface{}, 0, len(results)) + for i := range results { + r = append(r, results[i].Interface()) + } + results = []reflect.Value{reflect.ValueOf(r)} + } + for i, r := range results { + var text []byte + var err error + outputJSON := true + kind := r.Kind() + if kind == reflect.Interface { + kind = r.Elem().Kind() + } + switch kind { + case reflect.Map: + case reflect.Array: + case reflect.Slice: + case reflect.Struct: + default: + outputJSON = false + } + switch { + case outputJSON || j.outputJSON: + if j.outputJSON { + text, err = json.MarshalIndent(r.Interface(), "", " ") + text = append(text, '\n') + } else { + text, err = json.Marshal(r.Interface()) + } + default: + text, err = j.evalToText(r) + } + if err != nil { + return err + } + if i != len(results)-1 { + text = append(text, ' ') + } + if _, err = wr.Write(text); err != nil { + return err + } + } + + return nil + +} + +// walk visits tree rooted at the given node in DFS order +func (j *JSONPath) walk(value []reflect.Value, node Node) ([]reflect.Value, error) { + switch node := node.(type) { + case *ListNode: + return j.evalList(value, node) + case *TextNode: + return []reflect.Value{reflect.ValueOf(node.Text)}, nil + case *FieldNode: + return j.evalField(value, node) + case *ArrayNode: + return j.evalArray(value, node) + case *FilterNode: + return j.evalFilter(value, node) + case *IntNode: + return j.evalInt(value, node) + case *BoolNode: + return j.evalBool(value, node) + case *FloatNode: + return j.evalFloat(value, node) + case *WildcardNode: + return j.evalWildcard(value, node) + case *RecursiveNode: + return j.evalRecursive(value, node) + case *UnionNode: + return j.evalUnion(value, node) + case *IdentifierNode: + return j.evalIdentifier(value, node) + default: + return value, fmt.Errorf("unexpected Node %v", node) + } +} + +// evalInt evaluates IntNode +func (j *JSONPath) evalInt(input []reflect.Value, node *IntNode) ([]reflect.Value, error) { + result := make([]reflect.Value, len(input)) + for i := range input { + result[i] = reflect.ValueOf(node.Value) + } + return result, nil +} + +// evalFloat evaluates FloatNode +func (j *JSONPath) evalFloat(input []reflect.Value, node *FloatNode) ([]reflect.Value, error) { + result := make([]reflect.Value, len(input)) + for i := range input { + result[i] = reflect.ValueOf(node.Value) + } + return result, nil +} + +// evalBool evaluates BoolNode +func (j *JSONPath) evalBool(input []reflect.Value, node *BoolNode) ([]reflect.Value, error) { + result := make([]reflect.Value, len(input)) + for i := range input { + result[i] = reflect.ValueOf(node.Value) + } + return result, nil +} + +// evalList evaluates ListNode +func (j *JSONPath) evalList(value []reflect.Value, node *ListNode) ([]reflect.Value, error) { + var err error + curValue := value + for _, node := range node.Nodes { + curValue, err = j.walk(curValue, node) + if err != nil { + return curValue, err + } + } + return curValue, nil +} + +// evalIdentifier evaluates IdentifierNode +func (j *JSONPath) evalIdentifier(input []reflect.Value, node *IdentifierNode) ([]reflect.Value, error) { + results := []reflect.Value{} + switch node.Name { + case "range": + j.beginRange++ + results = input + case "end": + if j.inRange > 0 { + j.endRange++ + } else { + return results, fmt.Errorf("not in range, nothing to end") + } + default: + return input, fmt.Errorf("unrecognized identifier %v", node.Name) + } + return results, nil +} + +// evalArray evaluates ArrayNode +func (j *JSONPath) evalArray(input []reflect.Value, node *ArrayNode) ([]reflect.Value, error) { + result := []reflect.Value{} + for _, value := range input { + + value, isNil := template.Indirect(value) + if isNil { + continue + } + if value.Kind() != reflect.Array && value.Kind() != reflect.Slice { + return input, fmt.Errorf("%v is not array or slice", value.Type()) + } + params := node.Params + if !params[0].Known { + params[0].Value = 0 + } + if params[0].Value < 0 { + params[0].Value += value.Len() + } + if !params[1].Known { + params[1].Value = value.Len() + } + + if params[1].Value < 0 || (params[1].Value == 0 && params[1].Derived) { + params[1].Value += value.Len() + } + sliceLength := value.Len() + if params[1].Value != params[0].Value { // if you're requesting zero elements, allow it through. + if params[0].Value >= sliceLength || params[0].Value < 0 { + return input, fmt.Errorf("array index out of bounds: index %d, length %d", params[0].Value, sliceLength) + } + if params[1].Value > sliceLength || params[1].Value < 0 { + return input, fmt.Errorf("array index out of bounds: index %d, length %d", params[1].Value-1, sliceLength) + } + if params[0].Value > params[1].Value { + return input, fmt.Errorf("starting index %d is greater than ending index %d", params[0].Value, params[1].Value) + } + } else { + return result, nil + } + + value = value.Slice(params[0].Value, params[1].Value) + + step := 1 + if params[2].Known { + if params[2].Value <= 0 { + return input, fmt.Errorf("step must be > 0") + } + step = params[2].Value + } + for i := 0; i < value.Len(); i += step { + result = append(result, value.Index(i)) + } + } + return result, nil +} + +// evalUnion evaluates UnionNode +func (j *JSONPath) evalUnion(input []reflect.Value, node *UnionNode) ([]reflect.Value, error) { + result := []reflect.Value{} + for _, listNode := range node.Nodes { + temp, err := j.evalList(input, listNode) + if err != nil { + return input, err + } + result = append(result, temp...) + } + return result, nil +} + +func (j *JSONPath) findFieldInValue(value *reflect.Value, node *FieldNode) (reflect.Value, error) { + t := value.Type() + var inlineValue *reflect.Value + for ix := 0; ix < t.NumField(); ix++ { + f := t.Field(ix) + jsonTag := f.Tag.Get("json") + parts := strings.Split(jsonTag, ",") + if len(parts) == 0 { + continue + } + if parts[0] == node.Value { + return value.Field(ix), nil + } + if len(parts[0]) == 0 { + val := value.Field(ix) + inlineValue = &val + } + } + if inlineValue != nil { + if inlineValue.Kind() == reflect.Struct { + // handle 'inline' + match, err := j.findFieldInValue(inlineValue, node) + if err != nil { + return reflect.Value{}, err + } + if match.IsValid() { + return match, nil + } + } + } + return value.FieldByName(node.Value), nil +} + +// evalField evaluates field of struct or key of map. +func (j *JSONPath) evalField(input []reflect.Value, node *FieldNode) ([]reflect.Value, error) { + results := []reflect.Value{} + // If there's no input, there's no output + if len(input) == 0 { + return results, nil + } + for _, value := range input { + var result reflect.Value + value, isNil := template.Indirect(value) + if isNil { + continue + } + + if value.Kind() == reflect.Struct { + var err error + if result, err = j.findFieldInValue(&value, node); err != nil { + return nil, err + } + } else if value.Kind() == reflect.Map { + mapKeyType := value.Type().Key() + nodeValue := reflect.ValueOf(node.Value) + // node value type must be convertible to map key type + if !nodeValue.Type().ConvertibleTo(mapKeyType) { + return results, fmt.Errorf("%s is not convertible to %s", nodeValue, mapKeyType) + } + result = value.MapIndex(nodeValue.Convert(mapKeyType)) + } + if result.IsValid() { + results = append(results, result) + } + } + if len(results) == 0 { + if j.allowMissingKeys { + return results, nil + } + return results, fmt.Errorf("%s is not found", node.Value) + } + return results, nil +} + +// evalWildcard extracts all contents of the given value +func (j *JSONPath) evalWildcard(input []reflect.Value, node *WildcardNode) ([]reflect.Value, error) { + results := []reflect.Value{} + for _, value := range input { + value, isNil := template.Indirect(value) + if isNil { + continue + } + + kind := value.Kind() + if kind == reflect.Struct { + for i := 0; i < value.NumField(); i++ { + results = append(results, value.Field(i)) + } + } else if kind == reflect.Map { + for _, key := range value.MapKeys() { + results = append(results, value.MapIndex(key)) + } + } else if kind == reflect.Array || kind == reflect.Slice || kind == reflect.String { + for i := 0; i < value.Len(); i++ { + results = append(results, value.Index(i)) + } + } + } + return results, nil +} + +// evalRecursive visits the given value recursively and pushes all of them to result +func (j *JSONPath) evalRecursive(input []reflect.Value, node *RecursiveNode) ([]reflect.Value, error) { + result := []reflect.Value{} + for _, value := range input { + results := []reflect.Value{} + value, isNil := template.Indirect(value) + if isNil { + continue + } + + kind := value.Kind() + if kind == reflect.Struct { + for i := 0; i < value.NumField(); i++ { + results = append(results, value.Field(i)) + } + } else if kind == reflect.Map { + for _, key := range value.MapKeys() { + results = append(results, value.MapIndex(key)) + } + } else if kind == reflect.Array || kind == reflect.Slice || kind == reflect.String { + for i := 0; i < value.Len(); i++ { + results = append(results, value.Index(i)) + } + } + if len(results) != 0 { + result = append(result, value) + output, err := j.evalRecursive(results, node) + if err != nil { + return result, err + } + result = append(result, output...) + } + } + return result, nil +} + +// evalFilter filters array according to FilterNode +func (j *JSONPath) evalFilter(input []reflect.Value, node *FilterNode) ([]reflect.Value, error) { + results := []reflect.Value{} + for _, value := range input { + value, _ = template.Indirect(value) + + if value.Kind() != reflect.Array && value.Kind() != reflect.Slice { + return input, fmt.Errorf("%v is not array or slice and cannot be filtered", value) + } + for i := 0; i < value.Len(); i++ { + temp := []reflect.Value{value.Index(i)} + lefts, err := j.evalList(temp, node.Left) + + //case exists + if node.Operator == "exists" { + if len(lefts) > 0 { + results = append(results, value.Index(i)) + } + continue + } + + if err != nil { + return input, err + } + + var left, right interface{} + switch { + case len(lefts) == 0: + continue + case len(lefts) > 1: + return input, fmt.Errorf("can only compare one element at a time") + } + left = lefts[0].Interface() + + rights, err := j.evalList(temp, node.Right) + if err != nil { + return input, err + } + switch { + case len(rights) == 0: + continue + case len(rights) > 1: + return input, fmt.Errorf("can only compare one element at a time") + } + right = rights[0].Interface() + + pass := false + switch node.Operator { + case "<": + pass, err = template.Less(left, right) + case ">": + pass, err = template.Greater(left, right) + case "==": + pass, err = template.Equal(left, right) + case "!=": + pass, err = template.NotEqual(left, right) + case "<=": + pass, err = template.LessEqual(left, right) + case ">=": + pass, err = template.GreaterEqual(left, right) + default: + return results, fmt.Errorf("unrecognized filter operator %s", node.Operator) + } + if err != nil { + return results, err + } + if pass { + results = append(results, value.Index(i)) + } + } + } + return results, nil +} + +// evalToText translates reflect value to corresponding text +func (j *JSONPath) evalToText(v reflect.Value) ([]byte, error) { + iface, ok := template.PrintableValue(v) + if !ok { + return nil, fmt.Errorf("can't print type %s", v.Type()) + } + if iface == nil { + return []byte("null"), nil + } + var buffer bytes.Buffer + fmt.Fprint(&buffer, iface) + return buffer.Bytes(), nil +} diff --git a/vendor/k8s.io/client-go/util/jsonpath/node.go b/vendor/k8s.io/client-go/util/jsonpath/node.go new file mode 100644 index 0000000000..83abe8b037 --- /dev/null +++ b/vendor/k8s.io/client-go/util/jsonpath/node.go @@ -0,0 +1,256 @@ +/* +Copyright 2015 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package jsonpath + +import "fmt" + +// NodeType identifies the type of a parse tree node. +type NodeType int + +// Type returns itself and provides an easy default implementation +func (t NodeType) Type() NodeType { + return t +} + +func (t NodeType) String() string { + return NodeTypeName[t] +} + +const ( + NodeText NodeType = iota + NodeArray + NodeList + NodeField + NodeIdentifier + NodeFilter + NodeInt + NodeFloat + NodeWildcard + NodeRecursive + NodeUnion + NodeBool +) + +var NodeTypeName = map[NodeType]string{ + NodeText: "NodeText", + NodeArray: "NodeArray", + NodeList: "NodeList", + NodeField: "NodeField", + NodeIdentifier: "NodeIdentifier", + NodeFilter: "NodeFilter", + NodeInt: "NodeInt", + NodeFloat: "NodeFloat", + NodeWildcard: "NodeWildcard", + NodeRecursive: "NodeRecursive", + NodeUnion: "NodeUnion", + NodeBool: "NodeBool", +} + +type Node interface { + Type() NodeType + String() string +} + +// ListNode holds a sequence of nodes. +type ListNode struct { + NodeType + Nodes []Node // The element nodes in lexical order. +} + +func newList() *ListNode { + return &ListNode{NodeType: NodeList} +} + +func (l *ListNode) append(n Node) { + l.Nodes = append(l.Nodes, n) +} + +func (l *ListNode) String() string { + return l.Type().String() +} + +// TextNode holds plain text. +type TextNode struct { + NodeType + Text string // The text; may span newlines. +} + +func newText(text string) *TextNode { + return &TextNode{NodeType: NodeText, Text: text} +} + +func (t *TextNode) String() string { + return fmt.Sprintf("%s: %s", t.Type(), t.Text) +} + +// FieldNode holds field of struct +type FieldNode struct { + NodeType + Value string +} + +func newField(value string) *FieldNode { + return &FieldNode{NodeType: NodeField, Value: value} +} + +func (f *FieldNode) String() string { + return fmt.Sprintf("%s: %s", f.Type(), f.Value) +} + +// IdentifierNode holds an identifier +type IdentifierNode struct { + NodeType + Name string +} + +func newIdentifier(value string) *IdentifierNode { + return &IdentifierNode{ + NodeType: NodeIdentifier, + Name: value, + } +} + +func (f *IdentifierNode) String() string { + return fmt.Sprintf("%s: %s", f.Type(), f.Name) +} + +// ParamsEntry holds param information for ArrayNode +type ParamsEntry struct { + Value int + Known bool // whether the value is known when parse it + Derived bool +} + +// ArrayNode holds start, end, step information for array index selection +type ArrayNode struct { + NodeType + Params [3]ParamsEntry // start, end, step +} + +func newArray(params [3]ParamsEntry) *ArrayNode { + return &ArrayNode{ + NodeType: NodeArray, + Params: params, + } +} + +func (a *ArrayNode) String() string { + return fmt.Sprintf("%s: %v", a.Type(), a.Params) +} + +// FilterNode holds operand and operator information for filter +type FilterNode struct { + NodeType + Left *ListNode + Right *ListNode + Operator string +} + +func newFilter(left, right *ListNode, operator string) *FilterNode { + return &FilterNode{ + NodeType: NodeFilter, + Left: left, + Right: right, + Operator: operator, + } +} + +func (f *FilterNode) String() string { + return fmt.Sprintf("%s: %s %s %s", f.Type(), f.Left, f.Operator, f.Right) +} + +// IntNode holds integer value +type IntNode struct { + NodeType + Value int +} + +func newInt(num int) *IntNode { + return &IntNode{NodeType: NodeInt, Value: num} +} + +func (i *IntNode) String() string { + return fmt.Sprintf("%s: %d", i.Type(), i.Value) +} + +// FloatNode holds float value +type FloatNode struct { + NodeType + Value float64 +} + +func newFloat(num float64) *FloatNode { + return &FloatNode{NodeType: NodeFloat, Value: num} +} + +func (i *FloatNode) String() string { + return fmt.Sprintf("%s: %f", i.Type(), i.Value) +} + +// WildcardNode means a wildcard +type WildcardNode struct { + NodeType +} + +func newWildcard() *WildcardNode { + return &WildcardNode{NodeType: NodeWildcard} +} + +func (i *WildcardNode) String() string { + return i.Type().String() +} + +// RecursiveNode means a recursive descent operator +type RecursiveNode struct { + NodeType +} + +func newRecursive() *RecursiveNode { + return &RecursiveNode{NodeType: NodeRecursive} +} + +func (r *RecursiveNode) String() string { + return r.Type().String() +} + +// UnionNode is union of ListNode +type UnionNode struct { + NodeType + Nodes []*ListNode +} + +func newUnion(nodes []*ListNode) *UnionNode { + return &UnionNode{NodeType: NodeUnion, Nodes: nodes} +} + +func (u *UnionNode) String() string { + return u.Type().String() +} + +// BoolNode holds bool value +type BoolNode struct { + NodeType + Value bool +} + +func newBool(value bool) *BoolNode { + return &BoolNode{NodeType: NodeBool, Value: value} +} + +func (b *BoolNode) String() string { + return fmt.Sprintf("%s: %t", b.Type(), b.Value) +} diff --git a/vendor/k8s.io/client-go/util/jsonpath/parser.go b/vendor/k8s.io/client-go/util/jsonpath/parser.go new file mode 100644 index 0000000000..40bab188dc --- /dev/null +++ b/vendor/k8s.io/client-go/util/jsonpath/parser.go @@ -0,0 +1,527 @@ +/* +Copyright 2015 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package jsonpath + +import ( + "errors" + "fmt" + "regexp" + "strconv" + "strings" + "unicode" + "unicode/utf8" +) + +const eof = -1 + +const ( + leftDelim = "{" + rightDelim = "}" +) + +type Parser struct { + Name string + Root *ListNode + input string + pos int + start int + width int +} + +var ( + ErrSyntax = errors.New("invalid syntax") + dictKeyRex = regexp.MustCompile(`^'([^']*)'$`) + sliceOperatorRex = regexp.MustCompile(`^(-?[\d]*)(:-?[\d]*)?(:-?[\d]*)?$`) +) + +// Parse parsed the given text and return a node Parser. +// If an error is encountered, parsing stops and an empty +// Parser is returned with the error +func Parse(name, text string) (*Parser, error) { + p := NewParser(name) + err := p.Parse(text) + if err != nil { + p = nil + } + return p, err +} + +func NewParser(name string) *Parser { + return &Parser{ + Name: name, + } +} + +// parseAction parsed the expression inside delimiter +func parseAction(name, text string) (*Parser, error) { + p, err := Parse(name, fmt.Sprintf("%s%s%s", leftDelim, text, rightDelim)) + // when error happens, p will be nil, so we need to return here + if err != nil { + return p, err + } + p.Root = p.Root.Nodes[0].(*ListNode) + return p, nil +} + +func (p *Parser) Parse(text string) error { + p.input = text + p.Root = newList() + p.pos = 0 + return p.parseText(p.Root) +} + +// consumeText return the parsed text since last cosumeText +func (p *Parser) consumeText() string { + value := p.input[p.start:p.pos] + p.start = p.pos + return value +} + +// next returns the next rune in the input. +func (p *Parser) next() rune { + if p.pos >= len(p.input) { + p.width = 0 + return eof + } + r, w := utf8.DecodeRuneInString(p.input[p.pos:]) + p.width = w + p.pos += p.width + return r +} + +// peek returns but does not consume the next rune in the input. +func (p *Parser) peek() rune { + r := p.next() + p.backup() + return r +} + +// backup steps back one rune. Can only be called once per call of next. +func (p *Parser) backup() { + p.pos -= p.width +} + +func (p *Parser) parseText(cur *ListNode) error { + for { + if strings.HasPrefix(p.input[p.pos:], leftDelim) { + if p.pos > p.start { + cur.append(newText(p.consumeText())) + } + return p.parseLeftDelim(cur) + } + if p.next() == eof { + break + } + } + // Correctly reached EOF. + if p.pos > p.start { + cur.append(newText(p.consumeText())) + } + return nil +} + +// parseLeftDelim scans the left delimiter, which is known to be present. +func (p *Parser) parseLeftDelim(cur *ListNode) error { + p.pos += len(leftDelim) + p.consumeText() + newNode := newList() + cur.append(newNode) + cur = newNode + return p.parseInsideAction(cur) +} + +func (p *Parser) parseInsideAction(cur *ListNode) error { + prefixMap := map[string]func(*ListNode) error{ + rightDelim: p.parseRightDelim, + "[?(": p.parseFilter, + "..": p.parseRecursive, + } + for prefix, parseFunc := range prefixMap { + if strings.HasPrefix(p.input[p.pos:], prefix) { + return parseFunc(cur) + } + } + + switch r := p.next(); { + case r == eof || isEndOfLine(r): + return fmt.Errorf("unclosed action") + case r == ' ': + p.consumeText() + case r == '@' || r == '$': //the current object, just pass it + p.consumeText() + case r == '[': + return p.parseArray(cur) + case r == '"' || r == '\'': + return p.parseQuote(cur, r) + case r == '.': + return p.parseField(cur) + case r == '+' || r == '-' || unicode.IsDigit(r): + p.backup() + return p.parseNumber(cur) + case isAlphaNumeric(r): + p.backup() + return p.parseIdentifier(cur) + default: + return fmt.Errorf("unrecognized character in action: %#U", r) + } + return p.parseInsideAction(cur) +} + +// parseRightDelim scans the right delimiter, which is known to be present. +func (p *Parser) parseRightDelim(cur *ListNode) error { + p.pos += len(rightDelim) + p.consumeText() + return p.parseText(p.Root) +} + +// parseIdentifier scans build-in keywords, like "range" "end" +func (p *Parser) parseIdentifier(cur *ListNode) error { + var r rune + for { + r = p.next() + if isTerminator(r) { + p.backup() + break + } + } + value := p.consumeText() + + if isBool(value) { + v, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("can not parse bool '%s': %s", value, err.Error()) + } + + cur.append(newBool(v)) + } else { + cur.append(newIdentifier(value)) + } + + return p.parseInsideAction(cur) +} + +// parseRecursive scans the recursive descent operator .. +func (p *Parser) parseRecursive(cur *ListNode) error { + if lastIndex := len(cur.Nodes) - 1; lastIndex >= 0 && cur.Nodes[lastIndex].Type() == NodeRecursive { + return fmt.Errorf("invalid multiple recursive descent") + } + p.pos += len("..") + p.consumeText() + cur.append(newRecursive()) + if r := p.peek(); isAlphaNumeric(r) { + return p.parseField(cur) + } + return p.parseInsideAction(cur) +} + +// parseNumber scans number +func (p *Parser) parseNumber(cur *ListNode) error { + r := p.peek() + if r == '+' || r == '-' { + p.next() + } + for { + r = p.next() + if r != '.' && !unicode.IsDigit(r) { + p.backup() + break + } + } + value := p.consumeText() + i, err := strconv.Atoi(value) + if err == nil { + cur.append(newInt(i)) + return p.parseInsideAction(cur) + } + d, err := strconv.ParseFloat(value, 64) + if err == nil { + cur.append(newFloat(d)) + return p.parseInsideAction(cur) + } + return fmt.Errorf("cannot parse number %s", value) +} + +// parseArray scans array index selection +func (p *Parser) parseArray(cur *ListNode) error { +Loop: + for { + switch p.next() { + case eof, '\n': + return fmt.Errorf("unterminated array") + case ']': + break Loop + } + } + text := p.consumeText() + text = text[1 : len(text)-1] + if text == "*" { + text = ":" + } + + //union operator + strs := strings.Split(text, ",") + if len(strs) > 1 { + union := []*ListNode{} + for _, str := range strs { + parser, err := parseAction("union", fmt.Sprintf("[%s]", strings.Trim(str, " "))) + if err != nil { + return err + } + union = append(union, parser.Root) + } + cur.append(newUnion(union)) + return p.parseInsideAction(cur) + } + + // dict key + value := dictKeyRex.FindStringSubmatch(text) + if value != nil { + parser, err := parseAction("arraydict", fmt.Sprintf(".%s", value[1])) + if err != nil { + return err + } + for _, node := range parser.Root.Nodes { + cur.append(node) + } + return p.parseInsideAction(cur) + } + + //slice operator + value = sliceOperatorRex.FindStringSubmatch(text) + if value == nil { + return fmt.Errorf("invalid array index %s", text) + } + value = value[1:] + params := [3]ParamsEntry{} + for i := 0; i < 3; i++ { + if value[i] != "" { + if i > 0 { + value[i] = value[i][1:] + } + if i > 0 && value[i] == "" { + params[i].Known = false + } else { + var err error + params[i].Known = true + params[i].Value, err = strconv.Atoi(value[i]) + if err != nil { + return fmt.Errorf("array index %s is not a number", value[i]) + } + } + } else { + if i == 1 { + params[i].Known = true + params[i].Value = params[0].Value + 1 + params[i].Derived = true + } else { + params[i].Known = false + params[i].Value = 0 + } + } + } + cur.append(newArray(params)) + return p.parseInsideAction(cur) +} + +// parseFilter scans filter inside array selection +func (p *Parser) parseFilter(cur *ListNode) error { + p.pos += len("[?(") + p.consumeText() + begin := false + end := false + var pair rune + +Loop: + for { + r := p.next() + switch r { + case eof, '\n': + return fmt.Errorf("unterminated filter") + case '"', '\'': + if begin == false { + //save the paired rune + begin = true + pair = r + continue + } + //only add when met paired rune + if p.input[p.pos-2] != '\\' && r == pair { + end = true + } + case ')': + //in rightParser below quotes only appear zero or once + //and must be paired at the beginning and end + if begin == end { + break Loop + } + } + } + if p.next() != ']' { + return fmt.Errorf("unclosed array expect ]") + } + reg := regexp.MustCompile(`^([^!<>=]+)([!<>=]+)(.+?)$`) + text := p.consumeText() + text = text[:len(text)-2] + value := reg.FindStringSubmatch(text) + if value == nil { + parser, err := parseAction("text", text) + if err != nil { + return err + } + cur.append(newFilter(parser.Root, newList(), "exists")) + } else { + leftParser, err := parseAction("left", value[1]) + if err != nil { + return err + } + rightParser, err := parseAction("right", value[3]) + if err != nil { + return err + } + cur.append(newFilter(leftParser.Root, rightParser.Root, value[2])) + } + return p.parseInsideAction(cur) +} + +// parseQuote unquotes string inside double or single quote +func (p *Parser) parseQuote(cur *ListNode, end rune) error { +Loop: + for { + switch p.next() { + case eof, '\n': + return fmt.Errorf("unterminated quoted string") + case end: + //if it's not escape break the Loop + if p.input[p.pos-2] != '\\' { + break Loop + } + } + } + value := p.consumeText() + s, err := UnquoteExtend(value) + if err != nil { + return fmt.Errorf("unquote string %s error %v", value, err) + } + cur.append(newText(s)) + return p.parseInsideAction(cur) +} + +// parseField scans a field until a terminator +func (p *Parser) parseField(cur *ListNode) error { + p.consumeText() + for p.advance() { + } + value := p.consumeText() + if value == "*" { + cur.append(newWildcard()) + } else { + cur.append(newField(strings.Replace(value, "\\", "", -1))) + } + return p.parseInsideAction(cur) +} + +// advance scans until next non-escaped terminator +func (p *Parser) advance() bool { + r := p.next() + if r == '\\' { + p.next() + } else if isTerminator(r) { + p.backup() + return false + } + return true +} + +// isTerminator reports whether the input is at valid termination character to appear after an identifier. +func isTerminator(r rune) bool { + if isSpace(r) || isEndOfLine(r) { + return true + } + switch r { + case eof, '.', ',', '[', ']', '$', '@', '{', '}': + return true + } + return false +} + +// isSpace reports whether r is a space character. +func isSpace(r rune) bool { + return r == ' ' || r == '\t' +} + +// isEndOfLine reports whether r is an end-of-line character. +func isEndOfLine(r rune) bool { + return r == '\r' || r == '\n' +} + +// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore. +func isAlphaNumeric(r rune) bool { + return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) +} + +// isBool reports whether s is a boolean value. +func isBool(s string) bool { + return s == "true" || s == "false" +} + +// UnquoteExtend is almost same as strconv.Unquote(), but it support parse single quotes as a string +func UnquoteExtend(s string) (string, error) { + n := len(s) + if n < 2 { + return "", ErrSyntax + } + quote := s[0] + if quote != s[n-1] { + return "", ErrSyntax + } + s = s[1 : n-1] + + if quote != '"' && quote != '\'' { + return "", ErrSyntax + } + + // Is it trivial? Avoid allocation. + if !contains(s, '\\') && !contains(s, quote) { + return s, nil + } + + var runeTmp [utf8.UTFMax]byte + buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations. + for len(s) > 0 { + c, multibyte, ss, err := strconv.UnquoteChar(s, quote) + if err != nil { + return "", err + } + s = ss + if c < utf8.RuneSelf || !multibyte { + buf = append(buf, byte(c)) + } else { + n := utf8.EncodeRune(runeTmp[:], c) + buf = append(buf, runeTmp[:n]...) + } + } + return string(buf), nil +} + +func contains(s string, c byte) bool { + for i := 0; i < len(s); i++ { + if s[i] == c { + return true + } + } + return false +} diff --git a/vendor/k8s.io/kubectl/LICENSE b/vendor/k8s.io/kubectl/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/vendor/k8s.io/kubectl/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/k8s.io/kubectl/pkg/util/interrupt/interrupt.go b/vendor/k8s.io/kubectl/pkg/util/interrupt/interrupt.go new file mode 100644 index 0000000000..0265b9fb17 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/interrupt/interrupt.go @@ -0,0 +1,104 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package interrupt + +import ( + "os" + "os/signal" + "sync" + "syscall" +) + +// terminationSignals are signals that cause the program to exit in the +// supported platforms (linux, darwin, windows). +var terminationSignals = []os.Signal{syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT} + +// Handler guarantees execution of notifications after a critical section (the function passed +// to a Run method), even in the presence of process termination. It guarantees exactly once +// invocation of the provided notify functions. +type Handler struct { + notify []func() + final func(os.Signal) + once sync.Once +} + +// Chain creates a new handler that invokes all notify functions when the critical section exits +// and then invokes the optional handler's notifications. This allows critical sections to be +// nested without losing exactly once invocations. Notify functions can invoke any cleanup needed +// but should not exit (which is the responsibility of the parent handler). +func Chain(handler *Handler, notify ...func()) *Handler { + if handler == nil { + return New(nil, notify...) + } + return New(handler.Signal, append(notify, handler.Close)...) +} + +// New creates a new handler that guarantees all notify functions are run after the critical +// section exits (or is interrupted by the OS), then invokes the final handler. If no final +// handler is specified, the default final is `os.Exit(1)`. A handler can only be used for +// one critical section. +func New(final func(os.Signal), notify ...func()) *Handler { + return &Handler{ + final: final, + notify: notify, + } +} + +// Close executes all the notification handlers if they have not yet been executed. +func (h *Handler) Close() { + h.once.Do(func() { + for _, fn := range h.notify { + fn() + } + }) +} + +// Signal is called when an os.Signal is received, and guarantees that all notifications +// are executed, then the final handler is executed. This function should only be called once +// per Handler instance. +func (h *Handler) Signal(s os.Signal) { + h.once.Do(func() { + for _, fn := range h.notify { + fn() + } + if h.final == nil { + os.Exit(1) + } + h.final(s) + }) +} + +// Run ensures that any notifications are invoked after the provided fn exits (even if the +// process is interrupted by an OS termination signal). Notifications are only invoked once +// per Handler instance, so calling Run more than once will not behave as the user expects. +func (h *Handler) Run(fn func() error) error { + ch := make(chan os.Signal, 1) + signal.Notify(ch, terminationSignals...) + defer func() { + signal.Stop(ch) + close(ch) + }() + go func() { + sig, ok := <-ch + if !ok { + return + } + h.Signal(sig) + }() + defer h.Close() + return fn() +} diff --git a/vendor/k8s.io/kubectl/pkg/util/templates/command_groups.go b/vendor/k8s.io/kubectl/pkg/util/templates/command_groups.go new file mode 100644 index 0000000000..447a39621f --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/templates/command_groups.go @@ -0,0 +1,59 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package templates + +import ( + "github.com/spf13/cobra" +) + +type CommandGroup struct { + Message string + Commands []*cobra.Command +} + +type CommandGroups []CommandGroup + +func (g CommandGroups) Add(c *cobra.Command) { + for _, group := range g { + c.AddCommand(group.Commands...) + } +} + +func (g CommandGroups) Has(c *cobra.Command) bool { + for _, group := range g { + for _, command := range group.Commands { + if command == c { + return true + } + } + } + return false +} + +func AddAdditionalCommands(g CommandGroups, message string, cmds []*cobra.Command) CommandGroups { + group := CommandGroup{Message: message} + for _, c := range cmds { + // Don't show commands that have no short description + if !g.Has(c) && len(c.Short) != 0 { + group.Commands = append(group.Commands, c) + } + } + if len(group.Commands) == 0 { + return g + } + return append(g, group) +} diff --git a/vendor/k8s.io/kubectl/pkg/util/templates/help_flags_printer.go b/vendor/k8s.io/kubectl/pkg/util/templates/help_flags_printer.go new file mode 100644 index 0000000000..fdfdf08eeb --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/templates/help_flags_printer.go @@ -0,0 +1,76 @@ +/* +Copyright 2022 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package templates + +import ( + "bytes" + "fmt" + "io" + "strings" + + "github.com/mitchellh/go-wordwrap" + flag "github.com/spf13/pflag" +) + +const offset = 10 + +// HelpFlagPrinter is a printer that +// processes the help flag and print +// it to i/o writer +type HelpFlagPrinter struct { + wrapLimit uint + out io.Writer +} + +// NewHelpFlagPrinter will initialize a HelpFlagPrinter given the +// i/o writer +func NewHelpFlagPrinter(out io.Writer, wrapLimit uint) *HelpFlagPrinter { + return &HelpFlagPrinter{ + wrapLimit: wrapLimit, + out: out, + } +} + +// PrintHelpFlag will beautify the help flags and print it out to p.out +func (p *HelpFlagPrinter) PrintHelpFlag(flag *flag.Flag) { + formatBuf := new(bytes.Buffer) + writeFlag(formatBuf, flag) + + wrappedStr := formatBuf.String() + flagAndUsage := strings.Split(formatBuf.String(), "\n") + flagStr := flagAndUsage[0] + + // if the flag usage is longer than one line, wrap it again + if len(flagAndUsage) > 1 { + nextLines := strings.Join(flagAndUsage[1:], " ") + wrappedUsages := wordwrap.WrapString(nextLines, p.wrapLimit-offset) + wrappedStr = flagStr + "\n" + wrappedUsages + } + appendTabStr := strings.ReplaceAll(wrappedStr, "\n", "\n\t") + + fmt.Fprintf(p.out, appendTabStr+"\n\n") +} + +// writeFlag will output the help flag based +// on the format provided by getFlagFormat to i/o writer +func writeFlag(out io.Writer, f *flag.Flag) { + deprecated := "" + if f.Deprecated != "" { + deprecated = fmt.Sprintf(" (DEPRECATED: %s)", f.Deprecated) + } + fmt.Fprintf(out, getFlagFormat(f), f.Shorthand, f.Name, f.DefValue, f.Usage, deprecated) +} diff --git a/vendor/k8s.io/kubectl/pkg/util/templates/markdown.go b/vendor/k8s.io/kubectl/pkg/util/templates/markdown.go new file mode 100644 index 0000000000..962cd9eec9 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/templates/markdown.go @@ -0,0 +1,116 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package templates + +import ( + "fmt" + "io" + "strings" + + "github.com/russross/blackfriday/v2" +) + +const linebreak = "\n" + +// ASCIIRenderer implements blackfriday.Renderer +var _ blackfriday.Renderer = &ASCIIRenderer{} + +// ASCIIRenderer is a blackfriday.Renderer intended for rendering markdown +// documents as plain text, well suited for human reading on terminals. +type ASCIIRenderer struct { + Indentation string + + listItemCount uint + listLevel uint +} + +// render markdown to text +func (r *ASCIIRenderer) RenderNode(w io.Writer, node *blackfriday.Node, entering bool) blackfriday.WalkStatus { + switch node.Type { + case blackfriday.Text: + raw := string(node.Literal) + lines := strings.Split(raw, linebreak) + for _, line := range lines { + trimmed := strings.Trim(line, " \n\t") + if len(trimmed) > 0 && trimmed[0] != '_' { + w.Write([]byte(" ")) + } + w.Write([]byte(trimmed)) + } + case blackfriday.HorizontalRule, blackfriday.Hardbreak: + w.Write([]byte(linebreak + "----------" + linebreak)) + case blackfriday.Code, blackfriday.CodeBlock: + w.Write([]byte(linebreak)) + lines := []string{} + for _, line := range strings.Split(string(node.Literal), linebreak) { + trimmed := strings.Trim(line, " \t") + // Adding 4 times of indentation will let blackfriday to accept + // this literal as Code or CodeBlock again in next invocation + indented := strings.Repeat(r.Indentation, 4) + trimmed + lines = append(lines, indented) + } + w.Write([]byte(strings.Join(lines, linebreak))) + case blackfriday.Image: + w.Write(node.LinkData.Destination) + case blackfriday.Link: + w.Write([]byte(" ")) + w.Write(node.LinkData.Destination) + case blackfriday.Paragraph: + if r.listLevel == 0 { + w.Write([]byte(linebreak)) + } + case blackfriday.List: + if entering { + w.Write([]byte(linebreak)) + r.listLevel++ + } else { + r.listLevel-- + r.listItemCount = 0 + } + case blackfriday.Item: + if entering { + r.listItemCount++ + for i := 0; uint(i) < r.listLevel; i++ { + w.Write([]byte(r.Indentation)) + } + if node.ListFlags&blackfriday.ListTypeOrdered != 0 { + w.Write([]byte(fmt.Sprintf("%d. ", r.listItemCount))) + } else { + w.Write([]byte("* ")) + } + } else { + w.Write([]byte(linebreak)) + } + default: + normalText(w, node.Literal) + } + return blackfriday.GoToNext +} + +func normalText(w io.Writer, text []byte) { + w.Write([]byte(strings.Trim(string(text), " \n\t"))) +} + +// RenderHeader writes document preamble and TOC if requested. +func (r *ASCIIRenderer) RenderHeader(w io.Writer, ast *blackfriday.Node) { + +} + +// RenderFooter writes document footer. +func (r *ASCIIRenderer) RenderFooter(w io.Writer, ast *blackfriday.Node) { + io.WriteString(w, "\n") +} diff --git a/vendor/k8s.io/kubectl/pkg/util/templates/normalizers.go b/vendor/k8s.io/kubectl/pkg/util/templates/normalizers.go new file mode 100644 index 0000000000..09094ffdfe --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/templates/normalizers.go @@ -0,0 +1,97 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package templates + +import ( + "strings" + + "github.com/MakeNowJust/heredoc" + "github.com/russross/blackfriday/v2" + "github.com/spf13/cobra" +) + +const Indentation = ` ` + +// LongDesc normalizes a command's long description to follow the conventions. +func LongDesc(s string) string { + if len(s) == 0 { + return s + } + return normalizer{s}.heredoc().markdown().trim().string +} + +// Examples normalizes a command's examples to follow the conventions. +func Examples(s string) string { + if len(s) == 0 { + return s + } + return normalizer{s}.trim().indent().string +} + +// Normalize perform all required normalizations on a given command. +func Normalize(cmd *cobra.Command) *cobra.Command { + if len(cmd.Long) > 0 { + cmd.Long = LongDesc(cmd.Long) + } + if len(cmd.Example) > 0 { + cmd.Example = Examples(cmd.Example) + } + return cmd +} + +// NormalizeAll perform all required normalizations in the entire command tree. +func NormalizeAll(cmd *cobra.Command) *cobra.Command { + if cmd.HasSubCommands() { + for _, subCmd := range cmd.Commands() { + NormalizeAll(subCmd) + } + } + Normalize(cmd) + return cmd +} + +type normalizer struct { + string +} + +func (s normalizer) markdown() normalizer { + bytes := []byte(s.string) + formatted := blackfriday.Run(bytes, blackfriday.WithExtensions(blackfriday.NoIntraEmphasis), blackfriday.WithRenderer(&ASCIIRenderer{Indentation: Indentation})) + s.string = string(formatted) + return s +} + +func (s normalizer) heredoc() normalizer { + s.string = heredoc.Doc(s.string) + return s +} + +func (s normalizer) trim() normalizer { + s.string = strings.TrimSpace(s.string) + return s +} + +func (s normalizer) indent() normalizer { + indentedLines := []string{} + for _, line := range strings.Split(s.string, "\n") { + trimmed := strings.TrimSpace(line) + indented := Indentation + trimmed + indentedLines = append(indentedLines, indented) + } + s.string = strings.Join(indentedLines, "\n") + return s +} diff --git a/vendor/k8s.io/kubectl/pkg/util/templates/templater.go b/vendor/k8s.io/kubectl/pkg/util/templates/templater.go new file mode 100644 index 0000000000..8fe181a050 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/templates/templater.go @@ -0,0 +1,319 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package templates + +import ( + "bytes" + "fmt" + "strings" + "text/template" + "unicode" + + "github.com/spf13/cobra" + flag "github.com/spf13/pflag" + + "k8s.io/kubectl/pkg/util/term" +) + +type FlagExposer interface { + ExposeFlags(cmd *cobra.Command, flags ...string) FlagExposer +} + +func ActsAsRootCommand(cmd *cobra.Command, filters []string, groups ...CommandGroup) FlagExposer { + if cmd == nil { + panic("nil root command") + } + templater := &templater{ + RootCmd: cmd, + UsageTemplate: MainUsageTemplate(), + HelpTemplate: MainHelpTemplate(), + CommandGroups: groups, + Filtered: filters, + } + cmd.SetFlagErrorFunc(templater.FlagErrorFunc()) + cmd.SilenceUsage = true + cmd.SetUsageFunc(templater.UsageFunc()) + cmd.SetHelpFunc(templater.HelpFunc()) + return templater +} + +func UseOptionsTemplates(cmd *cobra.Command) { + templater := &templater{ + UsageTemplate: OptionsUsageTemplate(), + HelpTemplate: OptionsHelpTemplate(), + } + cmd.SetUsageFunc(templater.UsageFunc()) + cmd.SetHelpFunc(templater.HelpFunc()) +} + +type templater struct { + UsageTemplate string + HelpTemplate string + RootCmd *cobra.Command + CommandGroups + Filtered []string +} + +func (templater *templater) FlagErrorFunc(exposedFlags ...string) func(*cobra.Command, error) error { + return func(c *cobra.Command, err error) error { + c.SilenceUsage = true + switch c.CalledAs() { + case "options": + return fmt.Errorf("%s\nRun '%s' without flags.", err, c.CommandPath()) + default: + return fmt.Errorf("%s\nSee '%s --help' for usage.", err, c.CommandPath()) + } + } +} + +func (templater *templater) ExposeFlags(cmd *cobra.Command, flags ...string) FlagExposer { + cmd.SetUsageFunc(templater.UsageFunc(flags...)) + return templater +} + +func (templater *templater) HelpFunc() func(*cobra.Command, []string) { + return func(c *cobra.Command, s []string) { + t := template.New("help") + t.Funcs(templater.templateFuncs()) + template.Must(t.Parse(templater.HelpTemplate)) + out := term.NewResponsiveWriter(c.OutOrStdout()) + err := t.Execute(out, c) + if err != nil { + c.Println(err) + } + } +} + +func (templater *templater) UsageFunc(exposedFlags ...string) func(*cobra.Command) error { + return func(c *cobra.Command) error { + t := template.New("usage") + t.Funcs(templater.templateFuncs(exposedFlags...)) + template.Must(t.Parse(templater.UsageTemplate)) + out := term.NewResponsiveWriter(c.OutOrStderr()) + return t.Execute(out, c) + } +} + +func (templater *templater) templateFuncs(exposedFlags ...string) template.FuncMap { + return template.FuncMap{ + "trim": strings.TrimSpace, + "trimRight": func(s string) string { return strings.TrimRightFunc(s, unicode.IsSpace) }, + "trimLeft": func(s string) string { return strings.TrimLeftFunc(s, unicode.IsSpace) }, + "gt": cobra.Gt, + "eq": cobra.Eq, + "rpad": rpad, + "appendIfNotPresent": appendIfNotPresent, + "flagsNotIntersected": flagsNotIntersected, + "visibleFlags": visibleFlags, + "flagsUsages": flagsUsages, + "cmdGroups": templater.cmdGroups, + "cmdGroupsString": templater.cmdGroupsString, + "rootCmd": templater.rootCmdName, + "isRootCmd": templater.isRootCmd, + "optionsCmdFor": templater.optionsCmdFor, + "usageLine": templater.usageLine, + "reverseParentsNames": templater.reverseParentsNames, + "exposed": func(c *cobra.Command) *flag.FlagSet { + exposed := flag.NewFlagSet("exposed", flag.ContinueOnError) + if len(exposedFlags) > 0 { + for _, name := range exposedFlags { + if flag := c.Flags().Lookup(name); flag != nil { + exposed.AddFlag(flag) + } + } + } + return exposed + }, + } +} + +func (templater *templater) cmdGroups(c *cobra.Command, all []*cobra.Command) []CommandGroup { + if len(templater.CommandGroups) > 0 && c == templater.RootCmd { + all = filter(all, templater.Filtered...) + return AddAdditionalCommands(templater.CommandGroups, "Other Commands:", all) + } + all = filter(all, "options") + return []CommandGroup{ + { + Message: "Available Commands:", + Commands: all, + }, + } +} + +func (t *templater) cmdGroupsString(c *cobra.Command) string { + groups := []string{} + for _, cmdGroup := range t.cmdGroups(c, c.Commands()) { + cmds := []string{cmdGroup.Message} + for _, cmd := range cmdGroup.Commands { + if cmd.IsAvailableCommand() { + cmds = append(cmds, " "+rpad(cmd.Name(), cmd.NamePadding())+" "+cmd.Short) + } + } + groups = append(groups, strings.Join(cmds, "\n")) + } + return strings.Join(groups, "\n\n") +} + +func (t *templater) rootCmdName(c *cobra.Command) string { + return t.rootCmd(c).CommandPath() +} + +func (t *templater) reverseParentsNames(c *cobra.Command) []string { + reverseParentsNames := []string{} + parents := t.parents(c) + for i := len(parents) - 1; i >= 0; i-- { + reverseParentsNames = append(reverseParentsNames, parents[i].Name()) + } + return reverseParentsNames +} + +func (t *templater) isRootCmd(c *cobra.Command) bool { + return t.rootCmd(c) == c +} + +func (t *templater) parents(c *cobra.Command) []*cobra.Command { + parents := []*cobra.Command{c} + for current := c; !t.isRootCmd(current) && current.HasParent(); { + current = current.Parent() + parents = append(parents, current) + } + return parents +} + +func (t *templater) rootCmd(c *cobra.Command) *cobra.Command { + if c != nil && !c.HasParent() { + return c + } + if t.RootCmd == nil { + panic("nil root cmd") + } + return t.RootCmd +} + +func (t *templater) optionsCmdFor(c *cobra.Command) string { + if !c.Runnable() { + return "" + } + rootCmdStructure := t.parents(c) + for i := len(rootCmdStructure) - 1; i >= 0; i-- { + cmd := rootCmdStructure[i] + if _, _, err := cmd.Find([]string{"options"}); err == nil { + return cmd.CommandPath() + " options" + } + } + return "" +} + +func (t *templater) usageLine(c *cobra.Command) string { + usage := c.UseLine() + suffix := "[options]" + if c.HasFlags() && !strings.Contains(usage, suffix) { + usage += " " + suffix + } + return usage +} + +// flagsUsages will print out the kubectl help flags +func flagsUsages(f *flag.FlagSet) (string, error) { + flagBuf := new(bytes.Buffer) + wrapLimit, err := term.GetWordWrapperLimit() + if err != nil { + wrapLimit = 0 + } + printer := NewHelpFlagPrinter(flagBuf, wrapLimit) + + f.VisitAll(func(flag *flag.Flag) { + if flag.Hidden { + return + } + printer.PrintHelpFlag(flag) + }) + + return flagBuf.String(), nil +} + +// getFlagFormat will output the flag format +func getFlagFormat(f *flag.Flag) string { + var format string + format = "--%s=%s:\n%s%s" + if f.Value.Type() == "string" { + format = "--%s='%s':\n%s%s" + } + + if len(f.Shorthand) > 0 { + format = " -%s, " + format + } else { + format = " %s" + format + } + + return format +} + +func rpad(s string, padding int) string { + template := fmt.Sprintf("%%-%ds", padding) + return fmt.Sprintf(template, s) +} + +func appendIfNotPresent(s, stringToAppend string) string { + if strings.Contains(s, stringToAppend) { + return s + } + return s + " " + stringToAppend +} + +func flagsNotIntersected(l *flag.FlagSet, r *flag.FlagSet) *flag.FlagSet { + f := flag.NewFlagSet("notIntersected", flag.ContinueOnError) + l.VisitAll(func(flag *flag.Flag) { + if r.Lookup(flag.Name) == nil { + f.AddFlag(flag) + } + }) + return f +} + +func visibleFlags(l *flag.FlagSet) *flag.FlagSet { + hidden := "help" + f := flag.NewFlagSet("visible", flag.ContinueOnError) + l.VisitAll(func(flag *flag.Flag) { + if flag.Name != hidden { + f.AddFlag(flag) + } + }) + return f +} + +func filter(cmds []*cobra.Command, names ...string) []*cobra.Command { + out := []*cobra.Command{} + for _, c := range cmds { + if c.Hidden { + continue + } + skip := false + for _, name := range names { + if name == c.Name() { + skip = true + break + } + } + if skip { + continue + } + out = append(out, c) + } + return out +} diff --git a/vendor/k8s.io/kubectl/pkg/util/templates/templates.go b/vendor/k8s.io/kubectl/pkg/util/templates/templates.go new file mode 100644 index 0000000000..454695c0b2 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/templates/templates.go @@ -0,0 +1,104 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package templates + +import ( + "strings" + "unicode" +) + +const ( + // SectionVars is the help template section that declares variables to be used in the template. + SectionVars = `{{$isRootCmd := isRootCmd .}}` + + `{{$rootCmd := rootCmd .}}` + + `{{$visibleFlags := visibleFlags (flagsNotIntersected .LocalFlags .PersistentFlags)}}` + + `{{$explicitlyExposedFlags := exposed .}}` + + `{{$optionsCmdFor := optionsCmdFor .}}` + + `{{$usageLine := usageLine .}}` + + `{{$reverseParentsNames := reverseParentsNames .}}` + + // SectionAliases is the help template section that displays command aliases. + SectionAliases = `{{if gt .Aliases 0}}Aliases: +{{.NameAndAliases}} + +{{end}}` + + // SectionExamples is the help template section that displays command examples. + SectionExamples = `{{if .HasExample}}Examples: +{{trimRight .Example}} + +{{end}}` + + // SectionSubcommands is the help template section that displays the command's subcommands. + SectionSubcommands = `{{if .HasAvailableSubCommands}}{{cmdGroupsString .}} + +{{end}}` + + // SectionFlags is the help template section that displays the command's flags. + SectionFlags = `{{ if or $visibleFlags.HasFlags $explicitlyExposedFlags.HasFlags}}Options: +{{ if $visibleFlags.HasFlags}}{{trimRight (flagsUsages $visibleFlags)}}{{end}}{{ if $explicitlyExposedFlags.HasFlags}}{{ if $visibleFlags.HasFlags}} +{{end}}{{trimRight (flagsUsages $explicitlyExposedFlags)}}{{end}} + +{{end}}` + + // SectionUsage is the help template section that displays the command's usage. + SectionUsage = `{{if and .Runnable (ne .UseLine "") (ne .UseLine $rootCmd)}}Usage: + {{$usageLine}} + +{{end}}` + + // SectionTipsHelp is the help template section that displays the '--help' hint. + SectionTipsHelp = `{{if .HasSubCommands}}Use "{{range $reverseParentsNames}}{{.}} {{end}} --help" for more information about a given command. +{{end}}` + + // SectionTipsGlobalOptions is the help template section that displays the 'options' hint for displaying global flags. + SectionTipsGlobalOptions = `{{if $optionsCmdFor}}Use "{{$optionsCmdFor}}" for a list of global command-line options (applies to all commands). +{{end}}` +) + +// MainHelpTemplate if the template for 'help' used by most commands. +func MainHelpTemplate() string { + return `{{with or .Long .Short }}{{. | trim}}{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}` +} + +// MainUsageTemplate if the template for 'usage' used by most commands. +func MainUsageTemplate() string { + sections := []string{ + "\n\n", + SectionVars, + SectionAliases, + SectionExamples, + SectionSubcommands, + SectionFlags, + SectionUsage, + SectionTipsHelp, + SectionTipsGlobalOptions, + } + return strings.TrimRightFunc(strings.Join(sections, ""), unicode.IsSpace) +} + +// OptionsHelpTemplate if the template for 'help' used by the 'options' command. +func OptionsHelpTemplate() string { + return "" +} + +// OptionsUsageTemplate if the template for 'usage' used by the 'options' command. +func OptionsUsageTemplate() string { + return `{{ if .HasInheritedFlags}}The following options can be passed to any command: + +{{flagsUsages .InheritedFlags}}{{end}}` +} diff --git a/vendor/k8s.io/kubectl/pkg/util/term/resize.go b/vendor/k8s.io/kubectl/pkg/util/term/resize.go new file mode 100644 index 0000000000..636b8bef45 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/term/resize.go @@ -0,0 +1,132 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package term + +import ( + "fmt" + + "github.com/moby/term" + "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/tools/remotecommand" +) + +// GetSize returns the current size of the user's terminal. If it isn't a terminal, +// nil is returned. +func (t TTY) GetSize() *remotecommand.TerminalSize { + outFd, isTerminal := term.GetFdInfo(t.Out) + if !isTerminal { + return nil + } + return GetSize(outFd) +} + +// GetSize returns the current size of the terminal associated with fd. +func GetSize(fd uintptr) *remotecommand.TerminalSize { + winsize, err := term.GetWinsize(fd) + if err != nil { + runtime.HandleError(fmt.Errorf("unable to get terminal size: %v", err)) + return nil + } + + return &remotecommand.TerminalSize{Width: winsize.Width, Height: winsize.Height} +} + +// MonitorSize monitors the terminal's size. It returns a TerminalSizeQueue primed with +// initialSizes, or nil if there's no TTY present. +func (t *TTY) MonitorSize(initialSizes ...*remotecommand.TerminalSize) remotecommand.TerminalSizeQueue { + outFd, isTerminal := term.GetFdInfo(t.Out) + if !isTerminal { + return nil + } + + t.sizeQueue = &sizeQueue{ + t: *t, + // make it buffered so we can send the initial terminal sizes without blocking, prior to starting + // the streaming below + resizeChan: make(chan remotecommand.TerminalSize, len(initialSizes)), + stopResizing: make(chan struct{}), + } + + t.sizeQueue.monitorSize(outFd, initialSizes...) + + return t.sizeQueue +} + +// sizeQueue implements remotecommand.TerminalSizeQueue +type sizeQueue struct { + t TTY + // resizeChan receives a Size each time the user's terminal is resized. + resizeChan chan remotecommand.TerminalSize + stopResizing chan struct{} +} + +// make sure sizeQueue implements the resize.TerminalSizeQueue interface +var _ remotecommand.TerminalSizeQueue = &sizeQueue{} + +// monitorSize primes resizeChan with initialSizes and then monitors for resize events. With each +// new event, it sends the current terminal size to resizeChan. +func (s *sizeQueue) monitorSize(outFd uintptr, initialSizes ...*remotecommand.TerminalSize) { + // send the initial sizes + for i := range initialSizes { + if initialSizes[i] != nil { + s.resizeChan <- *initialSizes[i] + } + } + + resizeEvents := make(chan remotecommand.TerminalSize, 1) + + monitorResizeEvents(outFd, resizeEvents, s.stopResizing) + + // listen for resize events in the background + go func() { + defer runtime.HandleCrash() + + for { + select { + case size, ok := <-resizeEvents: + if !ok { + return + } + + select { + // try to send the size to resizeChan, but don't block + case s.resizeChan <- size: + // send successful + default: + // unable to send / no-op + } + case <-s.stopResizing: + return + } + } + }() +} + +// Next returns the new terminal size after the terminal has been resized. It returns nil when +// monitoring has been stopped. +func (s *sizeQueue) Next() *remotecommand.TerminalSize { + size, ok := <-s.resizeChan + if !ok { + return nil + } + return &size +} + +// stop stops the background goroutine that is monitoring for terminal resizes. +func (s *sizeQueue) stop() { + close(s.stopResizing) +} diff --git a/vendor/k8s.io/kubectl/pkg/util/term/resizeevents.go b/vendor/k8s.io/kubectl/pkg/util/term/resizeevents.go new file mode 100644 index 0000000000..e361b1adb3 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/term/resizeevents.go @@ -0,0 +1,62 @@ +//go:build !windows +// +build !windows + +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package term + +import ( + "os" + "os/signal" + + "golang.org/x/sys/unix" + "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/tools/remotecommand" +) + +// monitorResizeEvents spawns a goroutine that waits for SIGWINCH signals (these indicate the +// terminal has resized). After receiving a SIGWINCH, this gets the terminal size and tries to send +// it to the resizeEvents channel. The goroutine stops when the stop channel is closed. +func monitorResizeEvents(fd uintptr, resizeEvents chan<- remotecommand.TerminalSize, stop chan struct{}) { + go func() { + defer runtime.HandleCrash() + + winch := make(chan os.Signal, 1) + signal.Notify(winch, unix.SIGWINCH) + defer signal.Stop(winch) + + for { + select { + case <-winch: + size := GetSize(fd) + if size == nil { + return + } + + // try to send size + select { + case resizeEvents <- *size: + // success + default: + // not sent + } + case <-stop: + return + } + } + }() +} diff --git a/vendor/k8s.io/kubectl/pkg/util/term/resizeevents_windows.go b/vendor/k8s.io/kubectl/pkg/util/term/resizeevents_windows.go new file mode 100644 index 0000000000..adccf87346 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/term/resizeevents_windows.go @@ -0,0 +1,62 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package term + +import ( + "time" + + "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/client-go/tools/remotecommand" +) + +// monitorResizeEvents spawns a goroutine that periodically gets the terminal size and tries to send +// it to the resizeEvents channel if the size has changed. The goroutine stops when the stop channel +// is closed. +func monitorResizeEvents(fd uintptr, resizeEvents chan<- remotecommand.TerminalSize, stop chan struct{}) { + go func() { + defer runtime.HandleCrash() + + size := GetSize(fd) + if size == nil { + return + } + lastSize := *size + + for { + // see if we need to stop running + select { + case <-stop: + return + default: + } + + size := GetSize(fd) + if size == nil { + return + } + + if size.Height != lastSize.Height || size.Width != lastSize.Width { + lastSize.Height = size.Height + lastSize.Width = size.Width + resizeEvents <- *size + } + + // sleep to avoid hot looping + time.Sleep(250 * time.Millisecond) + } + }() +} diff --git a/vendor/k8s.io/kubectl/pkg/util/term/term.go b/vendor/k8s.io/kubectl/pkg/util/term/term.go new file mode 100644 index 0000000000..93a992fe31 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/term/term.go @@ -0,0 +1,115 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package term + +import ( + "io" + "os" + + "k8s.io/cli-runtime/pkg/printers" + + "github.com/moby/term" + + "k8s.io/kubectl/pkg/util/interrupt" +) + +// SafeFunc is a function to be invoked by TTY. +type SafeFunc func() error + +// TTY helps invoke a function and preserve the state of the terminal, even if the process is +// terminated during execution. It also provides support for terminal resizing for remote command +// execution/attachment. +type TTY struct { + // In is a reader representing stdin. It is a required field. + In io.Reader + // Out is a writer representing stdout. It must be set to support terminal resizing. It is an + // optional field. + Out io.Writer + // Raw is true if the terminal should be set raw. + Raw bool + // TryDev indicates the TTY should try to open /dev/tty if the provided input + // is not a file descriptor. + TryDev bool + // Parent is an optional interrupt handler provided to this function - if provided + // it will be invoked after the terminal state is restored. If it is not provided, + // a signal received during the TTY will result in os.Exit(0) being invoked. + Parent *interrupt.Handler + + // sizeQueue is set after a call to MonitorSize() and is used to monitor SIGWINCH signals when the + // user's terminal resizes. + sizeQueue *sizeQueue +} + +// IsTerminalIn returns true if t.In is a terminal. Does not check /dev/tty +// even if TryDev is set. +func (t TTY) IsTerminalIn() bool { + return printers.IsTerminal(t.In) +} + +// IsTerminalOut returns true if t.Out is a terminal. Does not check /dev/tty +// even if TryDev is set. +func (t TTY) IsTerminalOut() bool { + return printers.IsTerminal(t.Out) +} + +// IsTerminal returns whether the passed object is a terminal or not. +// Deprecated: use printers.IsTerminal instead. +var IsTerminal = printers.IsTerminal + +// AllowsColorOutput returns true if the specified writer is a terminal and +// the process environment indicates color output is supported and desired. +// Deprecated: use printers.AllowsColorOutput instead. +var AllowsColorOutput = printers.AllowsColorOutput + +// Safe invokes the provided function and will attempt to ensure that when the +// function returns (or a termination signal is sent) that the terminal state +// is reset to the condition it was in prior to the function being invoked. If +// t.Raw is true the terminal will be put into raw mode prior to calling the function. +// If the input file descriptor is not a TTY and TryDev is true, the /dev/tty file +// will be opened (if available). +func (t TTY) Safe(fn SafeFunc) error { + inFd, isTerminal := term.GetFdInfo(t.In) + + if !isTerminal && t.TryDev { + if f, err := os.Open("/dev/tty"); err == nil { + defer f.Close() + inFd = f.Fd() + isTerminal = term.IsTerminal(inFd) + } + } + if !isTerminal { + return fn() + } + + var state *term.State + var err error + if t.Raw { + state, err = term.MakeRaw(inFd) + } else { + state, err = term.SaveState(inFd) + } + if err != nil { + return err + } + return interrupt.Chain(t.Parent, func() { + if t.sizeQueue != nil { + t.sizeQueue.stop() + } + + term.RestoreTerminal(inFd, state) + }).Run(fn) +} diff --git a/vendor/k8s.io/kubectl/pkg/util/term/term_writer.go b/vendor/k8s.io/kubectl/pkg/util/term/term_writer.go new file mode 100644 index 0000000000..e3f6008802 --- /dev/null +++ b/vendor/k8s.io/kubectl/pkg/util/term/term_writer.go @@ -0,0 +1,146 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package term + +import ( + "errors" + "io" + "os" + + wordwrap "github.com/mitchellh/go-wordwrap" + "github.com/moby/term" + + "k8s.io/client-go/tools/remotecommand" +) + +type wordWrapWriter struct { + limit uint + writer io.Writer +} + +// NewResponsiveWriter creates a Writer that detects the column width of the +// terminal we are in, and adjusts every line width to fit and use recommended +// terminal sizes for better readability. Does proper word wrapping automatically. +// +// if terminal width >= 120 columns use 120 columns +// if terminal width >= 100 columns use 100 columns +// if terminal width >= 80 columns use 80 columns +// +// In case we're not in a terminal or if it's smaller than 80 columns width, +// doesn't do any wrapping. +func NewResponsiveWriter(w io.Writer) io.Writer { + file, ok := w.(*os.File) + if !ok { + return w + } + fd := file.Fd() + if !term.IsTerminal(fd) { + return w + } + + terminalSize := GetSize(fd) + if terminalSize == nil { + return w + } + limit := getTerminalLimitWidth(terminalSize) + + return NewWordWrapWriter(w, limit) +} + +// NewWordWrapWriter is a Writer that supports a limit of characters on every line +// and does auto word wrapping that respects that limit. +func NewWordWrapWriter(w io.Writer, limit uint) io.Writer { + return &wordWrapWriter{ + limit: limit, + writer: w, + } +} + +func getTerminalLimitWidth(terminalSize *remotecommand.TerminalSize) uint { + var limit uint + switch { + case terminalSize.Width >= 120: + limit = 120 + case terminalSize.Width >= 100: + limit = 100 + case terminalSize.Width >= 80: + limit = 80 + } + return limit +} + +func GetWordWrapperLimit() (uint, error) { + stdout := os.Stdout + fd := stdout.Fd() + if !term.IsTerminal(fd) { + return 0, errors.New("file descriptor is not a terminal") + } + terminalSize := GetSize(fd) + if terminalSize == nil { + return 0, errors.New("terminal size is nil") + } + return getTerminalLimitWidth(terminalSize), nil +} + +func (w wordWrapWriter) Write(p []byte) (nn int, err error) { + if w.limit == 0 { + return w.writer.Write(p) + } + original := string(p) + wrapped := wordwrap.WrapString(original, w.limit) + return w.writer.Write([]byte(wrapped)) +} + +// NewPunchCardWriter is a NewWordWrapWriter that limits the line width to 80 columns. +func NewPunchCardWriter(w io.Writer) io.Writer { + return NewWordWrapWriter(w, 80) +} + +type maxWidthWriter struct { + maxWidth uint + currentWidth uint + written uint + writer io.Writer +} + +// NewMaxWidthWriter is a Writer that supports a limit of characters on every +// line, but doesn't do any word wrapping automatically. +func NewMaxWidthWriter(w io.Writer, maxWidth uint) io.Writer { + return &maxWidthWriter{ + maxWidth: maxWidth, + writer: w, + } +} + +func (m maxWidthWriter) Write(p []byte) (nn int, err error) { + for _, b := range p { + if m.currentWidth == m.maxWidth { + m.writer.Write([]byte{'\n'}) + m.currentWidth = 0 + } + if b == '\n' { + m.currentWidth = 0 + } + _, err := m.writer.Write([]byte{b}) + if err != nil { + return int(m.written), err + } + m.written++ + m.currentWidth++ + } + return len(p), nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index a42098e00c..dd9320736d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,10 +1,17 @@ # github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 ## explicit; go 1.20 github.com/AdaLogics/go-fuzz-headers +# github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 +## explicit; go 1.16 +github.com/Azure/go-ansiterm +github.com/Azure/go-ansiterm/winterm # github.com/BurntSushi/toml v1.3.2 ## explicit; go 1.16 github.com/BurntSushi/toml github.com/BurntSushi/toml/internal +# github.com/MakeNowJust/heredoc v1.0.0 +## explicit; go 1.12 +github.com/MakeNowJust/heredoc # github.com/Microsoft/go-winio v0.6.2 ## explicit; go 1.21 github.com/Microsoft/go-winio @@ -46,6 +53,12 @@ github.com/Microsoft/hcsshim/pkg/ociwclayer # github.com/NYTimes/gziphandler v1.1.1 ## explicit; go 1.11 github.com/NYTimes/gziphandler +# github.com/akrylysov/pogreb v0.10.2 +## explicit; go 1.12 +github.com/akrylysov/pogreb +github.com/akrylysov/pogreb/fs +github.com/akrylysov/pogreb/internal/errors +github.com/akrylysov/pogreb/internal/hash # github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df ## explicit; go 1.18 github.com/antlr/antlr4/runtime/Go/antlr/v4 @@ -258,7 +271,26 @@ github.com/go-air/gini/inter github.com/go-air/gini/internal/xo github.com/go-air/gini/logic github.com/go-air/gini/z +<<<<<<< HEAD # github.com/go-logr/logr v1.4.2 +======= +# github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 +## explicit; go 1.13 +github.com/go-git/gcfg +github.com/go-git/gcfg/scanner +github.com/go-git/gcfg/token +github.com/go-git/gcfg/types +# github.com/go-git/go-billy/v5 v5.5.0 +## explicit; go 1.19 +github.com/go-git/go-billy/v5 +# github.com/go-git/go-git/v5 v5.11.0 +## explicit; go 1.19 +github.com/go-git/go-git/v5/internal/path_util +github.com/go-git/go-git/v5/plumbing/format/config +github.com/go-git/go-git/v5/plumbing/format/gitignore +github.com/go-git/go-git/v5/utils/ioutil +# github.com/go-logr/logr v1.4.1 +>>>>>>> 2452c2f43 (add opm to tools) ## explicit; go 1.18 github.com/go-logr/logr github.com/go-logr/logr/funcr @@ -362,6 +394,9 @@ github.com/google/uuid # github.com/gorilla/mux v1.8.1 ## explicit; go 1.20 github.com/gorilla/mux +# github.com/gorilla/websocket v1.5.0 +## explicit; go 1.12 +github.com/gorilla/websocket # github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 ## explicit github.com/grpc-ecosystem/go-grpc-prometheus @@ -391,6 +426,12 @@ github.com/itchyny/gojq # github.com/itchyny/timefmt-go v0.1.6 ## explicit; go 1.20 github.com/itchyny/timefmt-go +# github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 +## explicit +github.com/jbenet/go-context/io +# github.com/joelanford/ignore v0.1.0 +## explicit; go 1.21 +github.com/joelanford/ignore # github.com/josharian/intern v1.0.0 ## explicit; go 1.5 github.com/josharian/intern @@ -406,6 +447,9 @@ github.com/klauspost/compress/internal/cpuinfo github.com/klauspost/compress/internal/snapref github.com/klauspost/compress/zstd github.com/klauspost/compress/zstd/internal/xxhash +# github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de +## explicit +github.com/liggitt/tabwriter # github.com/mailru/easyjson v0.7.7 ## explicit; go 1.12 github.com/mailru/easyjson/buffer @@ -426,6 +470,9 @@ github.com/maxbrunsfeld/counterfeiter/v6 github.com/maxbrunsfeld/counterfeiter/v6/arguments github.com/maxbrunsfeld/counterfeiter/v6/command github.com/maxbrunsfeld/counterfeiter/v6/generator +# github.com/mitchellh/go-wordwrap v1.0.1 +## explicit; go 1.14 +github.com/mitchellh/go-wordwrap # github.com/mitchellh/hashstructure v1.1.0 ## explicit; go 1.14 github.com/mitchellh/hashstructure @@ -435,6 +482,10 @@ github.com/mitchellh/mapstructure # github.com/moby/locker v1.0.1 ## explicit; go 1.13 github.com/moby/locker +# github.com/moby/spdystream v0.2.0 +## explicit; go 1.13 +github.com/moby/spdystream +github.com/moby/spdystream/spdy # github.com/moby/sys/mountinfo v0.7.1 ## explicit; go 1.16 github.com/moby/sys/mountinfo @@ -444,6 +495,10 @@ github.com/moby/sys/sequential # github.com/moby/sys/user v0.1.0 ## explicit; go 1.17 github.com/moby/sys/user +# github.com/moby/term v0.5.0 +## explicit; go 1.18 +github.com/moby/term +github.com/moby/term/windows # github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd ## explicit github.com/modern-go/concurrent @@ -453,6 +508,9 @@ github.com/modern-go/reflect2 # github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 ## explicit github.com/munnerz/goautoneg +# github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f +## explicit +github.com/mxk/go-flowrate/flowrate # github.com/onsi/ginkgo/v2 v2.19.0 ## explicit; go 1.20 github.com/onsi/ginkgo/v2 @@ -542,9 +600,32 @@ github.com/operator-framework/api/pkg/validation/interfaces github.com/operator-framework/api/pkg/validation/internal # github.com/operator-framework/operator-registry v1.43.1 ## explicit; go 1.22.0 +github.com/operator-framework/operator-registry/alpha/action +github.com/operator-framework/operator-registry/alpha/declcfg github.com/operator-framework/operator-registry/alpha/model github.com/operator-framework/operator-registry/alpha/property +github.com/operator-framework/operator-registry/alpha/template/basic +github.com/operator-framework/operator-registry/alpha/template/composite +github.com/operator-framework/operator-registry/alpha/template/semver +github.com/operator-framework/operator-registry/cmd/opm +github.com/operator-framework/operator-registry/cmd/opm/alpha +github.com/operator-framework/operator-registry/cmd/opm/alpha/bundle +github.com/operator-framework/operator-registry/cmd/opm/alpha/list +github.com/operator-framework/operator-registry/cmd/opm/alpha/render-graph +github.com/operator-framework/operator-registry/cmd/opm/alpha/template +github.com/operator-framework/operator-registry/cmd/opm/generate +github.com/operator-framework/operator-registry/cmd/opm/index +github.com/operator-framework/operator-registry/cmd/opm/init +github.com/operator-framework/operator-registry/cmd/opm/internal/util +github.com/operator-framework/operator-registry/cmd/opm/migrate +github.com/operator-framework/operator-registry/cmd/opm/registry +github.com/operator-framework/operator-registry/cmd/opm/render +github.com/operator-framework/operator-registry/cmd/opm/root +github.com/operator-framework/operator-registry/cmd/opm/serve +github.com/operator-framework/operator-registry/cmd/opm/validate +github.com/operator-framework/operator-registry/cmd/opm/version github.com/operator-framework/operator-registry/pkg/api +github.com/operator-framework/operator-registry/pkg/cache github.com/operator-framework/operator-registry/pkg/client github.com/operator-framework/operator-registry/pkg/configmap github.com/operator-framework/operator-registry/pkg/containertools @@ -552,9 +633,18 @@ github.com/operator-framework/operator-registry/pkg/image github.com/operator-framework/operator-registry/pkg/image/containerdregistry github.com/operator-framework/operator-registry/pkg/image/execregistry github.com/operator-framework/operator-registry/pkg/lib/bundle +github.com/operator-framework/operator-registry/pkg/lib/certs +github.com/operator-framework/operator-registry/pkg/lib/config +github.com/operator-framework/operator-registry/pkg/lib/dns github.com/operator-framework/operator-registry/pkg/lib/encoding +github.com/operator-framework/operator-registry/pkg/lib/graceful +github.com/operator-framework/operator-registry/pkg/lib/indexer +github.com/operator-framework/operator-registry/pkg/lib/log +github.com/operator-framework/operator-registry/pkg/lib/registry github.com/operator-framework/operator-registry/pkg/lib/semver +github.com/operator-framework/operator-registry/pkg/lib/tmp github.com/operator-framework/operator-registry/pkg/lib/validation +github.com/operator-framework/operator-registry/pkg/mirror github.com/operator-framework/operator-registry/pkg/prettyunmarshaler github.com/operator-framework/operator-registry/pkg/registry github.com/operator-framework/operator-registry/pkg/server @@ -591,6 +681,9 @@ github.com/prometheus/common/model github.com/prometheus/procfs github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/util +# github.com/russross/blackfriday/v2 v2.1.0 +## explicit +github.com/russross/blackfriday/v2 # github.com/sirupsen/logrus v1.9.3 ## explicit; go 1.13 github.com/sirupsen/logrus @@ -611,6 +704,9 @@ github.com/stretchr/testify/require # github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 ## explicit github.com/syndtr/gocapability/capability +# github.com/tidwall/btree v1.7.0 +## explicit; go 1.19 +github.com/tidwall/btree # go.etcd.io/bbolt v1.3.10 ## explicit; go 1.21 go.etcd.io/bbolt @@ -900,6 +996,9 @@ google.golang.org/grpc/internal/transport/networktype google.golang.org/grpc/keepalive google.golang.org/grpc/metadata google.golang.org/grpc/peer +google.golang.org/grpc/reflection +google.golang.org/grpc/reflection/grpc_reflection_v1 +google.golang.org/grpc/reflection/grpc_reflection_v1alpha google.golang.org/grpc/resolver google.golang.org/grpc/resolver/dns google.golang.org/grpc/resolver/manual @@ -957,6 +1056,9 @@ gopkg.in/inf.v0 # gopkg.in/natefinch/lumberjack.v2 v2.2.1 ## explicit; go 1.13 gopkg.in/natefinch/lumberjack.v2 +# gopkg.in/warnings.v0 v0.1.2 +## explicit +gopkg.in/warnings.v0 # gopkg.in/yaml.v2 v2.4.0 ## explicit; go 1.15 gopkg.in/yaml.v2 @@ -1083,6 +1185,7 @@ k8s.io/apimachinery/pkg/util/duration k8s.io/apimachinery/pkg/util/errors k8s.io/apimachinery/pkg/util/framer k8s.io/apimachinery/pkg/util/httpstream +k8s.io/apimachinery/pkg/util/httpstream/spdy k8s.io/apimachinery/pkg/util/httpstream/wsstream k8s.io/apimachinery/pkg/util/intstr k8s.io/apimachinery/pkg/util/json @@ -1092,6 +1195,7 @@ k8s.io/apimachinery/pkg/util/mergepatch k8s.io/apimachinery/pkg/util/naming k8s.io/apimachinery/pkg/util/net k8s.io/apimachinery/pkg/util/portforward +k8s.io/apimachinery/pkg/util/proxy k8s.io/apimachinery/pkg/util/rand k8s.io/apimachinery/pkg/util/remotecommand k8s.io/apimachinery/pkg/util/runtime @@ -1107,6 +1211,7 @@ k8s.io/apimachinery/pkg/util/yaml k8s.io/apimachinery/pkg/version k8s.io/apimachinery/pkg/watch k8s.io/apimachinery/third_party/forked/golang/json +k8s.io/apimachinery/third_party/forked/golang/netutil k8s.io/apimachinery/third_party/forked/golang/reflect # k8s.io/apiserver v0.30.1 ## explicit; go 1.22.0 @@ -1257,6 +1362,9 @@ k8s.io/apiserver/plugin/pkg/audit/webhook k8s.io/apiserver/plugin/pkg/authenticator/token/webhook k8s.io/apiserver/plugin/pkg/authorizer/webhook k8s.io/apiserver/plugin/pkg/authorizer/webhook/metrics +# k8s.io/cli-runtime v0.30.0 +## explicit; go 1.22.0 +k8s.io/cli-runtime/pkg/printers # k8s.io/client-go v0.30.1 ## explicit; go 1.22.0 k8s.io/client-go/applyconfigurations/admissionregistration/v1 @@ -1557,6 +1665,7 @@ k8s.io/client-go/rest/fake k8s.io/client-go/rest/watch k8s.io/client-go/restmapper k8s.io/client-go/testing +k8s.io/client-go/third_party/forked/golang/template k8s.io/client-go/tools/auth k8s.io/client-go/tools/cache k8s.io/client-go/tools/cache/synctrack @@ -1573,11 +1682,16 @@ k8s.io/client-go/tools/pager k8s.io/client-go/tools/record k8s.io/client-go/tools/record/util k8s.io/client-go/tools/reference +k8s.io/client-go/tools/remotecommand k8s.io/client-go/transport +k8s.io/client-go/transport/spdy +k8s.io/client-go/transport/websocket k8s.io/client-go/util/cert k8s.io/client-go/util/connrotation +k8s.io/client-go/util/exec k8s.io/client-go/util/flowcontrol k8s.io/client-go/util/homedir +k8s.io/client-go/util/jsonpath k8s.io/client-go/util/keyutil k8s.io/client-go/util/retry k8s.io/client-go/util/workqueue @@ -1709,6 +1823,11 @@ k8s.io/kube-openapi/pkg/validation/spec k8s.io/kube-openapi/pkg/validation/strfmt k8s.io/kube-openapi/pkg/validation/strfmt/bson k8s.io/kube-openapi/pkg/validation/validate +# k8s.io/kubectl v0.30.0 +## explicit; go 1.22.0 +k8s.io/kubectl/pkg/util/interrupt +k8s.io/kubectl/pkg/util/templates +k8s.io/kubectl/pkg/util/term # k8s.io/utils v0.0.0-20240102154912-e7106e64919e ## explicit; go 1.18 k8s.io/utils/buffer From 99974c582a18ede979c12afd3e3b9b3032f350c7 Mon Sep 17 00:00:00 2001 From: Per Goncalves da Silva Date: Mon, 10 Jun 2024 11:23:02 +0200 Subject: [PATCH 3/9] update test bundles and catalog to a declarative config Signed-off-by: Per Goncalves da Silva --- test/images/busybox-index/dockerfile | 17 ++++ .../indexv1/busybox-dependency/catalog.json | 89 ++++++++++++++++++ .../indexv1/busybox/catalog.json | 89 ++++++++++++++++++ .../indexv2/busybox-dependency/catalog.json | 93 +++++++++++++++++++ .../indexv2/busybox/catalog.json | 93 +++++++++++++++++++ 5 files changed, 381 insertions(+) create mode 100644 test/images/busybox-index/dockerfile create mode 100644 test/images/busybox-index/indexv1/busybox-dependency/catalog.json create mode 100644 test/images/busybox-index/indexv1/busybox/catalog.json create mode 100644 test/images/busybox-index/indexv2/busybox-dependency/catalog.json create mode 100644 test/images/busybox-index/indexv2/busybox/catalog.json diff --git a/test/images/busybox-index/dockerfile b/test/images/busybox-index/dockerfile new file mode 100644 index 0000000000..d7c77a96e9 --- /dev/null +++ b/test/images/busybox-index/dockerfile @@ -0,0 +1,17 @@ +# The base image is expected to contain +# /bin/opm (with a serve subcommand) and /bin/grpc_health_probe +ARG OPM_VERSION=latest +FROM quay.io/operator-framework/opm:${OPM_VERSION} + +# Set DC-specific label for the location of the DC root directory +# in the image +LABEL operators.operatorframework.io.index.configs.v1=/configs + +# Copy declarative config root into image at /configs and pre-populate serve cache +ARG CONFIGS_DIR=/configs +COPY ${CONFIGS_DIR} /configs +RUN ["/bin/opm", "serve", "/configs", "--cache-dir=/tmp/cache", "--cache-only"] + +# Configure the entrypoint and command +ENTRYPOINT ["/bin/opm"] +CMD ["serve", "/configs", "--cache-dir=/tmp/cache"] diff --git a/test/images/busybox-index/indexv1/busybox-dependency/catalog.json b/test/images/busybox-index/indexv1/busybox-dependency/catalog.json new file mode 100644 index 0000000000..0ca557b5ec --- /dev/null +++ b/test/images/busybox-index/indexv1/busybox-dependency/catalog.json @@ -0,0 +1,89 @@ +{ + "schema": "olm.package", + "name": "busybox-dependency", + "defaultChannel": "alpha" +} +{ + "schema": "olm.channel", + "name": "alpha", + "package": "busybox-dependency", + "entries": [ + { + "name": "busybox-dependency.v1.0.0" + } + ] +} +{ + "schema": "olm.bundle", + "name": "busybox-dependency.v1.0.0", + "package": "busybox-dependency", + "image": "quay.io/olmtest/busybox-dependency-bundle:1.0.0", + "properties": [ + { + "type": "olm.gvk", + "value": { + "group": "olm.test.io", + "kind": "Foo", + "version": "v1" + } + }, + { + "type": "olm.package", + "value": { + "packageName": "busybox-dependency", + "version": "1.0.0" + } + }, + { + "type": "olm.csv.metadata", + "value": { + "apiServiceDefinitions": {}, + "crdDescriptions": { + "owned": [ + { + "name": "foos.olm.test.io", + "version": "v1", + "kind": "Foo", + "displayName": "Foo", + "description": "Foo resources for testing dependencies" + } + ] + }, + "description": "A busybox-dependency CSV.\n", + "displayName": "busybox-dependency", + "installModes": [ + { + "type": "OwnNamespace", + "supported": true + }, + { + "type": "SingleNamespace", + "supported": true + }, + { + "type": "MultiNamespace", + "supported": true + }, + { + "type": "AllNamespaces", + "supported": true + } + ], + "maturity": "alpha", + "provider": { + "name": "Red Hat" + } + } + } + ], + "relatedImages": [ + { + "name": "", + "image": "busybox" + }, + { + "name": "", + "image": "quay.io/olmtest/busybox-dependency-bundle:1.0.0" + } + ] +} diff --git a/test/images/busybox-index/indexv1/busybox/catalog.json b/test/images/busybox-index/indexv1/busybox/catalog.json new file mode 100644 index 0000000000..b373409115 --- /dev/null +++ b/test/images/busybox-index/indexv1/busybox/catalog.json @@ -0,0 +1,89 @@ +{ + "schema": "olm.package", + "name": "busybox", + "defaultChannel": "alpha" +} +{ + "schema": "olm.channel", + "name": "alpha", + "package": "busybox", + "entries": [ + { + "name": "busybox.v1.0.0" + } + ] +} +{ + "schema": "olm.bundle", + "name": "busybox.v1.0.0", + "package": "busybox", + "image": "quay.io/olmtest/busybox-bundle:1.0.0", + "properties": [ + { + "type": "olm.gvk.required", + "value": { + "group": "olm.test.io", + "kind": "Foo", + "version": "v1" + } + }, + { + "type": "olm.package", + "value": { + "packageName": "busybox", + "version": "1.0.0" + } + }, + { + "type": "olm.csv.metadata", + "value": { + "apiServiceDefinitions": {}, + "crdDescriptions": { + "required": [ + { + "name": "foos.olm.test.io", + "version": "v1", + "kind": "Foo", + "displayName": "Foo", + "description": "Foo resources for testing dependencies" + } + ] + }, + "description": "A busybox CSV.\n", + "displayName": "busybox", + "installModes": [ + { + "type": "OwnNamespace", + "supported": true + }, + { + "type": "SingleNamespace", + "supported": true + }, + { + "type": "MultiNamespace", + "supported": true + }, + { + "type": "AllNamespaces", + "supported": true + } + ], + "maturity": "alpha", + "provider": { + "name": "Red Hat" + } + } + } + ], + "relatedImages": [ + { + "name": "", + "image": "busybox" + }, + { + "name": "", + "image": "quay.io/olmtest/busybox-bundle:1.0.0" + } + ] +} diff --git a/test/images/busybox-index/indexv2/busybox-dependency/catalog.json b/test/images/busybox-index/indexv2/busybox-dependency/catalog.json new file mode 100644 index 0000000000..f42e9fa257 --- /dev/null +++ b/test/images/busybox-index/indexv2/busybox-dependency/catalog.json @@ -0,0 +1,93 @@ +{ + "schema": "olm.package", + "name": "busybox-dependency", + "defaultChannel": "alpha" +} +{ + "schema": "olm.channel", + "name": "alpha", + "package": "busybox-dependency", + "entries": [ + { + "name": "busybox-dependency.v2.0.0", + "skipRange": ">=0.0.0 <2.0.0" + } + ] +} +{ + "schema": "olm.bundle", + "name": "busybox-dependency.v2.0.0", + "package": "busybox-dependency", + "image": "quay.io/olmtest/busybox-dependency-bundle:2.0.0", + "properties": [ + { + "type": "olm.gvk", + "value": { + "group": "olm.test.io", + "kind": "Foo", + "version": "v1" + } + }, + { + "type": "olm.package", + "value": { + "packageName": "busybox-dependency", + "version": "2.0.0" + } + }, + { + "type": "olm.csv.metadata", + "value": { + "annotations": { + "olm.skipRange": ">=0.0.0 <2.0.0" + }, + "apiServiceDefinitions": {}, + "crdDescriptions": { + "owned": [ + { + "name": "foos.olm.test.io", + "version": "v1", + "kind": "Foo", + "displayName": "Foo", + "description": "Foo resources for testing dependencies" + } + ] + }, + "description": "A busybox-dependency CSV.\n", + "displayName": "busybox-dependency", + "installModes": [ + { + "type": "OwnNamespace", + "supported": true + }, + { + "type": "SingleNamespace", + "supported": true + }, + { + "type": "MultiNamespace", + "supported": true + }, + { + "type": "AllNamespaces", + "supported": true + } + ], + "maturity": "alpha", + "provider": { + "name": "Red Hat" + } + } + } + ], + "relatedImages": [ + { + "name": "", + "image": "busybox" + }, + { + "name": "", + "image": "quay.io/olmtest/busybox-dependency-bundle:2.0.0" + } + ] +} diff --git a/test/images/busybox-index/indexv2/busybox/catalog.json b/test/images/busybox-index/indexv2/busybox/catalog.json new file mode 100644 index 0000000000..72e9999546 --- /dev/null +++ b/test/images/busybox-index/indexv2/busybox/catalog.json @@ -0,0 +1,93 @@ +{ + "schema": "olm.package", + "name": "busybox", + "defaultChannel": "alpha" +} +{ + "schema": "olm.channel", + "name": "alpha", + "package": "busybox", + "entries": [ + { + "name": "busybox.v2.0.0", + "skipRange": ">=0.0.0 <2.0.0" + } + ] +} +{ + "schema": "olm.bundle", + "name": "busybox.v2.0.0", + "package": "busybox", + "image": "quay.io/olmtest/busybox-bundle:2.0.0", + "properties": [ + { + "type": "olm.gvk.required", + "value": { + "group": "olm.test.io", + "kind": "Foo", + "version": "v1" + } + }, + { + "type": "olm.package", + "value": { + "packageName": "busybox", + "version": "2.0.0" + } + }, + { + "type": "olm.csv.metadata", + "value": { + "annotations": { + "olm.skipRange": ">=0.0.0 <2.0.0" + }, + "apiServiceDefinitions": {}, + "crdDescriptions": { + "required": [ + { + "name": "foos.olm.test.io", + "version": "v1", + "kind": "Foo", + "displayName": "Foo", + "description": "Foo resources for testing dependencies" + } + ] + }, + "description": "A busybox CSV.\n", + "displayName": "busybox", + "installModes": [ + { + "type": "OwnNamespace", + "supported": true + }, + { + "type": "SingleNamespace", + "supported": true + }, + { + "type": "MultiNamespace", + "supported": true + }, + { + "type": "AllNamespaces", + "supported": true + } + ], + "maturity": "alpha", + "provider": { + "name": "Red Hat" + } + } + } + ], + "relatedImages": [ + { + "name": "", + "image": "busybox" + }, + { + "name": "", + "image": "quay.io/olmtest/busybox-bundle:2.0.0" + } + ] +} From c6a99a417d01e71b4061c8d798d3939b6cfa46b7 Mon Sep 17 00:00:00 2001 From: Per Goncalves da Silva Date: Mon, 10 Jun 2024 13:04:28 +0200 Subject: [PATCH 4/9] update e2e test to take opm version as a parameter Signed-off-by: Per Goncalves da Silva --- Makefile | 2 +- test/e2e/catalog_e2e_test.go | 11 ++++++----- test/e2e/e2e_test.go | 20 ++++++++++---------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 62827f582e..c2a14132a2 100644 --- a/Makefile +++ b/Makefile @@ -251,7 +251,7 @@ GINKGO_OPTS += -v -randomize-suites -race -trace --show-node-events $(if $(E2E_F .PHONY: e2e e2e: #HELP Run e2e tests against a cluster running OLM (params: $E2E_TEST_NS (operator), $E2E_INSTALL_NS (operator-lifecycle-manager), $E2E_CATALOG_NS (operator-lifecycle-manager), $E2E_TIMEOUT (90m), $E2E_FLAKE_ATTEMPTS (1), $TEST(undefined)) - $(GO_TEST_ENV) $(GINKGO) -timeout $(E2E_TIMEOUT) $(GINKGO_OPTS) ./test/e2e -- -namespace=$(E2E_TEST_NS) -olmNamespace=$(E2E_INSTALL_NS) -catalogNamespace=$(E2E_CATALOG_NS) $(E2E_OPTS) + $(GO_TEST_ENV) $(GINKGO) -timeout $(E2E_TIMEOUT) $(GINKGO_OPTS) ./test/e2e -- -namespace=$(E2E_TEST_NS) -olmNamespace=$(E2E_INSTALL_NS) -catalogNamespace=$(E2E_CATALOG_NS) -opmVersion=$(OPERATOR_REGISTRY_VERSION) $(E2E_OPTS) .PHONY: e2e-local e2e-local: e2e-build kind-create deploy e2e diff --git a/test/e2e/catalog_e2e_test.go b/test/e2e/catalog_e2e_test.go index 7fbb968ed9..c2cb0bf0f7 100644 --- a/test/e2e/catalog_e2e_test.go +++ b/test/e2e/catalog_e2e_test.go @@ -49,6 +49,7 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { c operatorclient.ClientInterface crc versioned.Interface packageserverClient *packageserverclientset.Clientset + testCatalogImage string ) BeforeEach(func() { @@ -67,6 +68,7 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { c = ctx.Ctx().KubeClient() crc = ctx.Ctx().OperatorClient() packageserverClient = packageserverclientset.NewForConfigOrDie(ctx.Ctx().RESTConfig()) + testCatalogImage = fmt.Sprintf("quay.io/olmtest/test-catalog:v%s", testOpmVersion) }) AfterEach(func() { @@ -704,7 +706,7 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { }, Spec: v1alpha1.CatalogSourceSpec{ SourceType: v1alpha1.SourceTypeGrpc, - Image: communityOperatorsImage, + Image: testCatalogImage, GrpcPodConfig: &v1alpha1.GrpcPodConfig{ SecurityContextConfig: v1alpha1.Restricted, }, @@ -764,7 +766,7 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { }, Spec: v1alpha1.CatalogSourceSpec{ SourceType: v1alpha1.SourceTypeGrpc, - Image: communityOperatorsImage, + Image: testCatalogImage, GrpcPodConfig: &v1alpha1.GrpcPodConfig{ SecurityContextConfig: v1alpha1.Restricted, ExtractContent: &v1alpha1.ExtractContentConfig{ @@ -1075,7 +1077,7 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { }, Spec: v1alpha1.CatalogSourceSpec{ SourceType: v1alpha1.SourceTypeGrpc, - Image: catSrcImage + ":1.0.0-with-ListBundles-method", + Image: fmt.Sprintf("%s:1.0.0-with-ListBundles-method-%s", catSrcImage, testOpmVersion), GrpcPodConfig: &v1alpha1.GrpcPodConfig{ SecurityContextConfig: v1alpha1.Restricted, }, @@ -1126,8 +1128,7 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { if err != nil { return err } - existingSource.Spec.Image = catSrcImage + ":2.0.0-with-ListBundles-method" - + existingSource.Spec.Image = fmt.Sprintf("%s:2.0.0-with-ListBundles-method-%s", catSrcImage, testOpmVersion) source, err = crc.OperatorsV1alpha1().CatalogSources(source.GetNamespace()).Update(context.Background(), existingSource, metav1.UpdateOptions{}) return err }).Should(Succeed()) diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index 7deb176552..71cbec7b30 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -38,10 +38,10 @@ var ( catalogNamespace = flag.String( "catalogNamespace", "", "namespace where the global catalog content is stored") - communityOperators = flag.String( - "communityOperators", - "quay.io/operatorhubio/catalog:latest", - "reference to upstream-community-operators image", + opmVersion = flag.String( + "opmVersion", + "latest", + "opm version used by test images", ) dummyImage = flag.String( @@ -71,11 +71,11 @@ var ( "Note that this flag will override the kubeconfig flag.", ) - testdataDir = "" - testNamespace = "" - operatorNamespace = "" - communityOperatorsImage = "" - globalCatalogNamespace = "" + testdataDir = "" + testNamespace = "" + operatorNamespace = "" + testOpmVersion = "" + globalCatalogNamespace = "" ) func TestEndToEnd(t *testing.T) { @@ -104,7 +104,7 @@ var _ = BeforeSuite(func() { testNamespace = *namespace operatorNamespace = *olmNamespace - communityOperatorsImage = *communityOperators + testOpmVersion = *opmVersion globalCatalogNamespace = *catalogNamespace testdataDir = *testdataPath deprovision = ctx.MustProvision(ctx.Ctx()) From 5163af056d185420158d5a8af47f0980efb1e1c4 Mon Sep 17 00:00:00 2001 From: Per Goncalves da Silva Date: Mon, 10 Jun 2024 13:04:44 +0200 Subject: [PATCH 5/9] update fixture script and e2e gha Signed-off-by: Per Goncalves da Silva --- .github/workflows/e2e-tests.yml | 43 ++++++++--- Makefile | 5 +- scripts/e2e_test_fixtures.sh | 127 ++++++++++++++++++++++---------- 3 files changed, 125 insertions(+), 50 deletions(-) diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 0ba645efe6..60aba73228 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -15,22 +15,36 @@ jobs: runs-on: ubuntu-latest outputs: sha: ${{ steps.vars.outputs.sha }} + UPDATE_FIXTURES: ${{ steps.fixtures.outputs.UPDATE_FIXTURES }} steps: # checkout code and setup go - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version-file: "go.mod" + # add the fixtures changed flag (UPDATE_FIXTURES) to the job output to others can use it + - name: Rebuild fixtures if necessary + id: fixtures + run: | + UPDATE_FIXTURES="$(scripts/e2e_test_fixtures.sh --check)" + if [ "${UPDATE_FIXTURES}" == "true" ]; then + # rebuild fixtures and export the images to .tar.gz files with --save + scripts/e2e_test_fixtures.sh --save + fi + + # Add UPDATE_FIXTURES to the job output + echo "UPDATE_FIXTURES=${UPDATE_FIXTURES}" >> $GITHUB_OUTPUT + # build binaries and image for e2e test (includes experimental features) - - name: Build controller image - run: make e2e-build - - name: Save image - run: docker save quay.io/operator-framework/olm:local -o olm-image.tar - - name: Upload Docker image as artifact + - name: Build OLM Image + run: | + make e2e-build + docker save quay.io/operator-framework/olm:local | gzip > olm-image.tar.gz + - name: Upload Artifacts uses: actions/upload-artifact@v4 with: - name: olm-image.tar - path: olm-image.tar + name: docker-images + path: "*.tar.gz" # Run e2e tests in parallel jobs # Take olm image from the previous stage @@ -54,13 +68,17 @@ jobs: with: go-version-file: "go.mod" - # load the olm image - - name: Load OLM Docker image + # load images into kind + - name: Download build artifacts uses: actions/download-artifact@v4 with: - name: olm-image.tar - path: . - - run: docker load < olm-image.tar + name: docker-images + path: images/ + - name: Load Docker images + run: | + for image in images/*.tar.gz; do + docker load -i $image + done # set e2e environment variables # Set ginkgo output and parallelism @@ -87,6 +105,7 @@ jobs: KIND_CLUSTER_NAME="kind-olmv0-${i}" \ KIND_CREATE_OPTS="--kubeconfig=${E2E_KUBECONFIG_ROOT}/kubeconfig-${i}" \ HELM_INSTALL_OPTS="--kubeconfig ${E2E_KUBECONFIG_ROOT}/kubeconfig-${i}" \ + UPDATE_FIXTURES="${{ needs.build.outputs.UPDATE_FIXTURES }}" \ make kind-create deploy; done diff --git a/Makefile b/Makefile index c2a14132a2..33b8bb4716 100644 --- a/Makefile +++ b/Makefile @@ -213,7 +213,10 @@ kind-create: kind-clean #HELP Create a new kind cluster $KIND_CLUSTER_NAME (defa .PHONY: deploy OLM_IMAGE := quay.io/operator-framework/olm:local deploy: $(KIND) $(HELM) #HELP Deploy OLM to kind cluster $KIND_CLUSTER_NAME (default: kind-olmv0) using $OLM_IMAGE (default: quay.io/operator-framework/olm:local) - $(KIND) load docker-image $(OLM_IMAGE) --name $(KIND_CLUSTER_NAME); \ + $(KIND) load docker-image $(OLM_IMAGE) --name $(KIND_CLUSTER_NAME) + @if [ "${UPDATE_FIXTURES}" = "true" ]; then \ + scripts/e2e_test_fixtures.sh --kind-load --skip-build; \ + fi $(HELM) upgrade --install olm deploy/chart \ --set debug=true \ --set olm.image.ref=$(OLM_IMAGE) \ diff --git a/scripts/e2e_test_fixtures.sh b/scripts/e2e_test_fixtures.sh index 911c775cd6..72c38519af 100755 --- a/scripts/e2e_test_fixtures.sh +++ b/scripts/e2e_test_fixtures.sh @@ -1,12 +1,20 @@ #!/usr/bin/env bash +# Load bingo tools for kind +source .bingo/variables.env + # Default values +KIND=${KIND:-kind} +KIND_CLUSTER_NAME=${KIND_CLUSTER_NAME:-kind-olmv0} OPM_VERSION=$(go list -m github.com/operator-framework/operator-registry | cut -d" " -f2 | sed 's/^v//') PUSH=false +SAVE=false CONTAINER_RUNTIME=docker REGISTRY=quay.io/olmtest TARGET_BRANCH=master -JUST_CHECK=false +CHECK=false +LOAD_KIND=false +BUILD=true while [ $# -gt 0 ]; do case "$1" in @@ -20,7 +28,7 @@ while [ $# -gt 0 ]; do ;; # check if images need to be updated - won't build or push images --check) - JUST_CHECK="true" + CHECK="true" ;; # container runtime to use, e.g. podman (default docker) --container-runtime=*) @@ -34,12 +42,30 @@ while [ $# -gt 0 ]; do --target-branch=*) TARGET_BRANCH="${1#*=}" ;; - + --kind-load) + LOAD_KIND="true" + ;; + --save) + SAVE="true" + ;; + --skip-build) + BUILD="false" + ;; *) printf "*************************\n" printf "* Error: Invalid argument.\n" - # shellcheck disable=SC2059 - printf "* Usage: %s [--opm-version=version] [--push=true|false] [--container-runtime=runtime] [--registry=registry] [--target-branch=branch]\n" "$0" + printf "* Usage: %s [--opm-version=version] [--check] [--push] [--container-runtime=runtime] [--registry=registry] [--target-branch=branch] [--kind-load] [--save] [--skip-build] \n" "$0" + printf "\n" + printf "\t--opm-version: opm version to build the fixtures against, e.g. 1.39.0\n" + printf "\t--check: check if images need to be updated - won't build or push images\n" + printf "\t--push: push images to registry after build\n" + printf "\t--container-runtime: container runtime to use, e.g. podman (default docker)\n" + printf "\t--registry: registry to push images (default: quay.io/olmtest)\n" + printf "\t--target-branch: target branch to compare against when checking for changes (default: master)\n" + printf "\t--kind-load: load fixture images into kind cluster (default: false)\n" + printf "\t--save: save images to tar.gz files (default: false)\n" + printf "\t--skip-build: skip building images - useful if you just want to kind-load/save/push (default: false)\n" + printf "*************************\n" exit 1 esac @@ -50,6 +76,7 @@ function check_changes() { OPM_CHANGED=false FIXTURES_CHANGED=false + git fetch origin "${TARGET_BRANCH}" --depth=2 if git diff "origin/${TARGET_BRANCH}" -- go.mod | grep -E '^\+[[:space:]]+github.com/operator-framework/operator-registry' > /dev/null; then OPM_CHANGED=true fi @@ -65,14 +92,7 @@ function check_changes() { fi } -function push_fixtures() { - ${CONTAINER_RUNTIME} push "${TEST_CATALOG_IMAGE}" -} - -if [ "$JUST_CHECK" = true ]; then - check_changes - exit 0 -fi +set -x # Fixtures BUNDLE_V1_IMAGE="${REGISTRY}/busybox-bundle:1.0.0-${OPM_VERSION}" @@ -85,36 +105,69 @@ INDEX_V2="${REGISTRY}/busybox-dependencies-index:2.0.0-with-ListBundles-method-$ TEST_CATALOG_IMAGE="${REGISTRY}/test-catalog:${OPM_VERSION}" -# Busybox Operator Index Image -${CONTAINER_RUNTIME} build -t "${BUNDLE_V1_IMAGE}" ./test/images/busybox-index/busybox/1.0.0 -${CONTAINER_RUNTIME} build -t "${BUNDLE_V1_DEP_IMAGE}" ./test/images/busybox-index/busybox-dependency/1.0.0 -${CONTAINER_RUNTIME} build -t "${BUNDLE_V2_IMAGE}" ./test/images/busybox-index/busybox/2.0.0 -${CONTAINER_RUNTIME} build -t "${BUNDLE_V2_DEP_IMAGE}" ./test/images/busybox-index/busybox-dependency/2.0.0 +# Prints true if changes are detected, false otherwise +if [ "$CHECK" = "true" ]; then + check_changes + exit 0 +fi + +if [ "$BUILD" = "true" ]; then + # Busybox Operator + # Build bundles + ${CONTAINER_RUNTIME} build -t "${BUNDLE_V1_IMAGE}" ./test/images/busybox-index/busybox/1.0.0 + ${CONTAINER_RUNTIME} build -t "${BUNDLE_V1_DEP_IMAGE}" ./test/images/busybox-index/busybox-dependency/1.0.0 + ${CONTAINER_RUNTIME} build -t "${BUNDLE_V2_IMAGE}" ./test/images/busybox-index/busybox/2.0.0 + ${CONTAINER_RUNTIME} build -t "${BUNDLE_V2_DEP_IMAGE}" ./test/images/busybox-index/busybox-dependency/2.0.0 + + + # Build catalogs + ${CONTAINER_RUNTIME} build -t "${INDEX_V1}" --build-arg="OPM_VERSION=v${OPM_VERSION}" --build-arg="CONFIGS_DIR=indexv1" ./test/images/busybox-index + ${CONTAINER_RUNTIME} build -t "${INDEX_V2}" --build-arg="OPM_VERSION=v${OPM_VERSION}" --build-arg="CONFIGS_DIR=indexv2" ./test/images/busybox-index + + # The following catalog used for e2e tests related to serving an extracted registry + # See catalog_e2e_test.go + # let's just reuse one of the other catalogs for this - the tests don't care about the content + # only that a catalog's content can be extracted and served by a different container + ${CONTAINER_RUNTIME} tag "${INDEX_V2}" "${TEST_CATALOG_IMAGE}" +fi + +# Assumes images are already built, kind cluster is running, and kubeconfig is set +if [ "$LOAD_KIND" = true ]; then + ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${BUNDLE_V1_IMAGE}" + ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${BUNDLE_V1_DEP_IMAGE}" + ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${BUNDLE_V2_IMAGE}" + ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${BUNDLE_V2_DEP_IMAGE}" + ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${INDEX_V1}" + ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${INDEX_V2}" + ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${TEST_CATALOG_IMAGE}" +fi -# Build catalog from templates -mkdir -p ./test/images/busybox-index/indexv1 -mkdir -p ./test/images/busybox-index/indexv2 -sed -e "s|#BUNDLE_V1_IMAGE#|\"${BUNDLE_V1_IMAGE}\"|g" -e "s|#BUNDLE_V1_DEP_IMAGE#|\"${BUNDLE_V1_DEP_IMAGE}\"|g" ./test/images/busybox-index/busybox-index-v1.template.json > ./test/images/busybox-index/indexv1/catalog.json -sed -e "s|#BUNDLE_V1_IMAGE#|\"${BUNDLE_V1_IMAGE}\"|g" -e "s|#BUNDLE_V1_DEP_IMAGE#|\"${BUNDLE_V1_DEP_IMAGE}\"|g" -e "s|#BUNDLE_V2_IMAGE#|\"${BUNDLE_V2_IMAGE}\"|g" -e "s|#BUNDLE_V2_DEP_IMAGE#|\"${BUNDLE_V2_DEP_IMAGE}\"|g" ./test/images/busybox-index/busybox-index-v2.template.json > ./test/images/busybox-index/indexv2/catalog.json +# Assumes images are already built +if [ "${SAVE}" = true ]; then + ${CONTAINER_RUNTIME} save "${BUNDLE_V1_IMAGE}" | gzip > bundlev1.tar.gz + ${CONTAINER_RUNTIME} save "${BUNDLE_V1_DEP_IMAGE}" | gzip > bundlev1dep.tar.gz -# Clean up -rm -rf ./test/images/busybox-index/indexv1 -rm -rf ./test/images/busybox-index/indexv2 + ${CONTAINER_RUNTIME} save "${BUNDLE_V2_IMAGE}" | gzip > bundlev2.tar.gz + ${CONTAINER_RUNTIME} save "${BUNDLE_V2_DEP_IMAGE}" | gzip > bundlev2dep.tar.gz -# Test catalog used for e2e tests related to serving an extracted registry -# Let's reuse one of the other indices for this -${CONTAINER_RUNTIME} tag -t "${TEST_CATALOG_IMAGE}" "${INDEX_V2}" + ${CONTAINER_RUNTIME} save "${INDEX_V1}" | gzip > indexv1.tar.gz + ${CONTAINER_RUNTIME} save "${INDEX_V2}" | gzip > indexv2.tar.gz + ${CONTAINER_RUNTIME} save "${TEST_CATALOG_IMAGE}" | gzip > testcatalog.tar.gz +fi + +# Assumes images are already built if [ "$PUSH" = true ]; then # push bundles - ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" - ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" - ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" - ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" + ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" + ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" + ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" + ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" - # push indexes - ${CONTAINER_RUNTIME} push "${INDEX_V1}" - ${CONTAINER_RUNTIME} push "${INDEX_V2}" + # push indexes + ${CONTAINER_RUNTIME} push "${INDEX_V1}" + ${CONTAINER_RUNTIME} push "${INDEX_V2}" - # push test catalog + # push test catalog + ${CONTAINER_RUNTIME} push "${TEST_CATALOG_IMAGE}" fi From a5a75f44efb58b29c081b21310a5f5ddf1558884 Mon Sep 17 00:00:00 2001 From: Per Goncalves da Silva Date: Mon, 10 Jun 2024 18:48:21 +0200 Subject: [PATCH 6/9] ensure e2e fixture images are only pulled if not present Signed-off-by: Per Goncalves da Silva --- pkg/lib/image/image.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/lib/image/image.go b/pkg/lib/image/image.go index aa03e31c14..7cc5426bef 100644 --- a/pkg/lib/image/image.go +++ b/pkg/lib/image/image.go @@ -13,5 +13,12 @@ func InferImagePullPolicy(image string) corev1.PullPolicy { if strings.Contains(image, "@") { return corev1.PullIfNotPresent } + + // Ensure test registry images are pulled only if needed + // These will normally be loaded through kind load docker-image + // This is also helps support the e2e fixture image re-build flow (see e2e GHA) + if strings.HasPrefix(image, "quay.io/olmtest/") { + return corev1.PullIfNotPresent + } return corev1.PullAlways } From 442c42d69df5d789568dc06cd18c88350dca2e23 Mon Sep 17 00:00:00 2001 From: Per Goncalves da Silva Date: Tue, 11 Jun 2024 10:04:32 +0200 Subject: [PATCH 7/9] move fixture publishing to its own gha Signed-off-by: Per Goncalves da Silva --- .github/workflows/fixtures.yml | 33 +++++++++++++++++++++++++++++++++ pkg/lib/image/image.go | 2 +- scripts/build_test_images.sh | 19 ------------------- vendor/modules.txt | 6 +----- 4 files changed, 35 insertions(+), 25 deletions(-) create mode 100644 .github/workflows/fixtures.yml delete mode 100755 scripts/build_test_images.sh diff --git a/.github/workflows/fixtures.yml b/.github/workflows/fixtures.yml new file mode 100644 index 0000000000..1d4bc9c76a --- /dev/null +++ b/.github/workflows/fixtures.yml @@ -0,0 +1,33 @@ +name: fixtures +on: + push: + branches: + - master +jobs: + rebuild: + if: ${{ needs.build.outputs.UPDATE_FIXTURES == 'true' && success() }} + needs: e2e-tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: "go.mod" + - name: Docker Login + uses: docker/login-action@v3 + with: + registry: quay.io + username: ${{ secrets.QUAY_USERNAME }} + password: ${{ secrets.QUAY_PASSWORD }} + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: docker-images + path: images/ + - name: Load Docker images + run: | + for image in images/*.tar.gz; do + docker load -i $image + done + - name: Push fixture images + run: scripts/e2e_test_fixtures.sh --push --skip-build diff --git a/pkg/lib/image/image.go b/pkg/lib/image/image.go index 7cc5426bef..5920fa4fba 100644 --- a/pkg/lib/image/image.go +++ b/pkg/lib/image/image.go @@ -17,7 +17,7 @@ func InferImagePullPolicy(image string) corev1.PullPolicy { // Ensure test registry images are pulled only if needed // These will normally be loaded through kind load docker-image // This is also helps support the e2e fixture image re-build flow (see e2e GHA) - if strings.HasPrefix(image, "quay.io/olmtest/") { + if strings.HasPrefix(image, "quay.io/olmtest/test-catalog") { return corev1.PullIfNotPresent } return corev1.PullAlways diff --git a/scripts/build_test_images.sh b/scripts/build_test_images.sh deleted file mode 100755 index 32f1fcaa6e..0000000000 --- a/scripts/build_test_images.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash - -# Busybox Operator Index Image -docker build -t quay.io/olmtest/busybox-bundle:1.0.0 ./test/images/busybox-index/busybox/1.0.0 -docker build -t quay.io/olmtest/busybox-bundle:2.0.0 ./test/images/busybox-index/busybox/2.0.0 - -docker build -t quay.io/olmtest/busybox-dependency-bundle:1.0.0 ./test/images/busybox-index/busybox-dependency/1.0.0 -docker build -t quay.io/olmtest/busybox-dependency-bundle:2.0.0 ./test/images/busybox-index/busybox-dependency/2.0.0 - -docker push quay.io/olmtest/busybox-bundle:1.0.0 -docker push quay.io/olmtest/busybox-bundle:2.0.0 -docker push quay.io/olmtest/busybox-dependency-bundle:1.0.0 -docker push quay.io/olmtest/busybox-dependency-bundle:2.0.0 - -opm index add --bundles quay.io/olmtest/busybox-dependency-bundle:1.0.0,quay.io/olmtest/busybox-bundle:1.0.0 --tag quay.io/olmtest/busybox-dependencies-index:1.0.0-with-ListBundles-method -c docker -docker push quay.io/olmtest/busybox-dependencies-index:1.0.0-with-ListBundles-method - -opm index add --bundles quay.io/olmtest/busybox-dependency-bundle:2.0.0,quay.io/olmtest/busybox-bundle:2.0.0 --tag quay.io/olmtest/busybox-dependencies-index:2.0.0-with-ListBundles-method --from-index quay.io/olmtest/busybox-dependencies-index:1.0.0-with-ListBundles-method -c docker -docker push quay.io/olmtest/busybox-dependencies-index:2.0.0-with-ListBundles-method diff --git a/vendor/modules.txt b/vendor/modules.txt index dd9320736d..2f6b305658 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -271,9 +271,6 @@ github.com/go-air/gini/inter github.com/go-air/gini/internal/xo github.com/go-air/gini/logic github.com/go-air/gini/z -<<<<<<< HEAD -# github.com/go-logr/logr v1.4.2 -======= # github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 ## explicit; go 1.13 github.com/go-git/gcfg @@ -289,8 +286,7 @@ github.com/go-git/go-git/v5/internal/path_util github.com/go-git/go-git/v5/plumbing/format/config github.com/go-git/go-git/v5/plumbing/format/gitignore github.com/go-git/go-git/v5/utils/ioutil -# github.com/go-logr/logr v1.4.1 ->>>>>>> 2452c2f43 (add opm to tools) +# github.com/go-logr/logr v1.4.2 ## explicit; go 1.18 github.com/go-logr/logr github.com/go-logr/logr/funcr From e20bf75eb8af96abac77dfc18e935f63461e6d7e Mon Sep 17 00:00:00 2001 From: Per Goncalves da Silva Date: Fri, 14 Jun 2024 17:55:49 +0200 Subject: [PATCH 8/9] add internal registry Signed-off-by: Per Goncalves da Silva --- .github/workflows/e2e-tests.yml | 15 +- Makefile | 19 +- scripts/e2e_test_fixtures.sh | 8 +- scripts/generate_registry_cert.sh | 62 ++++++ scripts/image_registry.sh | 100 ++++++++++ scripts/publish_e2e_catalog.sh | 73 +++++++ test/e2e/catalog_e2e_test.go | 3 +- test/images/test-catalog/configs/.indexignore | 2 + test/images/test-catalog/configs/catalog.json | 187 ++++++++++++++++++ test/images/test-catalog/dockerfile | 16 ++ 10 files changed, 460 insertions(+), 25 deletions(-) create mode 100755 scripts/generate_registry_cert.sh create mode 100755 scripts/image_registry.sh create mode 100755 scripts/publish_e2e_catalog.sh create mode 100644 test/images/test-catalog/configs/.indexignore create mode 100644 test/images/test-catalog/configs/catalog.json create mode 100644 test/images/test-catalog/dockerfile diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 60aba73228..246b3f4b77 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -22,19 +22,6 @@ jobs: - uses: actions/setup-go@v5 with: go-version-file: "go.mod" - # add the fixtures changed flag (UPDATE_FIXTURES) to the job output to others can use it - - name: Rebuild fixtures if necessary - id: fixtures - run: | - UPDATE_FIXTURES="$(scripts/e2e_test_fixtures.sh --check)" - if [ "${UPDATE_FIXTURES}" == "true" ]; then - # rebuild fixtures and export the images to .tar.gz files with --save - scripts/e2e_test_fixtures.sh --save - fi - - # Add UPDATE_FIXTURES to the job output - echo "UPDATE_FIXTURES=${UPDATE_FIXTURES}" >> $GITHUB_OUTPUT - # build binaries and image for e2e test (includes experimental features) - name: Build OLM Image run: | @@ -106,7 +93,7 @@ jobs: KIND_CREATE_OPTS="--kubeconfig=${E2E_KUBECONFIG_ROOT}/kubeconfig-${i}" \ HELM_INSTALL_OPTS="--kubeconfig ${E2E_KUBECONFIG_ROOT}/kubeconfig-${i}" \ UPDATE_FIXTURES="${{ needs.build.outputs.UPDATE_FIXTURES }}" \ - make kind-create deploy; + make kind-create image-registry build-and-load-e2e-fixture-images deploy; done # run non-flakes if matrix-id is not 'flakes' diff --git a/Makefile b/Makefile index 33b8bb4716..340e54e708 100644 --- a/Makefile +++ b/Makefile @@ -210,13 +210,26 @@ kind-create: kind-clean #HELP Create a new kind cluster $KIND_CLUSTER_NAME (defa $(KIND) create cluster --name $(KIND_CLUSTER_NAME) --image $(KIND_CLUSTER_IMAGE) $(KIND_CREATE_OPTS) $(KIND) export kubeconfig --name $(KIND_CLUSTER_NAME) +.PHONY: image-registry +E2E_REGISTRY_NAME := docker-registry +E2E_REGISTRY_NAMESPACE := olm-e2e +export REGISTRY_ROOT := $(E2E_REGISTRY_NAME).$(E2E_REGISTRY_NAMESPACE).svc:5000 +export CATALOG_IMG := $(REGISTRY_ROOT)/test-catalog:e2e +image-registry: ## Setup in-cluster image registry + ./scripts/image_registry.sh "$(E2E_REGISTRY_NAMESPACE)" "$(E2E_REGISTRY_NAME)" + +.PHONY: build-and-load-e2e-fixture-images +build-and-load-e2e-fixture-images: # Build e2e fixture images and either kind-load or push them to an on-cluster registry + # build and kind-load fixture images + scripts/e2e_test_fixtures.sh --kind-load + + # push the test-catalog to an on-cluster registry + ./scripts/publish_e2e_catalog.sh $(E2E_REGISTRY_NAMESPACE) $(CATALOG_IMG) + .PHONY: deploy OLM_IMAGE := quay.io/operator-framework/olm:local deploy: $(KIND) $(HELM) #HELP Deploy OLM to kind cluster $KIND_CLUSTER_NAME (default: kind-olmv0) using $OLM_IMAGE (default: quay.io/operator-framework/olm:local) $(KIND) load docker-image $(OLM_IMAGE) --name $(KIND_CLUSTER_NAME) - @if [ "${UPDATE_FIXTURES}" = "true" ]; then \ - scripts/e2e_test_fixtures.sh --kind-load --skip-build; \ - fi $(HELM) upgrade --install olm deploy/chart \ --set debug=true \ --set olm.image.ref=$(OLM_IMAGE) \ diff --git a/scripts/e2e_test_fixtures.sh b/scripts/e2e_test_fixtures.sh index 72c38519af..caf4a11b1f 100755 --- a/scripts/e2e_test_fixtures.sh +++ b/scripts/e2e_test_fixtures.sh @@ -128,6 +128,8 @@ if [ "$BUILD" = "true" ]; then # See catalog_e2e_test.go # let's just reuse one of the other catalogs for this - the tests don't care about the content # only that a catalog's content can be extracted and served by a different container + # There is no point in kind-loading this image since the image pull policy is AlwaysPull + # This image will be published in an on cluster registry ${CONTAINER_RUNTIME} tag "${INDEX_V2}" "${TEST_CATALOG_IMAGE}" fi @@ -139,7 +141,6 @@ if [ "$LOAD_KIND" = true ]; then ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${BUNDLE_V2_DEP_IMAGE}" ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${INDEX_V1}" ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${INDEX_V2}" - ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${TEST_CATALOG_IMAGE}" fi # Assumes images are already built @@ -152,8 +153,6 @@ if [ "${SAVE}" = true ]; then ${CONTAINER_RUNTIME} save "${INDEX_V1}" | gzip > indexv1.tar.gz ${CONTAINER_RUNTIME} save "${INDEX_V2}" | gzip > indexv2.tar.gz - - ${CONTAINER_RUNTIME} save "${TEST_CATALOG_IMAGE}" | gzip > testcatalog.tar.gz fi # Assumes images are already built @@ -167,7 +166,4 @@ if [ "$PUSH" = true ]; then # push indexes ${CONTAINER_RUNTIME} push "${INDEX_V1}" ${CONTAINER_RUNTIME} push "${INDEX_V2}" - - # push test catalog - ${CONTAINER_RUNTIME} push "${TEST_CATALOG_IMAGE}" fi diff --git a/scripts/generate_registry_cert.sh b/scripts/generate_registry_cert.sh new file mode 100755 index 0000000000..0dc583116e --- /dev/null +++ b/scripts/generate_registry_cert.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +set -x + +help=" +generate_registry_cert.sh is a script to generate the self-signed certificates used by the internal registry. +Usage: + generate_registry_cert.sh [NAMESPACE] [NAME] + +Argument Descriptions: + - NAMESPACE is the namespace that should be created and is the namespace in which the image registry will be created + - NAME is the name that should be used for the image registry Deployment and Service +" + +if [[ "$#" -ne 2 ]]; then + echo "Illegal number of arguments passed" + echo "${help}" + exit 1 +fi + +namespace=$1 +name=$2 + +# Generate ECDSA private key +openssl ecparam -genkey -name prime256v1 -out tls.key + +# Create CSR configuration file (csr.conf) +cat < csr.conf +[ req ] +prompt = no +distinguished_name = dn + +[ dn ] +CN = ${name}.${namespace}.svc + +[ alt_names ] +DNS.1 = ${name}.${namespace}.svc +DNS.2 = ${name}.${namespace}.cluster.local +EOF + +# Generate CSR +openssl req -new -key tls.key -out tls.csr -config csr.conf + +# Create certificate configuration file (cert.conf) +cat < cert.conf +[ req ] +prompt = no +distinguished_name = dn + +[ dn ] +CN = ${name}.${namespace}.svc + +[ alt_names ] +DNS.1 = ${name}.${namespace}.svc +DNS.2 = ${name}.${namespace}.cluster.local +EOF + +# Generate self-signed certificate +openssl req -x509 -key tls.key -in tls.csr -out tls.crt -days 3650 -config cert.conf + +# Remove temporary files +rm -rf cert.conf csr.conf tls.csr \ No newline at end of file diff --git a/scripts/image_registry.sh b/scripts/image_registry.sh new file mode 100755 index 0000000000..fc4752b8ea --- /dev/null +++ b/scripts/image_registry.sh @@ -0,0 +1,100 @@ +#! /bin/bash + +set -o errexit +set -o nounset +set -o pipefail + +set -x + +help=" +image_registry.sh is a script to stand up an image registry within a cluster. +Usage: + image_registry.sh [NAMESPACE] [NAME] + +Argument Descriptions: + - NAMESPACE is the namespace that should be created and is the namespace in which the image registry will be created + - NAME is the name that should be used for the image registry Deployment and Service +" + +if [[ "$#" -ne 2 ]]; then + echo "Illegal number of arguments passed" + echo "${help}" + exit 1 +fi + +namespace=$1 +name=$2 + +# Generate self-signed TLS certificate +./scripts/generate_registry_cert.sh "${namespace}" "${name}" + +# Read and base64 encode the certificate and key files +CERT_FILE=$(cat "tls.crt" | base64 | tr -d '\n') +KEY_FILE=$(cat "tls.key" | base64 | tr -d '\n') + +kubectl apply -f - << EOF +apiVersion: v1 +kind: Namespace +metadata: + name: ${namespace} +--- +apiVersion: v1 +kind: Secret +metadata: + name: ${namespace}-registry + namespace: ${namespace} +type: Opaque +data: + tls.crt: "${CERT_FILE}" + tls.key: "${KEY_FILE}" +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ${name} + namespace: ${namespace} + labels: + app: registry +spec: + replicas: 1 + selector: + matchLabels: + app: registry + template: + metadata: + labels: + app: registry + spec: + containers: + - name: registry + image: registry:2 + volumeMounts: + - name: certs-vol + mountPath: "/certs" + env: + - name: REGISTRY_HTTP_TLS_CERTIFICATE + value: "/certs/tls.crt" + - name: REGISTRY_HTTP_TLS_KEY + value: "/certs/tls.key" + volumes: + - name: certs-vol + secret: + secretName: ${namespace}-registry +--- +apiVersion: v1 +kind: Service +metadata: + name: ${name} + namespace: ${namespace} +spec: + selector: + app: registry + ports: + - port: 5000 + targetPort: 5000 +EOF + +kubectl wait --for=condition=Available -n "${namespace}" "deploy/${name}" --timeout=60s + +# Alternatively, just generate the pair once and save it to the repo. But then in 10 years we might need to generate a new certificate! +rm -rf tls.crt tls.key \ No newline at end of file diff --git a/scripts/publish_e2e_catalog.sh b/scripts/publish_e2e_catalog.sh new file mode 100755 index 0000000000..ba95c72ef4 --- /dev/null +++ b/scripts/publish_e2e_catalog.sh @@ -0,0 +1,73 @@ +#! /bin/bash + +set -o errexit +set -o nounset +set -o pipefail + +help=" +build-push-e2e-catalog.sh is a script to build and push the e2e catalog image using kaniko. +Usage: + build-push-e2e-catalog.sh [NAMESPACE] [TAG] + +Argument Descriptions: + - NAMESPACE is the namespace the kaniko Job should be created in + - TAG is the full tag used to build and push the catalog image +" + +if [[ "$#" -ne 2 ]]; then + echo "Illegal number of arguments passed" + echo "${help}" + exit 1 +fi + +namespace=$1 +tag=$2 + +OPM_VERSION=${OPM_VERSION:-"latest"} + +echo "${namespace}" "${tag}" + +# Delete existing configmaps +kubectl delete configmap -n "${namespace}" test-catalog.dockerfile --ignore-not-found +kubectl delete configmap -n "${namespace}" test-catalog.build-contents --ignore-not-found + +kubectl create configmap -n "${namespace}" --from-file=test/images/test-catalog/dockerfile test-catalog.dockerfile +kubectl create configmap -n "${namespace}" --from-file=test/images/test-catalog/configs test-catalog.build-contents + +kubectl apply -f - << EOF +apiVersion: batch/v1 +kind: Job +metadata: + name: kaniko + namespace: "${namespace}" +spec: + template: + spec: + containers: + - name: kaniko + image: gcr.io/kaniko-project/executor:latest + args: [ "--build-arg=OPM_VERSION=${OPM_VERSION}", + "--dockerfile=/workspace/dockerfile", + "--context=/workspace", + "--destination=${tag}", + "--verbosity=trace", + "--skip-tls-verify"] + volumeMounts: + - name: dockerfile + mountPath: /workspace/ + - name: build-contents + mountPath: /workspace/configs/ + restartPolicy: Never + volumes: + - name: dockerfile + configMap: + name: test-catalog.dockerfile + items: + - key: dockerfile + path: dockerfile + - name: build-contents + configMap: + name: test-catalog.build-contents +EOF + +kubectl wait --for=condition=Complete -n "${namespace}" jobs/kaniko --timeout=60s \ No newline at end of file diff --git a/test/e2e/catalog_e2e_test.go b/test/e2e/catalog_e2e_test.go index c2cb0bf0f7..4eee96bef0 100644 --- a/test/e2e/catalog_e2e_test.go +++ b/test/e2e/catalog_e2e_test.go @@ -41,6 +41,7 @@ const ( openshiftregistryFQDN = "image-registry.openshift-image-registry.svc:5000" catsrcImage = "docker://quay.io/olmtest/catsrc-update-test:" badCSVDir = "bad-csv" + testCatalogImage = "docker-registry.olm-e2e.svc:5000/test-catalog:e2e" ) var _ = Describe("Starting CatalogSource e2e tests", func() { @@ -49,7 +50,6 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { c operatorclient.ClientInterface crc versioned.Interface packageserverClient *packageserverclientset.Clientset - testCatalogImage string ) BeforeEach(func() { @@ -68,7 +68,6 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { c = ctx.Ctx().KubeClient() crc = ctx.Ctx().OperatorClient() packageserverClient = packageserverclientset.NewForConfigOrDie(ctx.Ctx().RESTConfig()) - testCatalogImage = fmt.Sprintf("quay.io/olmtest/test-catalog:v%s", testOpmVersion) }) AfterEach(func() { diff --git a/test/images/test-catalog/configs/.indexignore b/test/images/test-catalog/configs/.indexignore new file mode 100644 index 0000000000..620c429a51 --- /dev/null +++ b/test/images/test-catalog/configs/.indexignore @@ -0,0 +1,2 @@ +/expected_all.json +..* \ No newline at end of file diff --git a/test/images/test-catalog/configs/catalog.json b/test/images/test-catalog/configs/catalog.json new file mode 100644 index 0000000000..4fa297577e --- /dev/null +++ b/test/images/test-catalog/configs/catalog.json @@ -0,0 +1,187 @@ +{ + "schema": "olm.package", + "name": "busybox", + "defaultChannel": "alpha" +} +{ + "schema": "olm.channel", + "name": "alpha", + "package": "busybox", + "entries": [ + { + "name": "busybox.v2.0.0", + "skipRange": ">=0.0.0 <2.0.0" + } + ] +} +{ + "schema": "olm.bundle", + "name": "busybox.v2.0.0", + "package": "busybox", + "image": "quay.io/olmtest/busybox-bundle:2.0.0", + "properties": [ + { + "type": "olm.gvk.required", + "value": { + "group": "olm.test.io", + "kind": "Foo", + "version": "v1" + } + }, + { + "type": "olm.package", + "value": { + "packageName": "busybox", + "version": "2.0.0" + } + }, + { + "type": "olm.csv.metadata", + "value": { + "annotations": { + "olm.skipRange": ">=0.0.0 <2.0.0" + }, + "apiServiceDefinitions": {}, + "crdDescriptions": { + "required": [ + { + "name": "foos.olm.test.io", + "version": "v1", + "kind": "Foo", + "displayName": "Foo", + "description": "Foo resources for testing dependencies" + } + ] + }, + "description": "A busybox CSV.\n", + "displayName": "busybox", + "installModes": [ + { + "type": "OwnNamespace", + "supported": true + }, + { + "type": "SingleNamespace", + "supported": true + }, + { + "type": "MultiNamespace", + "supported": true + }, + { + "type": "AllNamespaces", + "supported": true + } + ], + "maturity": "alpha", + "provider": { + "name": "Red Hat" + } + } + } + ], + "relatedImages": [ + { + "name": "", + "image": "busybox" + }, + { + "name": "", + "image": "quay.io/olmtest/busybox-bundle:2.0.0" + } + ] +} +{ + "schema": "olm.package", + "name": "busybox-dependency", + "defaultChannel": "alpha" +} +{ + "schema": "olm.channel", + "name": "alpha", + "package": "busybox-dependency", + "entries": [ + { + "name": "busybox-dependency.v2.0.0", + "skipRange": ">=0.0.0 <2.0.0" + } + ] +} +{ + "schema": "olm.bundle", + "name": "busybox-dependency.v2.0.0", + "package": "busybox-dependency", + "image": "quay.io/olmtest/busybox-dependency-bundle:2.0.0", + "properties": [ + { + "type": "olm.gvk", + "value": { + "group": "olm.test.io", + "kind": "Foo", + "version": "v1" + } + }, + { + "type": "olm.package", + "value": { + "packageName": "busybox-dependency", + "version": "2.0.0" + } + }, + { + "type": "olm.csv.metadata", + "value": { + "annotations": { + "olm.skipRange": ">=0.0.0 <2.0.0" + }, + "apiServiceDefinitions": {}, + "crdDescriptions": { + "owned": [ + { + "name": "foos.olm.test.io", + "version": "v1", + "kind": "Foo", + "displayName": "Foo", + "description": "Foo resources for testing dependencies" + } + ] + }, + "description": "A busybox-dependency CSV.\n", + "displayName": "busybox-dependency", + "installModes": [ + { + "type": "OwnNamespace", + "supported": true + }, + { + "type": "SingleNamespace", + "supported": true + }, + { + "type": "MultiNamespace", + "supported": true + }, + { + "type": "AllNamespaces", + "supported": true + } + ], + "maturity": "alpha", + "provider": { + "name": "Red Hat" + } + } + } + ], + "relatedImages": [ + { + "name": "", + "image": "busybox" + }, + { + "name": "", + "image": "quay.io/olmtest/busybox-dependency-bundle:2.0.0" + } + ] +} + diff --git a/test/images/test-catalog/dockerfile b/test/images/test-catalog/dockerfile new file mode 100644 index 0000000000..8eea9fa74c --- /dev/null +++ b/test/images/test-catalog/dockerfile @@ -0,0 +1,16 @@ +# The base image is expected to contain +# /bin/opm (with a serve subcommand) and /bin/grpc_health_probe +ARG OPM_VERSION=latest +FROM quay.io/operator-framework/opm:${OPM_VERSION} + +# Set DC-specific label for the location of the DC root directory +# in the image +LABEL operators.operatorframework.io.index.configs.v1=/configs + +# Copy declarative config root into image at /configs and pre-populate serve cache +COPY configs /configs +RUN ["/bin/opm", "serve", "/configs", "--cache-dir=/tmp/cache", "--cache-only"] + +# Configure the entrypoint and command +ENTRYPOINT ["/bin/opm"] +CMD ["serve", "/configs", "--cache-dir=/tmp/cache"] From 17d51c360fc3e6f8354a16291b99f3b7bda71d21 Mon Sep 17 00:00:00 2001 From: Per Goncalves da Silva Date: Mon, 17 Jun 2024 18:49:32 +0200 Subject: [PATCH 9/9] move all catalogs to internal registry Signed-off-by: Per Goncalves da Silva --- .github/workflows/e2e-tests.yml | 1 - Makefile | 7 +- pkg/lib/image/image.go | 7 -- scripts/e2e_test_fixtures.sh | 24 ----- scripts/publish_e2e_catalog.sh | 44 +++------ test/e2e/catalog_e2e_test.go | 2 +- .../busybox-dependency/1.0.0/dockerfile | 0 .../1.0.0/manifests/csv.yaml | 0 .../1.0.0/manifests/foo.crd.yaml | 0 .../1.0.0/metadata/annotations.yaml | 0 .../busybox-dependency/2.0.0/dockerfile | 0 .../2.0.0/manifests/csv.yaml | 0 .../2.0.0/manifests/foo.crd.yaml | 0 .../2.0.0/metadata/annotations.yaml | 0 .../busybox/1.0.0/dockerfile | 0 .../busybox/1.0.0/manifests/csv.yaml | 0 .../busybox/1.0.0/metadata/annotations.yaml | 0 .../busybox/2.0.0/dockerfile | 0 .../busybox/2.0.0/manifests/csv.yaml | 0 .../busybox/2.0.0/metadata/annotations.yaml | 0 .../configs/.indexignore | 0 .../configs}/catalog.json | 89 ++++++++++++++++++ .../dockerfile | 2 +- .../busybox-index-v2/configs/.indexignore | 2 + .../configs/catalog.json | 1 - .../dockerfile | 3 +- .../indexv1/busybox/catalog.json | 89 ------------------ .../indexv2/busybox-dependency/catalog.json | 93 ------------------- .../indexv2/busybox/catalog.json | 93 ------------------- 29 files changed, 112 insertions(+), 345 deletions(-) rename test/images/{busybox-index => busybox-index-bundles}/busybox-dependency/1.0.0/dockerfile (100%) rename test/images/{busybox-index => busybox-index-bundles}/busybox-dependency/1.0.0/manifests/csv.yaml (100%) rename test/images/{busybox-index => busybox-index-bundles}/busybox-dependency/1.0.0/manifests/foo.crd.yaml (100%) rename test/images/{busybox-index => busybox-index-bundles}/busybox-dependency/1.0.0/metadata/annotations.yaml (100%) rename test/images/{busybox-index => busybox-index-bundles}/busybox-dependency/2.0.0/dockerfile (100%) rename test/images/{busybox-index => busybox-index-bundles}/busybox-dependency/2.0.0/manifests/csv.yaml (100%) rename test/images/{busybox-index => busybox-index-bundles}/busybox-dependency/2.0.0/manifests/foo.crd.yaml (100%) rename test/images/{busybox-index => busybox-index-bundles}/busybox-dependency/2.0.0/metadata/annotations.yaml (100%) rename test/images/{busybox-index => busybox-index-bundles}/busybox/1.0.0/dockerfile (100%) rename test/images/{busybox-index => busybox-index-bundles}/busybox/1.0.0/manifests/csv.yaml (100%) rename test/images/{busybox-index => busybox-index-bundles}/busybox/1.0.0/metadata/annotations.yaml (100%) rename test/images/{busybox-index => busybox-index-bundles}/busybox/2.0.0/dockerfile (100%) rename test/images/{busybox-index => busybox-index-bundles}/busybox/2.0.0/manifests/csv.yaml (100%) rename test/images/{busybox-index => busybox-index-bundles}/busybox/2.0.0/metadata/annotations.yaml (100%) rename test/images/{test-catalog => busybox-index-v1}/configs/.indexignore (100%) rename test/images/{busybox-index/indexv1/busybox-dependency => busybox-index-v1/configs}/catalog.json (51%) rename test/images/{test-catalog => busybox-index-v1}/dockerfile (96%) create mode 100644 test/images/busybox-index-v2/configs/.indexignore rename test/images/{test-catalog => busybox-index-v2}/configs/catalog.json (99%) rename test/images/{busybox-index => busybox-index-v2}/dockerfile (91%) delete mode 100644 test/images/busybox-index/indexv1/busybox/catalog.json delete mode 100644 test/images/busybox-index/indexv2/busybox-dependency/catalog.json delete mode 100644 test/images/busybox-index/indexv2/busybox/catalog.json diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 246b3f4b77..c79faee434 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -92,7 +92,6 @@ jobs: KIND_CLUSTER_NAME="kind-olmv0-${i}" \ KIND_CREATE_OPTS="--kubeconfig=${E2E_KUBECONFIG_ROOT}/kubeconfig-${i}" \ HELM_INSTALL_OPTS="--kubeconfig ${E2E_KUBECONFIG_ROOT}/kubeconfig-${i}" \ - UPDATE_FIXTURES="${{ needs.build.outputs.UPDATE_FIXTURES }}" \ make kind-create image-registry build-and-load-e2e-fixture-images deploy; done diff --git a/Makefile b/Makefile index 340e54e708..444f8caf2d 100644 --- a/Makefile +++ b/Makefile @@ -220,11 +220,10 @@ image-registry: ## Setup in-cluster image registry .PHONY: build-and-load-e2e-fixture-images build-and-load-e2e-fixture-images: # Build e2e fixture images and either kind-load or push them to an on-cluster registry - # build and kind-load fixture images - scripts/e2e_test_fixtures.sh --kind-load - # push the test-catalog to an on-cluster registry - ./scripts/publish_e2e_catalog.sh $(E2E_REGISTRY_NAMESPACE) $(CATALOG_IMG) + ./scripts/publish_e2e_catalog.sh "test/images/busybox-index-v1" "indexv1" "$(E2E_REGISTRY_NAMESPACE)" "$(REGISTRY_ROOT)/busybox-dependencies-index:1.0.0-with-ListBundles-method-${OPERATOR_REGISTRY_VERSION}" + ./scripts/publish_e2e_catalog.sh "test/images/busybox-index-v2" "indexv2" "$(E2E_REGISTRY_NAMESPACE)" "$(REGISTRY_ROOT)/busybox-dependencies-index:2.0.0-with-ListBundles-method-${OPERATOR_REGISTRY_VERSION}" + ./scripts/publish_e2e_catalog.sh "test/images/busybox-index-v2" "test-catalog" "$(E2E_REGISTRY_NAMESPACE)" "$(REGISTRY_ROOT)/test-catalog:e2e" .PHONY: deploy OLM_IMAGE := quay.io/operator-framework/olm:local diff --git a/pkg/lib/image/image.go b/pkg/lib/image/image.go index 5920fa4fba..aa03e31c14 100644 --- a/pkg/lib/image/image.go +++ b/pkg/lib/image/image.go @@ -13,12 +13,5 @@ func InferImagePullPolicy(image string) corev1.PullPolicy { if strings.Contains(image, "@") { return corev1.PullIfNotPresent } - - // Ensure test registry images are pulled only if needed - // These will normally be loaded through kind load docker-image - // This is also helps support the e2e fixture image re-build flow (see e2e GHA) - if strings.HasPrefix(image, "quay.io/olmtest/test-catalog") { - return corev1.PullIfNotPresent - } return corev1.PullAlways } diff --git a/scripts/e2e_test_fixtures.sh b/scripts/e2e_test_fixtures.sh index caf4a11b1f..0a405da401 100755 --- a/scripts/e2e_test_fixtures.sh +++ b/scripts/e2e_test_fixtures.sh @@ -6,7 +6,6 @@ source .bingo/variables.env # Default values KIND=${KIND:-kind} KIND_CLUSTER_NAME=${KIND_CLUSTER_NAME:-kind-olmv0} -OPM_VERSION=$(go list -m github.com/operator-framework/operator-registry | cut -d" " -f2 | sed 's/^v//') PUSH=false SAVE=false CONTAINER_RUNTIME=docker @@ -133,16 +132,6 @@ if [ "$BUILD" = "true" ]; then ${CONTAINER_RUNTIME} tag "${INDEX_V2}" "${TEST_CATALOG_IMAGE}" fi -# Assumes images are already built, kind cluster is running, and kubeconfig is set -if [ "$LOAD_KIND" = true ]; then - ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${BUNDLE_V1_IMAGE}" - ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${BUNDLE_V1_DEP_IMAGE}" - ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${BUNDLE_V2_IMAGE}" - ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${BUNDLE_V2_DEP_IMAGE}" - ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${INDEX_V1}" - ${KIND} load docker-image --name="${KIND_CLUSTER_NAME}" "${INDEX_V2}" -fi - # Assumes images are already built if [ "${SAVE}" = true ]; then ${CONTAINER_RUNTIME} save "${BUNDLE_V1_IMAGE}" | gzip > bundlev1.tar.gz @@ -154,16 +143,3 @@ if [ "${SAVE}" = true ]; then ${CONTAINER_RUNTIME} save "${INDEX_V1}" | gzip > indexv1.tar.gz ${CONTAINER_RUNTIME} save "${INDEX_V2}" | gzip > indexv2.tar.gz fi - -# Assumes images are already built -if [ "$PUSH" = true ]; then - # push bundles - ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" - ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" - ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" - ${CONTAINER_RUNTIME} push "${BUNDLE_V1_IMAGE}" - - # push indexes - ${CONTAINER_RUNTIME} push "${INDEX_V1}" - ${CONTAINER_RUNTIME} push "${INDEX_V2}" -fi diff --git a/scripts/publish_e2e_catalog.sh b/scripts/publish_e2e_catalog.sh index ba95c72ef4..a42940201c 100755 --- a/scripts/publish_e2e_catalog.sh +++ b/scripts/publish_e2e_catalog.sh @@ -1,44 +1,30 @@ #! /bin/bash +set -x set -o errexit set -o nounset set -o pipefail -help=" -build-push-e2e-catalog.sh is a script to build and push the e2e catalog image using kaniko. -Usage: - build-push-e2e-catalog.sh [NAMESPACE] [TAG] - -Argument Descriptions: - - NAMESPACE is the namespace the kaniko Job should be created in - - TAG is the full tag used to build and push the catalog image -" - -if [[ "$#" -ne 2 ]]; then - echo "Illegal number of arguments passed" - echo "${help}" - exit 1 -fi - -namespace=$1 -tag=$2 +src=$1 +name=$2 +namespace=$3 +dest=$4 OPM_VERSION=${OPM_VERSION:-"latest"} -echo "${namespace}" "${tag}" - # Delete existing configmaps -kubectl delete configmap -n "${namespace}" test-catalog.dockerfile --ignore-not-found -kubectl delete configmap -n "${namespace}" test-catalog.build-contents --ignore-not-found +kubectl delete configmap -n "${namespace}" "${name}.dockerfile" --ignore-not-found +kubectl delete configmap -n "${namespace}" "${name}.build-contents" --ignore-not-found -kubectl create configmap -n "${namespace}" --from-file=test/images/test-catalog/dockerfile test-catalog.dockerfile -kubectl create configmap -n "${namespace}" --from-file=test/images/test-catalog/configs test-catalog.build-contents +kubectl create configmap -n "${namespace}" --from-file="${src}/dockerfile" "${name}.dockerfile" +kubectl create configmap -n "${namespace}" --from-file="${src}/configs" "${name}.build-contents" +# Create the kaniko job kubectl apply -f - << EOF apiVersion: batch/v1 kind: Job metadata: - name: kaniko + name: "kaniko-${name}" namespace: "${namespace}" spec: template: @@ -49,7 +35,7 @@ spec: args: [ "--build-arg=OPM_VERSION=${OPM_VERSION}", "--dockerfile=/workspace/dockerfile", "--context=/workspace", - "--destination=${tag}", + "--destination=${dest}", "--verbosity=trace", "--skip-tls-verify"] volumeMounts: @@ -61,13 +47,13 @@ spec: volumes: - name: dockerfile configMap: - name: test-catalog.dockerfile + name: "${name}.dockerfile" items: - key: dockerfile path: dockerfile - name: build-contents configMap: - name: test-catalog.build-contents + name: "${name}.build-contents" EOF -kubectl wait --for=condition=Complete -n "${namespace}" jobs/kaniko --timeout=60s \ No newline at end of file +kubectl wait --for=condition=Complete -n "${namespace}" "jobs/kaniko-${name}" --timeout=60s \ No newline at end of file diff --git a/test/e2e/catalog_e2e_test.go b/test/e2e/catalog_e2e_test.go index 4eee96bef0..49e8eb603e 100644 --- a/test/e2e/catalog_e2e_test.go +++ b/test/e2e/catalog_e2e_test.go @@ -1062,7 +1062,7 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { packageName := "busybox" channelName := "alpha" - catSrcImage := "quay.io/olmtest/busybox-dependencies-index" + catSrcImage := "docker-registry.olm-e2e.svc:5000/busybox-dependencies-index" By("creating gRPC CatalogSource") source := &v1alpha1.CatalogSource{ diff --git a/test/images/busybox-index/busybox-dependency/1.0.0/dockerfile b/test/images/busybox-index-bundles/busybox-dependency/1.0.0/dockerfile similarity index 100% rename from test/images/busybox-index/busybox-dependency/1.0.0/dockerfile rename to test/images/busybox-index-bundles/busybox-dependency/1.0.0/dockerfile diff --git a/test/images/busybox-index/busybox-dependency/1.0.0/manifests/csv.yaml b/test/images/busybox-index-bundles/busybox-dependency/1.0.0/manifests/csv.yaml similarity index 100% rename from test/images/busybox-index/busybox-dependency/1.0.0/manifests/csv.yaml rename to test/images/busybox-index-bundles/busybox-dependency/1.0.0/manifests/csv.yaml diff --git a/test/images/busybox-index/busybox-dependency/1.0.0/manifests/foo.crd.yaml b/test/images/busybox-index-bundles/busybox-dependency/1.0.0/manifests/foo.crd.yaml similarity index 100% rename from test/images/busybox-index/busybox-dependency/1.0.0/manifests/foo.crd.yaml rename to test/images/busybox-index-bundles/busybox-dependency/1.0.0/manifests/foo.crd.yaml diff --git a/test/images/busybox-index/busybox-dependency/1.0.0/metadata/annotations.yaml b/test/images/busybox-index-bundles/busybox-dependency/1.0.0/metadata/annotations.yaml similarity index 100% rename from test/images/busybox-index/busybox-dependency/1.0.0/metadata/annotations.yaml rename to test/images/busybox-index-bundles/busybox-dependency/1.0.0/metadata/annotations.yaml diff --git a/test/images/busybox-index/busybox-dependency/2.0.0/dockerfile b/test/images/busybox-index-bundles/busybox-dependency/2.0.0/dockerfile similarity index 100% rename from test/images/busybox-index/busybox-dependency/2.0.0/dockerfile rename to test/images/busybox-index-bundles/busybox-dependency/2.0.0/dockerfile diff --git a/test/images/busybox-index/busybox-dependency/2.0.0/manifests/csv.yaml b/test/images/busybox-index-bundles/busybox-dependency/2.0.0/manifests/csv.yaml similarity index 100% rename from test/images/busybox-index/busybox-dependency/2.0.0/manifests/csv.yaml rename to test/images/busybox-index-bundles/busybox-dependency/2.0.0/manifests/csv.yaml diff --git a/test/images/busybox-index/busybox-dependency/2.0.0/manifests/foo.crd.yaml b/test/images/busybox-index-bundles/busybox-dependency/2.0.0/manifests/foo.crd.yaml similarity index 100% rename from test/images/busybox-index/busybox-dependency/2.0.0/manifests/foo.crd.yaml rename to test/images/busybox-index-bundles/busybox-dependency/2.0.0/manifests/foo.crd.yaml diff --git a/test/images/busybox-index/busybox-dependency/2.0.0/metadata/annotations.yaml b/test/images/busybox-index-bundles/busybox-dependency/2.0.0/metadata/annotations.yaml similarity index 100% rename from test/images/busybox-index/busybox-dependency/2.0.0/metadata/annotations.yaml rename to test/images/busybox-index-bundles/busybox-dependency/2.0.0/metadata/annotations.yaml diff --git a/test/images/busybox-index/busybox/1.0.0/dockerfile b/test/images/busybox-index-bundles/busybox/1.0.0/dockerfile similarity index 100% rename from test/images/busybox-index/busybox/1.0.0/dockerfile rename to test/images/busybox-index-bundles/busybox/1.0.0/dockerfile diff --git a/test/images/busybox-index/busybox/1.0.0/manifests/csv.yaml b/test/images/busybox-index-bundles/busybox/1.0.0/manifests/csv.yaml similarity index 100% rename from test/images/busybox-index/busybox/1.0.0/manifests/csv.yaml rename to test/images/busybox-index-bundles/busybox/1.0.0/manifests/csv.yaml diff --git a/test/images/busybox-index/busybox/1.0.0/metadata/annotations.yaml b/test/images/busybox-index-bundles/busybox/1.0.0/metadata/annotations.yaml similarity index 100% rename from test/images/busybox-index/busybox/1.0.0/metadata/annotations.yaml rename to test/images/busybox-index-bundles/busybox/1.0.0/metadata/annotations.yaml diff --git a/test/images/busybox-index/busybox/2.0.0/dockerfile b/test/images/busybox-index-bundles/busybox/2.0.0/dockerfile similarity index 100% rename from test/images/busybox-index/busybox/2.0.0/dockerfile rename to test/images/busybox-index-bundles/busybox/2.0.0/dockerfile diff --git a/test/images/busybox-index/busybox/2.0.0/manifests/csv.yaml b/test/images/busybox-index-bundles/busybox/2.0.0/manifests/csv.yaml similarity index 100% rename from test/images/busybox-index/busybox/2.0.0/manifests/csv.yaml rename to test/images/busybox-index-bundles/busybox/2.0.0/manifests/csv.yaml diff --git a/test/images/busybox-index/busybox/2.0.0/metadata/annotations.yaml b/test/images/busybox-index-bundles/busybox/2.0.0/metadata/annotations.yaml similarity index 100% rename from test/images/busybox-index/busybox/2.0.0/metadata/annotations.yaml rename to test/images/busybox-index-bundles/busybox/2.0.0/metadata/annotations.yaml diff --git a/test/images/test-catalog/configs/.indexignore b/test/images/busybox-index-v1/configs/.indexignore similarity index 100% rename from test/images/test-catalog/configs/.indexignore rename to test/images/busybox-index-v1/configs/.indexignore diff --git a/test/images/busybox-index/indexv1/busybox-dependency/catalog.json b/test/images/busybox-index-v1/configs/catalog.json similarity index 51% rename from test/images/busybox-index/indexv1/busybox-dependency/catalog.json rename to test/images/busybox-index-v1/configs/catalog.json index 0ca557b5ec..4915a26952 100644 --- a/test/images/busybox-index/indexv1/busybox-dependency/catalog.json +++ b/test/images/busybox-index-v1/configs/catalog.json @@ -1,3 +1,92 @@ +{ + "schema": "olm.package", + "name": "busybox", + "defaultChannel": "alpha" +} +{ + "schema": "olm.channel", + "name": "alpha", + "package": "busybox", + "entries": [ + { + "name": "busybox.v1.0.0" + } + ] +} +{ + "schema": "olm.bundle", + "name": "busybox.v1.0.0", + "package": "busybox", + "image": "quay.io/olmtest/busybox-bundle:1.0.0", + "properties": [ + { + "type": "olm.gvk.required", + "value": { + "group": "olm.test.io", + "kind": "Foo", + "version": "v1" + } + }, + { + "type": "olm.package", + "value": { + "packageName": "busybox", + "version": "1.0.0" + } + }, + { + "type": "olm.csv.metadata", + "value": { + "apiServiceDefinitions": {}, + "crdDescriptions": { + "required": [ + { + "name": "foos.olm.test.io", + "version": "v1", + "kind": "Foo", + "displayName": "Foo", + "description": "Foo resources for testing dependencies" + } + ] + }, + "description": "A busybox CSV.\n", + "displayName": "busybox", + "installModes": [ + { + "type": "OwnNamespace", + "supported": true + }, + { + "type": "SingleNamespace", + "supported": true + }, + { + "type": "MultiNamespace", + "supported": true + }, + { + "type": "AllNamespaces", + "supported": true + } + ], + "maturity": "alpha", + "provider": { + "name": "Red Hat" + } + } + } + ], + "relatedImages": [ + { + "name": "", + "image": "busybox" + }, + { + "name": "", + "image": "quay.io/olmtest/busybox-bundle:1.0.0" + } + ] +} { "schema": "olm.package", "name": "busybox-dependency", diff --git a/test/images/test-catalog/dockerfile b/test/images/busybox-index-v1/dockerfile similarity index 96% rename from test/images/test-catalog/dockerfile rename to test/images/busybox-index-v1/dockerfile index 8eea9fa74c..08c6e009d2 100644 --- a/test/images/test-catalog/dockerfile +++ b/test/images/busybox-index-v1/dockerfile @@ -8,7 +8,7 @@ FROM quay.io/operator-framework/opm:${OPM_VERSION} LABEL operators.operatorframework.io.index.configs.v1=/configs # Copy declarative config root into image at /configs and pre-populate serve cache -COPY configs /configs +COPY /configs /configs RUN ["/bin/opm", "serve", "/configs", "--cache-dir=/tmp/cache", "--cache-only"] # Configure the entrypoint and command diff --git a/test/images/busybox-index-v2/configs/.indexignore b/test/images/busybox-index-v2/configs/.indexignore new file mode 100644 index 0000000000..620c429a51 --- /dev/null +++ b/test/images/busybox-index-v2/configs/.indexignore @@ -0,0 +1,2 @@ +/expected_all.json +..* \ No newline at end of file diff --git a/test/images/test-catalog/configs/catalog.json b/test/images/busybox-index-v2/configs/catalog.json similarity index 99% rename from test/images/test-catalog/configs/catalog.json rename to test/images/busybox-index-v2/configs/catalog.json index 4fa297577e..35331655e9 100644 --- a/test/images/test-catalog/configs/catalog.json +++ b/test/images/busybox-index-v2/configs/catalog.json @@ -184,4 +184,3 @@ } ] } - diff --git a/test/images/busybox-index/dockerfile b/test/images/busybox-index-v2/dockerfile similarity index 91% rename from test/images/busybox-index/dockerfile rename to test/images/busybox-index-v2/dockerfile index d7c77a96e9..08c6e009d2 100644 --- a/test/images/busybox-index/dockerfile +++ b/test/images/busybox-index-v2/dockerfile @@ -8,8 +8,7 @@ FROM quay.io/operator-framework/opm:${OPM_VERSION} LABEL operators.operatorframework.io.index.configs.v1=/configs # Copy declarative config root into image at /configs and pre-populate serve cache -ARG CONFIGS_DIR=/configs -COPY ${CONFIGS_DIR} /configs +COPY /configs /configs RUN ["/bin/opm", "serve", "/configs", "--cache-dir=/tmp/cache", "--cache-only"] # Configure the entrypoint and command diff --git a/test/images/busybox-index/indexv1/busybox/catalog.json b/test/images/busybox-index/indexv1/busybox/catalog.json deleted file mode 100644 index b373409115..0000000000 --- a/test/images/busybox-index/indexv1/busybox/catalog.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "schema": "olm.package", - "name": "busybox", - "defaultChannel": "alpha" -} -{ - "schema": "olm.channel", - "name": "alpha", - "package": "busybox", - "entries": [ - { - "name": "busybox.v1.0.0" - } - ] -} -{ - "schema": "olm.bundle", - "name": "busybox.v1.0.0", - "package": "busybox", - "image": "quay.io/olmtest/busybox-bundle:1.0.0", - "properties": [ - { - "type": "olm.gvk.required", - "value": { - "group": "olm.test.io", - "kind": "Foo", - "version": "v1" - } - }, - { - "type": "olm.package", - "value": { - "packageName": "busybox", - "version": "1.0.0" - } - }, - { - "type": "olm.csv.metadata", - "value": { - "apiServiceDefinitions": {}, - "crdDescriptions": { - "required": [ - { - "name": "foos.olm.test.io", - "version": "v1", - "kind": "Foo", - "displayName": "Foo", - "description": "Foo resources for testing dependencies" - } - ] - }, - "description": "A busybox CSV.\n", - "displayName": "busybox", - "installModes": [ - { - "type": "OwnNamespace", - "supported": true - }, - { - "type": "SingleNamespace", - "supported": true - }, - { - "type": "MultiNamespace", - "supported": true - }, - { - "type": "AllNamespaces", - "supported": true - } - ], - "maturity": "alpha", - "provider": { - "name": "Red Hat" - } - } - } - ], - "relatedImages": [ - { - "name": "", - "image": "busybox" - }, - { - "name": "", - "image": "quay.io/olmtest/busybox-bundle:1.0.0" - } - ] -} diff --git a/test/images/busybox-index/indexv2/busybox-dependency/catalog.json b/test/images/busybox-index/indexv2/busybox-dependency/catalog.json deleted file mode 100644 index f42e9fa257..0000000000 --- a/test/images/busybox-index/indexv2/busybox-dependency/catalog.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "schema": "olm.package", - "name": "busybox-dependency", - "defaultChannel": "alpha" -} -{ - "schema": "olm.channel", - "name": "alpha", - "package": "busybox-dependency", - "entries": [ - { - "name": "busybox-dependency.v2.0.0", - "skipRange": ">=0.0.0 <2.0.0" - } - ] -} -{ - "schema": "olm.bundle", - "name": "busybox-dependency.v2.0.0", - "package": "busybox-dependency", - "image": "quay.io/olmtest/busybox-dependency-bundle:2.0.0", - "properties": [ - { - "type": "olm.gvk", - "value": { - "group": "olm.test.io", - "kind": "Foo", - "version": "v1" - } - }, - { - "type": "olm.package", - "value": { - "packageName": "busybox-dependency", - "version": "2.0.0" - } - }, - { - "type": "olm.csv.metadata", - "value": { - "annotations": { - "olm.skipRange": ">=0.0.0 <2.0.0" - }, - "apiServiceDefinitions": {}, - "crdDescriptions": { - "owned": [ - { - "name": "foos.olm.test.io", - "version": "v1", - "kind": "Foo", - "displayName": "Foo", - "description": "Foo resources for testing dependencies" - } - ] - }, - "description": "A busybox-dependency CSV.\n", - "displayName": "busybox-dependency", - "installModes": [ - { - "type": "OwnNamespace", - "supported": true - }, - { - "type": "SingleNamespace", - "supported": true - }, - { - "type": "MultiNamespace", - "supported": true - }, - { - "type": "AllNamespaces", - "supported": true - } - ], - "maturity": "alpha", - "provider": { - "name": "Red Hat" - } - } - } - ], - "relatedImages": [ - { - "name": "", - "image": "busybox" - }, - { - "name": "", - "image": "quay.io/olmtest/busybox-dependency-bundle:2.0.0" - } - ] -} diff --git a/test/images/busybox-index/indexv2/busybox/catalog.json b/test/images/busybox-index/indexv2/busybox/catalog.json deleted file mode 100644 index 72e9999546..0000000000 --- a/test/images/busybox-index/indexv2/busybox/catalog.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "schema": "olm.package", - "name": "busybox", - "defaultChannel": "alpha" -} -{ - "schema": "olm.channel", - "name": "alpha", - "package": "busybox", - "entries": [ - { - "name": "busybox.v2.0.0", - "skipRange": ">=0.0.0 <2.0.0" - } - ] -} -{ - "schema": "olm.bundle", - "name": "busybox.v2.0.0", - "package": "busybox", - "image": "quay.io/olmtest/busybox-bundle:2.0.0", - "properties": [ - { - "type": "olm.gvk.required", - "value": { - "group": "olm.test.io", - "kind": "Foo", - "version": "v1" - } - }, - { - "type": "olm.package", - "value": { - "packageName": "busybox", - "version": "2.0.0" - } - }, - { - "type": "olm.csv.metadata", - "value": { - "annotations": { - "olm.skipRange": ">=0.0.0 <2.0.0" - }, - "apiServiceDefinitions": {}, - "crdDescriptions": { - "required": [ - { - "name": "foos.olm.test.io", - "version": "v1", - "kind": "Foo", - "displayName": "Foo", - "description": "Foo resources for testing dependencies" - } - ] - }, - "description": "A busybox CSV.\n", - "displayName": "busybox", - "installModes": [ - { - "type": "OwnNamespace", - "supported": true - }, - { - "type": "SingleNamespace", - "supported": true - }, - { - "type": "MultiNamespace", - "supported": true - }, - { - "type": "AllNamespaces", - "supported": true - } - ], - "maturity": "alpha", - "provider": { - "name": "Red Hat" - } - } - } - ], - "relatedImages": [ - { - "name": "", - "image": "busybox" - }, - { - "name": "", - "image": "quay.io/olmtest/busybox-bundle:2.0.0" - } - ] -}