Skip to content

feat(go): add Go workflow scripts for ONTAP automation#55

Open
57388sp wants to merge 2 commits into
mainfrom
feat/go-scripts
Open

feat(go): add Go workflow scripts for ONTAP automation#55
57388sp wants to merge 2 commits into
mainfrom
feat/go-scripts

Conversation

@57388sp

@57388sp 57388sp commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Summary
Go implementations of the existing ONTAP workflows. Same use cases as Python/Ansible/Terraform — picked Go because some teams already have it in their stack and stdlib-only means nothing extra to install.

Changes
go.mod — module definition, Go 1.22+
ontapclient — thin HTTP wrapper around ONTAP REST (auth, job polling, error handling)
cluster_setup_basic — bootstrap a 2-node cluster
snapmirror_provision_src_managed — SnapMirror setup from source side
snapmirror_provision_dest_managed — SnapMirror setup from dest side, handles peer setup automatically
snapmirror_test_failover — FlexClone the dest volume for a test failover
snapmirror_cleanup_test_failover — tear down the test clone
.gitignore — added *.exe and *.test

Checklist
No hardcoded IPs or passwords — everything comes from env vars, defaults are empty strings
go build Downloads. and go vet Downloads. clean
catalog.yaml — skipped, Go isn't a catalogued tool yet

Test Report
Environment: ONTAP 9.8 vsim, Go 1.22.3, Windows 11

Ran all five scripts against a two-node vsim pair. Re-running each script a second time skips already-existing resources without errors.

Related issues
Part of the Go language support track.

@57388sp 57388sp requested a review from hvinn as a code owner June 15, 2026 06:02
@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown

A CI check failed — here is how to fix it

Workflow: PR Guard · Run #84 · Failed jobs: 1

commitlint

Commit message does not follow Conventional Commits. Required format:

<type>(<scope>): <description>

Valid types: build, chore, ci, doc, feat, fix, perf, refactor, revert, style, test. Valid scopes: python, ansible, terraform, docs, ci, deps.

To rewrite the last commit:

git commit --amend -m "feat(python): your description"
git push --force-with-lease

Push a fix and CI re-runs automatically; this comment updates with the next failure (or stays put if the same check fails again). Stuck? Comment on the PR and a maintainer will help — typical response time is 1 business day.

Auto-generated · explain-failure.yml

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Go implementations of existing ONTAP automation workflows, introducing a small stdlib-based ONTAP REST client plus Go scripts that mirror the SnapMirror and cluster-setup examples already present in Python/Ansible/Terraform.

Changes:

  • Added a new Go module (go 1.22) and a lightweight ontapclient wrapper for ONTAP REST calls.
  • Implemented Go workflow scripts for cluster setup and SnapMirror provisioning/test-failover/cleanup.
  • Updated .gitignore to exclude Go build/test outputs under go/.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
go/go.mod Defines the Go module and language version baseline.
go/ontapclient/ontap_client.go Adds a minimal REST client (auth, JSON handling, job polling, relationship polling).
go/cluster_setup_basic/main.go Go implementation of basic 2-node cluster bootstrap workflow.
go/snapmirror_provision_src_managed/main.go Go implementation of source-managed SnapMirror provisioning flow.
go/snapmirror_provision_dest_managed/main.go Go implementation of destination-managed provisioning, including auto peer setup.
go/snapmirror_test_failover/main.go Go implementation to create/tag a test-failover FlexClone and resync SnapMirror.
go/snapmirror_cleanup_test_failover/main.go Go implementation to locate/delete the tagged test-failover clone safely.
.gitignore Ignores go/**/*.exe and go/**/*.test outputs.

Comment on lines +168 to +185
func (c *Client) PollJob(jobUUID string, intervalSecs int) (map[string]interface{}, error) {
if intervalSecs <= 0 {
intervalSecs = 10
}
for {
result, err := c.Get(fmt.Sprintf("/cluster/jobs/%s", jobUUID),
map[string]string{"fields": "state,message,error,code"})
if err != nil {
return nil, fmt.Errorf("poll job %s: %w", jobUUID, err)
}
state, _ := result["state"].(string)
log.Printf(" job %s — state=%s", jobUUID, state)
if state != "running" {
return result, nil
}
time.Sleep(time.Duration(intervalSecs) * time.Second)
}
}
Comment on lines +174 to +183
cloneVol := map[string]interface{}{}
if vols := ontapclient.Records(cloneVolResp); len(vols) > 0 {
cloneVol = vols[0]
}
cloneUUID := ontapclient.NestedStr(cloneVol, "uuid")
log.Printf("CLONE | name=%s | uuid=%s | state=%s | junction=%s",
ontapclient.NestedStr(cloneVol, "name"), cloneUUID,
ontapclient.NestedStr(cloneVol, "state"),
ontapclient.NestedStr(cloneVol, "nas", "path"))
return cloneName, cloneUUID
Comment on lines +162 to +167
peerName := ""
if peers := ontapclient.Records(peerResp); len(peers) > 0 {
peerName = ontapclient.NestedStr(peers[0], "name")
}
log.Printf("CLUSTER PEER | name=%s", peerName)

Comment thread go/snapmirror_provision_src_managed/main.go
Comment thread go/snapmirror_provision_src_managed/main.go Outdated
Comment on lines +397 to +419
func fetchCreatedPeerNames(src, dst *ontapclient.Client) (string, string, string) {
okStates := map[string]bool{"available": true, "partial": true, "pending": true}
dstCP, _ := dst.Get(pathClusterPeers, map[string]string{"fields": peerFields, "max_records": "10"})
dstPeer := map[string]interface{}{}
for _, p := range ontapclient.Records(dstCP) {
if okStates[ontapclient.NestedStr(p, "status", "state")] {
dstPeer = p
break
}
}
srcCP, _ := src.Get(pathClusterPeers, map[string]string{"fields": peerFields, "max_records": "10"})
srcPeer := map[string]interface{}{}
for _, p := range ontapclient.Records(srcCP) {
if okStates[ontapclient.NestedStr(p, "status", "state")] {
srcPeer = p
break
}
}
log.Printf("CLUSTER PEER | dst sees src as '%s'", ontapclient.NestedStr(dstPeer, "name"))
return ontapclient.NestedStr(srcPeer, "name"),
ontapclient.NestedStr(dstPeer, "name"),
ontapclient.NestedStr(dstPeer, "uuid")
}
Comment thread go/snapmirror_provision_dest_managed/main.go
Comment thread go/snapmirror_provision_dest_managed/main.go
Comment on lines +7 to +10
// AUTO mode (SOURCE_VOLUME=* or unset):
//
// Queries both clusters, picks the one with the most recently created DP volume.
//
Comment thread go/snapmirror_cleanup_test_failover/main.go Outdated
Add Go implementations of the existing Python, Ansible, and Terraform workflows.
After POST /cluster ONTAP restarts its management stack, forcibly
closing the TCP connection. The previous code treated any poll error
as fatal; this change retries on network-level errors (expected reboot
drop) and only fails on HTTP-level errors (4xx/5xx).

Also adds 'errors' import required by errors.As().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants