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
18 changes: 11 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ go test -run TestName -v ./internal/job/... # Run a single test
- **`internal/agent/`** - Node agent: consumer/handler/processor pipeline for job execution
- **`internal/provider/`** - Operation implementations: `node/{host,disk,mem,load}`, `network/{dns,ping}`
- **`internal/config/`** - Viper-based config from `osapi.yaml`
- **`pkg/sdk/`** - Go SDK for programmatic REST API access (`osapi/` client library, `orchestrator/` DAG runner)
- **`pkg/sdk/`** - Go SDK for programmatic REST API access (`client/` client library, `orchestrator/` DAG runner)
- Shared `nats-client` and `nats-server` are sibling repos linked via `replace` in `go.mod`
- **`github/`** - Temporary GitHub org config tooling (`repos.json` for declarative repo settings, `sync.sh` for drift detection via `gh` CLI). Untracked and intended to move to its own repo.

Expand Down Expand Up @@ -171,7 +171,7 @@ Create `internal/api/{domain}/`:

### Step 5: Update SDK

The SDK client library lives in `pkg/sdk/osapi/`. Its generated HTTP client
The SDK client library lives in `pkg/sdk/client/`. Its generated HTTP client
uses the same combined OpenAPI spec as the server
(`internal/api/gen/api.yaml`).

Expand All @@ -180,15 +180,15 @@ uses the same combined OpenAPI spec as the server
1. Make changes to `internal/api/{domain}/gen/api.yaml` in this repo
2. Run `just generate` to regenerate server code (this also regenerates the
combined spec via `redocly join`)
3. Run `go generate ./pkg/sdk/osapi/gen/...` to regenerate the SDK client
4. Update the SDK service wrappers in `pkg/sdk/osapi/{domain}.go` if new
3. Run `go generate ./pkg/sdk/client/gen/...` to regenerate the SDK client
4. Update the SDK service wrappers in `pkg/sdk/client/{domain}.go` if new
response codes were added
5. Update CLI switch blocks in `cmd/` if new response codes were added

**When adding a new API domain:**

1. Add a service wrapper in `pkg/sdk/osapi/{domain}.go`
2. Run `go generate ./pkg/sdk/osapi/gen/...` to pick up the new domain's
1. Add a service wrapper in `pkg/sdk/client/{domain}.go`
2. Run `go generate ./pkg/sdk/client/gen/...` to pick up the new domain's
spec from the combined `api.yaml`

### Step 6: CLI Commands
Expand Down Expand Up @@ -253,7 +253,11 @@ Three test layers:
middleware with mocked backends.
- **Integration tests** (`test/integration/`) — build and start a real
`osapi` binary, exercise CLI commands end-to-end. Guarded by
`//go:build integration` tag, run with `just go::unit-int`.
`//go:build integration` tag, run with `just go::unit-int`. New API
domains should include a `{domain}_test.go` smoke suite. Write tests
(mutations) must be guarded by `skipWrite(s.T())` so CI can run
read-only tests by default (`OSAPI_INTEGRATION_WRITES=1` enables
writes).

Conventions:
- ALL tests in `internal/job/` MUST use `testify/suite` with table-driven patterns
Expand Down
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,15 @@ them to be used as appliances.
[Getting Started]: https://osapi-io.github.io/osapi/
[API]: https://osapi-io.github.io/osapi/category/api
[Usage]: https://osapi-io.github.io/osapi/sidebar/usage
[SDK]: https://osapi-io.github.io/osapi/sidebar/sdk/sdk
[SDK]: https://osapi-io.github.io/osapi/sidebar/sdk

## 🔗 Sister Projects

| Project | Description |
| --- | --- |
| [osapi-orchestrator][] | A Go package for orchestrating operations across OSAPI-managed hosts — typed operations, chaining, conditions, and result decoding built on top of the osapi-sdk engine |
| [nats-client][] | A Go package for connecting to and interacting with a NATS server |
| [nats-server][] | A Go package for running an embedded NATS server |

[osapi-orchestrator]: https://github.com/osapi-io/osapi-orchestrator
[nats-client]: https://github.com/osapi-io/nats-client
[nats-server]: https://github.com/osapi-io/nats-server

Expand Down
8 changes: 4 additions & 4 deletions cmd/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"context"
"log/slog"

"github.com/retr0h/osapi/pkg/sdk/osapi"
"github.com/retr0h/osapi/pkg/sdk/client"
"github.com/spf13/cobra"
"github.com/spf13/viper"

Expand All @@ -33,7 +33,7 @@ import (
)

var (
sdkClient *osapi.Client
sdkClient *client.Client
tracerShutdown func(context.Context) error
)

Expand Down Expand Up @@ -61,10 +61,10 @@ var clientCmd = &cobra.Command{
slog.String("api.client.url", appConfig.API.URL),
)

