Skip to content

Commit cd20ea6

Browse files
clcollinsclaude
andauthored
Fix base64 encoding for ocm-container CLI compatibility (#139)
* Fix base64 encoding to use standard alphabet for CLI compatibility Switch ALERT_DETAILS encoding from RawURLEncoding to RawStdEncoding. RawURLEncoding uses a URL-safe alphabet (-_) that the `base64 -d` CLI tool inside ocm-container doesn't understand. RawStdEncoding uses the standard alphabet (+/) which is compatible with `base64 -d`, while still avoiding = padding that breaks ocm-container's env var parsing. Created with assistance from Claude 🤖 <claude@anthropic.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Christopher Collins <collins.christopher@gmail.com> * Fix pre-existing lint issues - main.go: suppress errcheck for deferred asyncWriter.Close() - model_test.go: suppress staticcheck SA9003 for placeholder empty branch - views.go: remove unused renderActionLogHeader function Created with assistance from Claude 🤖 <claude@anthropic.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Christopher Collins <collins.christopher@gmail.com> * Address Copilot review feedback - Fix inconsistent base64 encoding references in README - Remove empty if block in model_test.go Created with assistance from Claude 🤖 <claude@anthropic.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Christopher Collins <collins.christopher@gmail.com> --------- Signed-off-by: Christopher Collins <collins.christopher@gmail.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 9f8db70 commit cd20ea6

6 files changed

Lines changed: 12 additions & 30 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,15 +229,15 @@ When using `ocm-container` as your cluster login command, srepd automatically pa
229229
The following environment variables are automatically set:
230230

231231
* `PAGERDUTY_INCIDENT` - The PagerDuty incident ID
232-
* `ALERT_DETAILS` - Base64 URL-encoded JSON containing the full incident object, all associated alerts, and incident notes
232+
* `ALERT_DETAILS` - Base64-encoded JSON containing the full incident object, all associated alerts, and incident notes
233233

234234
Example usage inside ocm-container:
235235

236236
```bash
237237
# View the incident ID
238238
echo $PAGERDUTY_INCIDENT
239239
240-
# Decode and view the full alert details (note: using base64 -d with URL encoding)
240+
# Decode and view the full alert details
241241
echo $ALERT_DETAILS | base64 -d | jq .
242242
243243
# Extract specific alert information
@@ -247,6 +247,6 @@ echo $ALERT_DETAILS | base64 -d | jq '.alerts[0].body.details.cluster_id'
247247
echo $ALERT_DETAILS | base64 -d | jq '.notes'
248248
```
249249

250-
**Note:** The `ALERT_DETAILS` variable uses base64 URL encoding (RFC 4648) without padding to avoid parsing issues with `=` characters.
250+
**Note:** The `ALERT_DETAILS` variable uses standard base64 encoding without padding to avoid parsing issues with `=` characters in ocm-container's env var handling.
251251

252252
These environment variables are automatically added when you use the login feature (press `l` on an incident). No additional configuration is required.

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func main() {
4444

4545
// Use async writer to prevent log I/O from blocking the UI
4646
asyncWriter := newAsyncWriter(f, 1000) // Buffer up to 1000 log messages
47-
defer asyncWriter.Close()
47+
defer asyncWriter.Close() //nolint:errcheck
4848

4949
log.SetOutput(asyncWriter)
5050

pkg/tui/commands.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,10 @@ func login(vars map[string]string, launcher launcher.ClusterLauncher, incident *
448448
if err != nil {
449449
log.Warn("tui.login(): failed to marshal alert data", "error", err)
450450
} else {
451-
// Use RawURLEncoding which doesn't add padding (no = characters)
452-
// This avoids issues with ocm-container's env var parsing which splits on =
453-
encoded := base64.RawURLEncoding.EncodeToString(jsonData)
451+
// Use RawStdEncoding: standard base64 alphabet (+/) without padding (no = characters)
452+
// No padding avoids issues with ocm-container's env var parsing which splits on =
453+
// Standard alphabet ensures `echo $ALERT_DETAILS | base64 -d` works in the container
454+
encoded := base64.RawStdEncoding.EncodeToString(jsonData)
454455
envFlags = append(envFlags, "-e", fmt.Sprintf("ALERT_DETAILS=%s", encoded))
455456
}
456457
}

pkg/tui/commands_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -458,14 +458,14 @@ func TestLoginEnvironmentVariables(t *testing.T) {
458458
assert.NoError(t, err, "Failed to marshal alertData")
459459
assert.NotNil(t, jsonData, "JSON data should not be nil")
460460

461-
// Test that it can be base64 URL encoded (without padding)
462-
encoded := base64.RawURLEncoding.EncodeToString(jsonData)
461+
// Test that it can be base64 encoded (standard alphabet, without padding)
462+
encoded := base64.RawStdEncoding.EncodeToString(jsonData)
463463
assert.NotEmpty(t, encoded, "Base64 encoding should not be empty")
464464
// Verify no padding characters
465-
assert.NotContains(t, encoded, "=", "RawURLEncoding should not contain = padding")
465+
assert.NotContains(t, encoded, "=", "RawStdEncoding should not contain = padding")
466466

467467
// Test that it can be decoded back
468-
decoded, err := base64.RawURLEncoding.DecodeString(encoded)
468+
decoded, err := base64.RawStdEncoding.DecodeString(encoded)
469469
assert.NoError(t, err, "Failed to decode base64")
470470

471471
var decodedData alertData

pkg/tui/model_test.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -266,14 +266,6 @@ func TestGetHighlightedIncident(t *testing.T) {
266266
m := createTestModel()
267267
m.incidentList = tt.incidentList
268268

269-
// Set up table rows to match incident list
270-
if tt.hasSelectedRow && len(tt.incidentList) > 0 {
271-
// Manually set the cursor to simulate a selected row
272-
// We'll use the test directly by creating a mock selected row
273-
// Since we can't easily mock the table.SelectedRow(), we'll test by
274-
// setting up the incident list and verifying the lookup logic
275-
}
276-
277269
// For this test, we'll directly test the lookup logic
278270
// by simulating what getHighlightedIncident does
279271
var result *pagerduty.Incident

pkg/tui/views.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -252,17 +252,6 @@ func (m model) renderHeader() string {
252252
return s.String()
253253
}
254254

255-
func (m model) renderActionLogHeader() string {
256-
headerText := "Action Log"
257-
// Center the header text horizontally
258-
// Using windowSize.Width and paddedStyle to match the main UI width
259-
centeredHeader := lipgloss.NewStyle().
260-
Width(windowSize.Width).
261-
Align(lipgloss.Center).
262-
Render(headerText)
263-
return paddedStyle.Render(centeredHeader)
264-
}
265-
266255
func (m model) renderBottomStatus() string {
267256
var s strings.Builder
268257
var selectedID string

0 commit comments

Comments
 (0)