CLI tool for manipulating Ceph's upmap exception table.

Related tags

pgremapper
Overview

pgremapper

Build License Go Report Card Apache License

When working with Ceph clusters, there are actions that cause backfill (CRUSH map changes) and cases where you want to cause backfill (moving data between OSDs or hosts). Trying to manage backfill via CRUSH is difficult because changes to the CRUSH map cause many ancillary data movements that can be wasteful.

Additionally, controlling the amount of in-progress backfill is difficult, and having PGs in backfill_wait state has consequences:

  • Any PG performing recovery or backfill must obtain local and remote reservations.
  • A PG in a wait state may hold some of its necessary reservations, but not all. This may, in turn, block other recoveries or backfills that could otherwise make independent progress.
  • For EC pools, the source of a backfill read is likely not the primary, and this is not considered as a part of the reservation scheme. A single OSD could have any number of backfills reading from it; no knobs outside of recovery sleep can be used to mitigate this. Pacific's mclock scheduler should theoretically improve this situation.
  • There are no reservation slots held for recoveries, meaning that a recovery could be waiting behind another backfill (or several backfills if they stack in a wait state).

The primary control knob for backfills, osd-max-backfills, sets the number of local and remote reservations available on a given OSD. Given the above, this knob is not sufficient given the way that backfill can pile up in the face of a large-scale change; one sometimes has to set it unacceptably high to achieve backfill concurrency across many OSDs.

This tool, pgremapper, is intended to aid with all of the above usecases and problems. It operates by manipulating the pg-upmap exception table available in Luminous+ to override CRUSH decisions based on a number of algorithms exposed as commands, outlined below. Many of these commands are intended to be run in a loop in order to achieve some target state.

Acknowledgments

The initial version of this tool, which became the cancel-backfill command below, was heavily inspired by techniques developed by CERN IT.

Requirements

As mentioned above, the upmap exception table was introduced in Luminous, and this is a hard requirement for pgremapper. However, there were significant improvements to the upmap code throughout the Luminous series. When working with upmaps, it's recommended that you are running Luminous v12.2.13 (the last release), Mimic v13.2.7+, Nautilus v14.2.5+, or newer, at least on the mons/mgrs.

We've used pgremapper on a variety of versions of Luminous and Nautilus.

Caveats

  • When running older versions of Luminous or Mimic, it's possible for stale upmap entries that have no effect to accumulate. pgremapper can become confused by these stale entries and fail. See the Requirements section above for recommended versions.
  • If the system is still processing osdmaps and peering, pgremapper can become confused and fail for pretty much the same reason as above (upmap entries at the mon layer may not yet be reflected in current PG state).
  • Given a recent enough Ceph version, CRUSH cannot be violated by an upmap entry. This is good, but it can make certain manipulations impossible; consider a case where a backfill is swapping EC chunks between two racks. To the best of our knowledge today, no upmap entry can be created to counteract such a backfill, as Ceph will evaluate the correctness of the upmap entry in parts, rather than as a whole. (If you have evidence to the contrary or this is actually possible in newer versions of Ceph, let us know!)

Bug Reports

If you find a situation where pgremapper isn't working right, please file a report with a clear description of how pgremapper was invoked and any of its output, what the system was doing at the time, and output from the following Ceph commands:

  • ceph osd dump -f json
  • ceph osd tree -f json
  • ceph pg dump pgs_brief -f json
  • If a specific PG is named in pgremapper error output, then ceph pg <pgid> query -f json

Building

If you have a Go environment configured, you can use go get:

go get github.com/digitalocean/pgremapper

Otherwise, clone this repository and use a golang Docker container to build:

docker run -v $(pwd):/pgremapper -w /pgremapper golang:1.16.3 go build -o pgremapper .

Usage

pgremapper makes no changes by default and has some global options:

