Metadata-Version: 2.4
Name: saltext.jumpcloud
Version: 0.1.0
Summary: Salt Extension for interacting with JumpCloud
Author-email: "Gary T. Giesen" <ggiesen@giesen.me>
License: Mozilla Public License 2.0 (MPL 2.0)
Project-URL: Homepage, https://gitlab.com/ggiesen/saltext-jumpcloud
Project-URL: Documentation, https://ggiesen.gitlab.io/saltext-jumpcloud/
Project-URL: Source, https://gitlab.com/ggiesen/saltext-jumpcloud
Project-URL: Tracker, https://gitlab.com/ggiesen/saltext-jumpcloud/-/issues
Keywords: salt-extension
Platform: any
Classifier: Programming Language :: Python
Classifier: Programming Language :: Cython
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: salt>=3006
Provides-Extra: changelog
Requires-Dist: towncrier==25.8.0; extra == "changelog"
Provides-Extra: dev
Requires-Dist: nox[uv]!=2025.05.01,>=2024.3; extra == "dev"
Requires-Dist: pre-commit>=2.21.0; extra == "dev"
Provides-Extra: dev-extra
Requires-Dist: black==26.5.1; extra == "dev-extra"
Requires-Dist: isort==8.0.1; extra == "dev-extra"
Requires-Dist: coverage==7.14.3; extra == "dev-extra"
Provides-Extra: docs
Requires-Dist: sphinx; extra == "docs"
Requires-Dist: sphinx-prompt; extra == "docs"
Requires-Dist: sphinxcontrib-spelling; extra == "docs"
Requires-Dist: sphinx-copybutton; extra == "docs"
Requires-Dist: towncrier==25.8.0; extra == "docs"
Requires-Dist: sphinxcontrib-towncrier; extra == "docs"
Requires-Dist: myst_parser; extra == "docs"
Requires-Dist: furo; extra == "docs"
Requires-Dist: sphinx-inline-tabs; extra == "docs"
Provides-Extra: docsauto
Requires-Dist: sphinx-autobuild; extra == "docsauto"
Provides-Extra: lint
Requires-Dist: pylint==4.0.4; extra == "lint"
Provides-Extra: tests
Requires-Dist: pytest>=7.2.0; extra == "tests"
Requires-Dist: pytest-salt-factories>=1.0.0; extra == "tests"
Requires-Dist: pytest-instafail; extra == "tests"
Dynamic: license-file

# Salt Extension for JumpCloud

Manage a JumpCloud organization from Salt: users, devices, the groups that bind
them together, and the policies that ride on those groups. Ships an execution
module, a runner and a set of states, so a directory can live in Git and be
reconciled rather than clicked together in a console.

```yaml
engineering:
  jumpcloud.usergroup_present:
    - description: Platform engineering
    - members:
      - jdoe
      - asmith
    - associations:
      - type: system_group
        name: linux-servers
```

## Status

Early. The API surface covered is deliberately narrower than JumpCloud's full
API: 13 collections across the v1 and v2 Console APIs, chosen as the part worth
managing declaratively. Everything else is reachable through
`jumpcloud.query`. See the [usage guide][docs-usage].

Requires Salt 3006 or newer.

## Design notes

**No SDK.** JumpCloud's Python SDK (`jcapi-python`) is not published to PyPI,
so a package depending on it could not itself be published to PyPI, and its
last commit was in 2019. The official Go CLI (`jc`) is actively developed but
is a community-support tool with a release most days, which is the wrong thing
for a state module to parse. This extension talks to the REST API directly
through `salt.utils.http`, which is also what `saltext-wanguard` does.

**The API model is verified against the vendor spec in CI.** JumpCloud
publishes both Console OpenAPI documents without authentication, so a CI job
fetches them and checks every claim this extension makes: that a collection
exists on the API version claimed, that the operations offered are actually
available, and that every declared association target still matches the
vendor's own schema. A JumpCloud-side change surfaces as a red pipeline rather
than as a `400` in somebody's state run.

**v1 and v2 differences are handled, not hidden badly.** v1 keys objects on
`_id` and wraps collections in an envelope; v2 keys on `id` and returns bare
arrays. A user is created at `/api/systemusers` but its bindings live at
`/api/v2/users`. Callers say `systemusers` and the client routes each call to
whichever API serves it.

## Branching

`master` is the release branch. Work happens on topic branches merged via merge
request. Tags matching `v*` enable a manual PyPI publish job.

## Security

If you discover a security vulnerability, please refer
to [Salt's security guide][security].

## User Documentation

For setup and usage instructions, please refer to the
[User Documentation][docs].

## Contributing

The saltext-jumpcloud project welcomes contributions from anyone!

The [Salt Extensions guide][salt-extensions-guide] provides comprehensive instructions on all aspects
of Salt extension development, including [writing tests][writing-tests], [running tests][running-tests],
[writing documentation][writing-docs] and [rendering the docs][rendering-docs].

### Quickstart

To get started contributing, first clone this repository (or your fork):

```bash
# Clone the repo
git clone --origin upstream git@gitlab.com:ggiesen/saltext-jumpcloud.git

# Change to the repo dir
cd saltext-jumpcloud
```

#### Automatic
If you have installed [direnv][direnv], copying the included `.envrc.example` to `.envrc` and
allowing it to run ensures a proper development environment is present and the virtual environment is active.

Without `direnv`, you can still run the automation explicitly:

```bash
make dev  # or python3 tools/initialize.py
source .venv/bin/activate
```

#### Manual
Please follow the [first steps][first-steps], skipping the repository initialization and first commit.

### Ways to contribute

Contributions come in many forms, and they’re all valuable! Here are some ways you can help
without writing code:

* **Documentation**: Especially examples showing how to use this project
  to solve specific problems.
* **Triaging issues**: Help manage [issues][issues].

You can also contribute by:

* Writing blog posts
* Sharing your experiences using Salt + JumpCloud
  on social media
* Giving talks at conferences
* Publishing videos
* Engaging in IRC, Discord or email groups

Any of these things are super valuable to our community, and we sincerely
appreciate every contribution!

[security]: https://github.com/saltstack/salt/blob/master/SECURITY.md
[salt-extensions-guide]: https://salt-extensions.github.io/salt-extension-copier/
[writing-tests]: https://salt-extensions.github.io/salt-extension-copier/topics/testing/writing.html
[running-tests]: https://salt-extensions.github.io/salt-extension-copier/topics/testing/running.html
[writing-docs]: https://salt-extensions.github.io/salt-extension-copier/topics/documenting/writing.html
[rendering-docs]: https://salt-extensions.github.io/salt-extension-copier/topics/documenting/building.html
[first-steps]: https://salt-extensions.github.io/salt-extension-copier/topics/creation.html#initialize-the-python-virtual-environment
[submitting-pr]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork
[direnv]: https://direnv.net
[issues]: https://gitlab.com/ggiesen/saltext-jumpcloud/-/issues
[comments]: https://conventionalcomments.org/
[docs]: https://ggiesen.gitlab.io/saltext-jumpcloud/

[docs-usage]: https://ggiesen.gitlab.io/saltext-jumpcloud/topics/usage.html