sdkClient = osapi.New(
sdkClient = client.New(
appConfig.API.URL,
appConfig.API.Client.Security.BearerToken,
osapi.WithLogger(logger),
client.WithLogger(logger),
)
},
PersistentPostRun: func(_ *cobra.Command, _ []string) {
Expand Down
4 changes: 2 additions & 2 deletions cmd/client_agent_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
"strings"
"time"

"github.com/retr0h/osapi/pkg/sdk/osapi"
"github.com/retr0h/osapi/pkg/sdk/client"
"github.com/spf13/cobra"

"github.com/retr0h/osapi/internal/cli"
Expand Down Expand Up @@ -57,7 +57,7 @@ var clientAgentGetCmd = &cobra.Command{

// displayAgentGetDetail renders detailed agent information in PrintKV style.
func displayAgentGetDetail(
data *osapi.Agent,
data *client.Agent,
) {
fmt.Println()

Expand Down
4 changes: 2 additions & 2 deletions cmd/client_audit_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
"fmt"
"strconv"

"github.com/retr0h/osapi/pkg/sdk/osapi"
"github.com/retr0h/osapi/pkg/sdk/client"
"github.com/spf13/cobra"

"github.com/retr0h/osapi/internal/audit/export"
Expand Down Expand Up @@ -60,7 +60,7 @@ entry as a JSON line (JSONL format). Requires audit:read permission.

func writeExport(
ctx context.Context,
items []osapi.AuditEntry,
items []client.AuditEntry,
totalItems int,
) {
var exporter export.Exporter
Expand Down
6 changes: 3 additions & 3 deletions cmd/client_file_upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
"github.com/spf13/cobra"

"github.com/retr0h/osapi/internal/cli"
osapi "github.com/retr0h/osapi/pkg/sdk/osapi"
"github.com/retr0h/osapi/pkg/sdk/client"
)

// clientFileUploadCmd represents the clientFileUpload command.
Expand All @@ -49,9 +49,9 @@ var clientFileUploadCmd = &cobra.Command{
}
defer func() { _ = f.Close() }()

var opts []osapi.UploadOption
var opts []client.UploadOption
if force {
opts = append(opts, osapi.WithForce())
opts = append(opts, client.WithForce())
}

resp, err := sdkClient.File.Upload(ctx, name, contentType, f, opts...)
Expand Down
4 changes: 2 additions & 2 deletions cmd/client_health_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ package cmd
import (
"fmt"

"github.com/retr0h/osapi/pkg/sdk/osapi"
"github.com/retr0h/osapi/pkg/sdk/client"
"github.com/spf13/cobra"

"github.com/retr0h/osapi/internal/cli"
Expand Down Expand Up @@ -55,7 +55,7 @@ Requires authentication.

// displayStatusHealth renders health status output with system metrics.
func displayStatusHealth(
data *osapi.SystemStatus,
data *client.SystemStatus,
) {
fmt.Println()
cli.PrintKV("Status", data.Status, "Version", data.Version, "Uptime", data.Uptime)
Expand Down
8 changes: 4 additions & 4 deletions cmd/client_job_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
"strings"
"time"

"github.com/retr0h/osapi/pkg/sdk/osapi"
"github.com/retr0h/osapi/pkg/sdk/client"
"github.com/spf13/cobra"

"github.com/retr0h/osapi/internal/cli"
Expand All @@ -44,7 +44,7 @@ var clientJobListCmd = &cobra.Command{
offsetFlag, _ := cmd.Flags().GetInt("offset")

// Get jobs list (server-side pagination)
jobsResp, err := sdkClient.Job.List(ctx, osapi.ListParams{
jobsResp, err := sdkClient.Job.List(ctx, client.ListParams{
Status: statusFilter,
Limit: limitFlag,
Offset: offsetFlag,
Expand Down Expand Up @@ -76,7 +76,7 @@ var clientJobListCmd = &cobra.Command{
}

func displayJobListJSON(
jobs []osapi.JobDetail,
jobs []client.JobDetail,
totalItems int,
statusCounts map[string]int,
statusFilter string,
Expand Down Expand Up @@ -129,7 +129,7 @@ func displayJobListSummary(
}

func displayJobListTable(
jobs []osapi.JobDetail,
jobs []client.JobDetail,
) {
if len(jobs) == 0 {
return
Expand Down
4 changes: 2 additions & 2 deletions cmd/client_job_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
"os"
"time"

"github.com/retr0h/osapi/pkg/sdk/osapi"
"github.com/retr0h/osapi/pkg/sdk/client"
"github.com/spf13/cobra"

"github.com/retr0h/osapi/internal/cli"
Expand Down Expand Up @@ -108,7 +108,7 @@ This combines job submission and retrieval into a single command for convenience

func checkJobComplete(
ctx context.Context,
jobService *osapi.JobService,
jobService *client.JobService,
jobID string,
) bool {
resp, err := jobService.Get(ctx, jobID)
Expand Down
Loading
Loading