$ ./pgremapper [--concurrency <n>] [--yes] [--verbose] <command>
  • --concurrency: For commands that can be issued in parallel, this controls the concurrency. This is set at a reasonable default that generally doesn't lead to too much concurrent peering in the cluster when manipulating the pg-upmap table.
  • --yes: Apply changes instead of emitting the diff output that would show which changes would be applied.
  • --verbose: Display Ceph commands being run, for debugging purposes.

osdspec

For commands or options that take a list of OSDs, pgremapper uses the concept of an osdspec (inspired by Git's refspec) to simplify the command line. An osdspec can either be an OSD ID (e.g. 42) or a CRUSH bucket prefixed by bucket: (e.g. bucket:rack1 or bucket:host4). In the latter case, all OSDs found under that CRUSH bucket are included.

balance-bucket

This is essentially a small, targeted version of Ceph's own upmap balancer (though not as sophisticated - it doesn't prioritize undoing existing pg-upmap entries, for example), useful for cases where general enablement of the balancer either isn't possible or is undesirable. The given CRUSH bucket must directly contain OSDs.

$ ./pgremapper balance-bucket <bucket> [--max-backfills <n>] [--target-spread <n>]
  • <bucket>: A CRUSH bucket that directly contains OSDs.
  • --max-backfills: The total number of backfills that should be allowed to be scheduled that affect this CRUSH bucket. This takes pre-existing backfills into account.
  • --target-spread: The goal state in terms of the maximum difference in PG counts across OSDs in this bucket.

Example

Schedule 10 backfills on the host named data11, trying to achieve a maximum PG spread of 3 between the fullest and emptiest OSDs (in terms of PG counts) within that host:

$ ./pgremapper balance-bucket data11 --max-backfills 10 --target-spread 3

cancel-backfill

This command iterates the list of PGs in a backfill state, creating, modifying, or removing upmap exception table entries to point the PGs back to where they are located now (i.e. makes the up set the same as the acting set). This essentially reverts whatever decision led to this backfill (i.e. CRUSH change, OSD reweight, or another upmap entry) and leaves the Ceph cluster with no (or very little) remapped PGs (there are cases where Ceph disallows such remapping due to violation of CRUSH rules).

Notably, pgremapper knows how to reconstruct the acting set for a degraded backfill (provided that complete copies exist for all indexes of that acting set), which can allow one to convert a degraded+backfill{ing,_wait} into degraded+recover{y,_wait}, at the cost of losing whatever backfill progress has been made so far.

$ ./pgremapper cancel-backfill [--exclude-backfilling] [--include-osds <osdspec>,...] [--exclude-osds <osdspec>,...] [--pgs-including <osdspec>,...]
  • --exclude-backfilling: Constrain cancellation to PGs that are in a backfill_wait state, ignoring those in a backfilling state.
  • --include-osds: Cancel backfills containing one of the given OSDs as a backfill source or target only.
  • --exclude-osds: The inverse of --include-osds - cancel backfills that do not contain one of the given OSDs as a backfill source or target.
  • --pgs-including: Cancel backfills for PGs that include the given OSDs in their up or acting set, whether or not the given OSDs are backfill sources or targets in those PGs.

Example - Cancel all backfill in the system as a part of an augment

This is useful during augment scenarios, if you want to control PG movement to the new nodes via the upmap balancer (a technique based on this CERN talk.

# Make sure no data movement occurs when manipulating the CRUSH map.
$ ceph osd set nobackfill
$ ceph osd set norebalance

<perform augment CRUSH changes>

$ ./pgremapper cancel-backfill --yes

$ ceph osd unset norebalance
$ ceph osd unset nobackfill

<enable the upmap balancer to begin gentle data movements>

Example - Cancel backfill that has a CRUSH bucket as a source or target, but not backfill including specified OSDs

You may want to reduce backfill load on a given host so that only a few OSDs on that host make progress. This will cancel backfill where host data04 is a source or target, but not if OSD 21 or 34 is the source or target.

$ ./pgremapper cancel-backfill --include-osds bucket:data04 --exclude-osds 21,34

Example - Cancel backfill for any PGs that include a given host

Due to a failure, we know that data10 is going to need a bunch of recovery, so let's make sure that the recovery can happen without any backfills entering a degraded state:

$ ./pgremapper cancel-backfill --pgs-including bucket:data10

drain

Remap PGs off of the given source OSD, up to the given maximum number of scheduled backfills. No attempt is made to balance the fullness of the target OSDs; rather, the least busy target OSDs and PGs will be selected.

$ ./pgremapper drain <source OSD> --target-osds <osdspec>[,<osdspec>] [--allow-movement-across <bucket type>] [--max-backfill-reservations default_max[,osdspec:max]] [--max-source-backfills <n>]
  • <source OSD>: The OSD that will become the backfill source.
  • --target-osds: The OSD(s) that will become the backfill target(s).
  • --allow-movement-across: Constrain which type of data movements will be considered if target OSDs are given outside of the CRUSH bucket that contains the source OSD. For example, if your OSDs all live in a CRUSH bucket of type host, passing host here will allow remappings across hosts as long as the source and target host live within the same CRUSH bucket themselves. Target CRUSH buckets will be not be considered for a given PG if they already contain replicas/chunks of that PG. By default, if this option isn't given, data movements are allowed only within the direct CRUSH bucket containing the source OSD.
  • --max-backfill-reservations: Consume only the given reservation maximums for backfill. You'll commonly want to set this below your osd-max-backfills setting so that any scheduled recoveries may clear without waiting for a backfill to complete. A default value is specified first, and then per-osdspec values for cases where you want to allow more backfill or have non-uniform osd-max-backfills settings.
  • --max-source-backfills: Allow the source OSD to have this maximum number of backfills scheduled. TODO: This option works for EC systems, where the given OSD truly will be the backfill source; in replicated systems, the primary OSD is the source and thus source concurrency must be controlled via --max-backfill-reservations.

Example - Offload some PGs from one OSD to another

Schedule backfills to move 5 PGs from OSD 4 to OSD 21:

$ ./pgremapper drain 4 --target-osds 21 --max-source-backfills 5

Example - Move PGs off-host

Schedule backfills to move 8 PGs from OSD 15 to any combination of OSDs on host data12, ensuring we don't exceed 2 backfill reservations anywhere:

$ ./pgremapper drain 15 --target-osds bucket:data12 --allow-movement-across host --max-backfill-reservations 2 --max-source-backfills 8

export-mappings

Export all upmaps for the given OSD spec(s) in a json format usable by import-mappings. Useful for keeping the state of existing mappings to restore after destroying a number of OSDs, or any other CRUSH change that will cause upmap items to be cleaned up by the mons.

Note that the mappings exported will be just the portions of the upmap items pertaining to the selected OSDs (i.e. if a given OSD is the From or To of the mapping).

$ ./pgremapper export-mappings <osdspec> ... [--output <file>]
  • <osdspec> ...: The OSDs for which mappings will be exported.
  • --output: Write output to the given file path instead of stdout.

import-mappings

Import all upmaps from the given JSON input (probably from export-mappings) to the cluster. Input is stdin unless a file path is provided.

JSON format example, remapping PG 1.1 from OSD 100 to OSD 42:

[
  {
    "pgid": "1.1",
    "mapping": {
      "from": 100,
      "to": 42,
    }
  }
]
$ ./pgremapper import-mappings [<file>]
  • <file>: Read from the given file path instead of stdin.

remap

Modify the upmap exception table with the requested mapping. Like other subcommands, this takes into account any existing mappings for this PG, and is thus safer and more convenient to use than 'ceph osd pg-upmap-items' directly.

$ ./pgremapper remap <pg ID> <source osd ID> <target osd ID>

undo-upmaps

Given a list of OSDs, remove (or modify) upmap items such that the OSDs become the source (or target if --target is specified) of backfill operations (i.e. they are currently the "To" ("From") of the upmap items) up to the backfill limits specified. Backfill is spread across target and primary OSDs in a best-effort manner.

This is useful for cases where the upmap rebalancer won't do this for us, e.g., performing a swap-bucket where we want the source OSDs to totally drain (vs. balance with the rest of the cluster). It also achieves a much higher level of concurrency than the balancer generally will.

$ ./pgremapper undo-upmaps <osdspec>[,<osdspec>] [--max-backfill-reservations default_max[,osdspec:max]] [--max-source-backfills <n>] [--target]
  • --max-backfill-reservations: Consume only the given reservation maximums for backfill. You'll commonly want to set this below your osd-max-backfills setting so that any scheduled recoveries may clear without waiting for a backfill to complete. A default value is specified first, and then per-osdspec values for cases where you want to allow more backfill or have non-uniform osd-max-backfills settings.
  • --max-source-backfills: Allow a given source OSD to have this maximum number of backfills scheduled. TODO: This option works for EC systems, where the given OSD truly will be the backfill source; in replicated systems, the primary OSD is the source and thus source concurrency must be controlled via --max-backfill-reservations.
  • --target: The given list of OSDs should serve as backfill targets, rather than the default of backfill sources.

Example - Move PGs back after an OSD recreate

A common usecase is reformatting an OSD - we want to move all data off of that OSD to another, recreate the first OSD in the new format, and then move the data back. There was an example above of using drain to move data from OSD 4 to OSD 21; now let's start moving it back:

$ ./pgremapper undo-upmaps 21 --max-source-backfills 5

Or:

$ ./pgremapper undo-upmaps 4 --target --max-source-backfills 5

(Note that drain could be used for this as well, since it will happily remove upmap entries as needed.)

Example - Move PGs off of a host after a swap-bucket

Let's say you swapped data01 and data04, where data04 is an empty replacement for data01. You use cancel-backfill to revert the swap, and then can start scheduling backfill in controlled batches - 2 per source OSD, not exceeding 2 backfill reservations except for data04 where 3 backfill reservations are allowed (more target concurrency):

$ ./pgremapper undo-upmaps bucket:data01 --max-backfill-reservations 2,bucket:data04:3 --max-source-backfills 2

Development

Testing

Because pgremapper is stateless and should largely make the same decisions each run (modulo some randomization that occurs in remapping commands to ensure a level of fairness), the majority of testing can be done in unit tests that simulate Ceph responses. If you're trying to accomplish something specific while a cluster is in a certain state, the best option is to put a Ceph cluster in that state and capture relevant output from it for unit tests.

Issues
  • panic: pg 1.38f: conflicting mapping(s) found when trying to map from 66 to 19

    panic: pg 1.38f: conflicting mapping(s) found when trying to map from 66 to 19

    When try to verify #4 I found a panic for pgremapper :D

    # ./pgremapper cancel-backfill --verbose
    ** executing: ceph osd dump -f json
    ** executing: ceph pg dump pgs_brief -f json
    ** executing: ceph pg dump pgs_brief -f json
    panic: pg 1.38f: conflicting mapping(s) found when trying to map from 66 to 19
    
    goroutine 86 [running]:
    main.(*mappingState).remap(0xc000012030, 0xc0004ac354, 0x5, 0x42, 0x13)
            /pgremapper/mappingstate.go:76 +0x7a5
    main.calcPgMappingsToUndoBackfill.func3(0xc00010e0c0, 0x5abe00, 0xc00011acc0, 0xc0000b4010, 0xc0000b4020, 0xc0000db5f4)
            /pgremapper/main.go:690 +0x373
    created by main.calcPgMappingsToUndoBackfill
            /pgremapper/main.go:633 +0x185
    

    All outputs are attached Archive.zip

    opened by k0ste 5
  • drain for source osdspec idea

    drain for source osdspec idea

    What we have:

    • full upmap balanced cluster
    • need to redeploy OSD host (full host): out -> purge -> deploy -> fill
    • pgremapper drain can drain only OSD's, not osdspec

    Can we achieve this currently:

    • ceph osd crush reweight-subtree 0
    • for e 'in ceph osd df tree name host1.example.com | grep osd\. | awk '{ print $1}'' ; do ceph osd out osd.${e} ; done
    • balance:
    ceph osd getmap -o osd.map
    osdmaptool osd.map \
      --upmap-deviation 1 \
      --upmap-max 10000 \
      --upmap upmap.sh | sh
    

    How we look the flow - one commad

    pgremapper drain bucket:host1.example.com
    

    This issued (may be not all steps, can be scripted):

    • ceph osd crush reweight-subtree 0
    • ceph osd out for this subtree
    • make upmaps to another buckets to respect crush rule

    What do you think?

    opened by k0ste 4
  • proposal: report mode on dry-run by default

    proposal: report mode on dry-run by default

    Hi,

    ceph-volume lvm batch command, when --yes is not defined will output brief --repot mode by default. This is very useful on scripting, for example:

    #!/bin/bash
    
    CHECK=$1
    
    if [[ ${CHECK} != "--yes" ]]
      then
        echo -e "\n'--yes' is not provided, running in report mode\n"
        MODE="--report"
      else
        MODE="${CHECK}"
    fi
    
    ceph-volume lvm batch --no-auto --crush-device-class=nvme_ms ${MODE} \
      /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1 /dev/nvme3n1 /dev/nvme4n1 \
      /dev/nvme5n1 /dev/nvme6n1 /dev/nvme7n1 /dev/nvme8n1 /dev/nvme9n1 \
      /dev/nvme10n1 /dev/nvme11n1 /dev/nvme12n1 /dev/nvme13n1 /dev/nvme14n1 \
      /dev/nvme15n1 /dev/nvme16n1 /dev/nvme17n1 /dev/nvme18n1 /dev/nvme19n1 \
      /dev/nvme20n1 /dev/nvme21n1 /dev/nvme22n1 /dev/nvme23n1
    

    When Ceph operator want a report - it's just run the script, if brief_check_dry-run_report mode is okay, just add --yes to script will deploy OSD host

    I think it will be useful for pgremapper too, instead y/n dialog without --yes

    Thanks

    opened by k0ste 2
  • Update README.md

    Update README.md

    Single spelling correction.

    opened by anthonyeleven 1
  • pgremapper: Consider upmaps when reordering up sets.

    pgremapper: Consider upmaps when reordering up sets.

    Consider the following upmap entry:

            {
                "pgid": "1.38f",
                "mappings": [
                    {
                        "from": 51,
                        "to": 3
                    },
                    {
                        "from": 19,
                        "to": 11
                    }
                ]
            },
    

    And the following PG state:

            {
                "pgid": "1.38f",
                "state": "active+remapped+backfill_wait",
                "up": [
                    3,
                    66,
                    11
                ],
                "acting": [
                    3,
                    19,
                    39
                ],
                "up_primary": 3,
                "acting_primary": 3
            },
    

    Prior to this change, pgremapper would attempt to remap 66->19, which would conflict with the existing mapping 19->11. After this change, pgremapper is wise enough to use the upmap item to realize that 19 and 11 are paired and re-order the up set accordingly for proper processing.

    opened by baergj 1
  • min_compat_client warning is not handled by pgremapper

    min_compat_client warning is not handled by pgremapper

    This panic:

    # ./upmap_cancel_backfill.sh --yes
    ** executing: ceph osd dump -f json
    ** executing: ceph pg dump pgs_brief -f json
    ** executing: ceph osd dump -f json
    ** executing: ceph pg dump pgs_brief -f json
    ** executing: ceph osd dump -f json
    ** executing: ceph osd dump -f json
    ** executing: ceph osd pg-upmap-items 3.0 39 7 6 37 66 48
    ** executing: ceph osd pg-upmap-items 3.1 6 88
    ** executing: ceph osd pg-upmap-items 3.101 89 90 123 124
    ** executing: ceph osd pg-upmap-items 3.10 130 84 93 134
    ** executing: ceph osd pg-upmap-items 3.100 35 19 4 49 143 84
    panic: failed to execute command: ceph osd pg-upmap-items 3.1 6 88: exit status 1
    
    goroutine 66 [running]:
    main.runOrDie(0xc0001e2000, 0x6, 0x8, 0x4, 0x6)
            /pgremapper/main.go:993 +0x117
    main.(*pgUpmapItem).do(0xc000458fa0)
            /pgremapper/ceph.go:259 +0x2c5
    main.(*mappingState).apply.func1(0xc000547d40, 0xc000556b50)
            /pgremapper/mappingstate.go:200 +0x3f
    created by main.(*mappingState).apply
            /pgremapper/mappingstate.go:198 +0xaa
    

    Actual issue is:

    # ceph osd pg-upmap-items 3.1 6 88
    Error EPERM: min_compat_client jewel < luminous, which is required for pg-upmap. Try 'ceph osd set-require-min-compat-client luminous' before using the new interface
    

    It will be good if error stderr is handled and printed instead panic

    opened by k0ste 1
  • Eliminate prompt when --yes isn't specified.

    Eliminate prompt when --yes isn't specified.

    Addresses https://github.com/digitalocean/pgremapper/issues/3.

    opened by baergj 0
  • Add --whole-pg option to export-mappings.

    Add --whole-pg option to export-mappings.

    At least on some Ceph versions, recreating an OSD causes upmap items to be dropped for an entire PG that includes that OSD, rather than items pertaining to just that OSD.

    opened by baergj 0
  • ceph: Exclude 'out' OSDs in getOsdsForBucket().

    ceph: Exclude 'out' OSDs in getOsdsForBucket().

    We can't perform any remapping operations on 'out' OSDs; they're never in any 'up' sets and can't be upmapped to or from.

    opened by baergj 0
  • panic: pg 18.48: conflicting mapping(s) found when trying to map from 72 to 527

    panic: pg 18.48: conflicting mapping(s) found when trying to map from 72 to 527

    Hi! What I've done:

    drained osd waited all active+clean did norebalance, nobackfill flags stopped this osd did ceph osd purge for this osd I got remapped pgs When I tried to do a cancell-backfill I got a panic:

    ./pgremapper cancel-backfill --verbose
    '--yes' is not provided, running in report mode
    
    ** executing: ceph osd dump -f json
    ** executing: ceph pg dump pgs_brief -f json
    ** executing: ceph osd dump -f json
    ** executing: ceph pg dump pgs_brief -f json
    ** executing: ceph osd dump -f json
    ** executing: ceph osd dump -f json
    panic: pg 18.48: conflicting mapping(s) found when trying to map from 72 to 527
    
    goroutine 82 [running]:
    main.(*mappingState).remap(0xc0000123f0, 0xc000e5d605, 0x5, 0x48, 0x20f)
    	/pgremapper/mappingstate.go:76 +0x7a5
    main.calcPgMappingsToUndoBackfill.func3(0xc00094a000, 0xc000012300, 0xc0000126c0, 0xc000182cc0, 0xc000948000, 0xc000948010, 0xc001240040)
    	/pgremapper/main.go:703 +0x3d3
    created by main.calcPgMappingsToUndoBackfill
    	/pgremapper/main.go:646 +0x1a5
    

    All dumps are needed in the attachment dump.zip

    opened by timureh 4
Owner
DigitalOcean
DigitalOcean
A versatile library for building CLI applications in Go

mow.cli Package cli provides a framework to build command line applications in Go with most of the burden of arguments parsing and validation placed o

Jawher Moussa 748 Sep 5, 2021
ASCII table in golang

ASCII Table Writer Generate ASCII table on the fly ... Installation is simple as go get github.com/olekukonko/tablewriter Features Automatic Padding

Oleku Konko 3k Sep 22, 2021
Make Highly Customized Boxes for your CLI

Box CLI Maker ?? Box CLI Maker is a Highly Customized Terminal Box Creator. Features Make Terminal Box in 8️⃣ inbuilt different styles 16 Inbuilt Colo

Swastik Baranwal 152 Sep 22, 2021
A command-line tool for Stripe

Stripe CLI The Stripe CLI helps you build, test, and manage your Stripe integration right from the terminal. With the CLI, you can: Securely test webh

Stripe 1.1k Sep 15, 2021
Another CLI framework for Go. It works on my machine.

Command line interface framework Go framework for rapid command line application development

Ulrich Kautz 108 May 24, 2021
GitHub’s official command line tool

GitHub CLI gh is GitHub on the command line. It brings pull requests, issues, and other GitHub concepts to the terminal next to where you are already

GitHub CLI 25.4k Sep 20, 2021
Highly customizable and lightweight Go CLI app framework πŸ‘Œ

Nice ?? Nice is a highly customizable and lightweight framework for crafting CLI apps. Nice respects idiomatic Go code and focuses to be clear, effici

Aleksandr Krivoshchekov 34 Sep 21, 2021
a lightweight and simple cli package

β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–„β–ˆ β–„β–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–€ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–Œ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–Œ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–Œ β–ˆβ–ˆβ–ˆ β–ˆβ–„ β–ˆβ–ˆβ–ˆ

seo.do 12 Aug 17, 2021
πŸ”₯ [WIP] Interactive Jira Command Line

JiraCLI Interactive Jira CLI ?? This project is still a work in progress ?? This tool mostly focuses on issue search and navigation at the moment. How

Ankit Pokhrel 175 Sep 16, 2021
Arduino command line tool

arduino-cli Arduino CLI is an all-in-one solution that provides builder, Boards/Library Manager, uploader, discovery and many other tools needed to us

Arduino 3.1k Sep 22, 2021
A command-line tool and library for generating regular expressions from user-provided test cases

Table of Contents What does this tool do? Do I still need to learn to write regexes then? Current features How to install? 4.1 The command-line tool 4

Peter M. Stahl 4.5k Sep 25, 2021
Handy little CLI for interacting with OCI data

oci-tool Handy little CLI for interacting with OCI data Installation go get github.com/csweichel/oci-tool I use Gitpod for developing this tool; you s

Christian Weichel 7 Sep 9, 2021
cross platform command line tool to list, notify and book vaccine using cowin API

Command line tool to List and Book Vaccine cowin-cli is a simple cli tool to book vaccines and list centers using the COWIN API. It also supports auto

Anoop S 36 Aug 11, 2021
Kong is a command-line parser for Go

Kong is a command-line parser for Go Introduction Help Help as a user of a Kong application Defining help in Kong Command handling Switch on the comma

Alec Thomas 663 Sep 25, 2021
FireFly Command Line Interface (CLI)

FireFly CLI The FireFly CLI can be used to create a local FireFly stacks for offline development of blockchain apps. This allows developers to rapidly

Kaleido 0 Sep 23, 2021
jt is a CLI tool for viewing and manipulating JIRA issues.

jt - jira-tool jt is a CLI tool for viewing and manipulating JIRA issues. One common example usage to transition an issue to a new status: jt "In Prog

Steve Coffman 7 Sep 2, 2021
Query git repositories with SQL. Generate reports, perform status checks, analyze codebases. πŸ” πŸ“Š

askgit is a command-line tool for running SQL queries on git repositories. It's meant for ad-hoc querying of git repositories on disk through a common interface (SQL), as an alternative to patching together various shell commands.

AskGit 2.6k Sep 20, 2021
A simple, fast, and fun package for building command line apps in Go

cli cli is a simple, fast, and fun package for building command line apps in Go. The goal is to enable developers to write fast and distributable comm

null 16.6k Sep 19, 2021
Simple and complete API for building command line applications in Go

Simple and complete API for building command line applications in Go Module cli provides a simple, fast and complete API for building command line app

teris.io 89 Jul 15, 2021