Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ and this project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html)

## [Unreleased]

## [0.50.0] - 2026-10-22

### Changed

- **`bin/apps` reads the environments the way `bin/idm` does.** Without `--props` it reads
`IDM_ENVIRONMENTS` (or `./environments.properties`), then the person's own `IDM_CREDENTIALS` when
set, whose lines win: the split a team server and the DirXMLDevWeb container keep.

## [0.49.0] - 2026-10-20

### Added
Expand Down
39 changes: 27 additions & 12 deletions bin/apps
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
request history — without a browser. Python 3 standard library only.

bin/apps --env <name> [--props environments.properties] <command> [args]
(without --props: IDM_ENVIRONMENTS or ./environments.properties, then IDM_CREDENTIALS, as bin/idm reads them)

The environment's keys (same file as vault.deploy; never committed):
<env>.formsUrl https://<identity applications host>
Expand Down Expand Up @@ -41,17 +42,31 @@ import argparse, base64, json, os, ssl, sys, time, urllib.error, urllib.parse, u
PRD_SUFFIX = ",cn=RequestDefs,cn=AppConfig,cn=User Application Driver,cn=driverset1,o=system"


def read_props(path, env):
def default_props():
"""What bin/idm reads when no file is named: IDM_ENVIRONMENTS (or ./environments.properties), then the
person's own IDM_CREDENTIALS when set, whose lines win (the split a team server and the container keep)."""
paths = [os.environ.get("IDM_ENVIRONMENTS") or "environments.properties"]
mine = os.environ.get("IDM_CREDENTIALS")
if mine and os.path.isfile(mine):
paths.append(mine)
return paths


def read_props(paths, env):
if isinstance(paths, str):
paths = [paths]
props = {}
warn_if_shared(path)
with open(path, encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
k, v = line.split("=", 1)
if k.startswith(env + "."):
props[k[len(env) + 1:]] = v.strip()
for path in paths:
warn_if_shared(path)
with open(path, encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
k, v = line.split("=", 1)
if k.startswith(env + "."):
props[k[len(env) + 1:]] = v.strip()
path = " and ".join(paths)
missing = [k for k in ("formsUrl", "appsUser") if k not in props]
if missing:
sys.exit("environment '%s' lacks %s in %s" % (env, ", ".join(env + "." + m for m in missing), path))
Expand Down Expand Up @@ -185,13 +200,13 @@ def fault(r):
def main(argv):
ap = argparse.ArgumentParser(prog="bin/apps", description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
ap.add_argument("--env", required=True)
ap.add_argument("--props", default="environments.properties")
ap.add_argument("--props", default=None, help="the environments file (default: IDM_ENVIRONMENTS or ./environments.properties, plus IDM_CREDENTIALS)")
ap.add_argument("--json", action="store_true", help="print the raw response")
ap.add_argument("--insecure", action="store_true", help="skip TLS verification (labs with private CAs)")
ap.add_argument("command")
ap.add_argument("args", nargs=argparse.REMAINDER)
a = ap.parse_args(argv)
apps = Apps(read_props(a.props, a.env), a.insecure)
apps = Apps(read_props(a.props if a.props else default_props(), a.env), a.insecure)
cmd, rest = a.command, a.args

def sub(extra):
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.pointblue.dirxml</groupId>
<artifactId>dirxml-dev</artifactId>
<version>0.49.0</version>
<version>0.50.0</version>
<packaging>jar</packaging>

<name>DirXML Dev</name>
Expand Down
Loading