-
Notifications
You must be signed in to change notification settings - Fork 156
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from TheJumpCloud/ra-go-example-scripts
Adding all the golang example scripts to support repo
- Loading branch information
Showing
30 changed files
with
3,126 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
build/ | ||
|
13 changes: 13 additions & 0 deletions
13
api-utils/JumpCloud_API_Go_Examples/BackupRestoreTags/BackupRestoreTags_suite_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package main_test | ||
|
||
import ( | ||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
|
||
"testing" | ||
) | ||
|
||
func TestBackupRestoreTags(t *testing.T) { | ||
RegisterFailHandler(Fail) | ||
RunSpecs(t, "BackupRestoreTags Suite") | ||
} |
156 changes: 156 additions & 0 deletions
156
api-utils/JumpCloud_API_Go_Examples/BackupRestoreTags/BackupRestoreTags_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
package main | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/TheJumpCloud/jcapi" | ||
|
||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
var _ = Describe("BackupRestoreTags", func() { | ||
Describe("jcback files", func() { | ||
const ( | ||
TESTFILE_1 = "testfile1.jcback" | ||
) | ||
|
||
var ( | ||
testTag1 jcapi.JCTag | ||
) | ||
|
||
BeforeEach(func() { | ||
testTag1 = jcapi.JCTag{ | ||
Id: "testId", | ||
Name: "testName", | ||
Systems: []string{"system1", "system2"}, | ||
SystemUsers: []string{"user1", "user2"}, | ||
} | ||
}) | ||
|
||
It("should write a file and read it back with the same contents", func() { | ||
err := writeTagFile(TESTFILE_1, testTag1) | ||
Expect(err).To(BeNil()) | ||
defer os.Remove(TESTFILE_1) | ||
|
||
exists := fileExists(TESTFILE_1) | ||
Expect(exists).To(BeTrue()) | ||
|
||
newTag, err := readTagFile(TESTFILE_1) | ||
Expect(err).To(BeNil()) | ||
|
||
Expect(newTag.Id).To(Equal("testId")) | ||
Expect(newTag.Name).To(Equal("testName")) | ||
Expect(newTag.Systems[0]).To(Equal("system1")) | ||
Expect(newTag.Systems[1]).To(Equal("system2")) | ||
Expect(newTag.SystemUsers[0]).To(Equal("user1")) | ||
Expect(newTag.SystemUsers[1]).To(Equal("user2")) | ||
}) | ||
|
||
It("should return false if a file does not exist", func() { | ||
exists := fileExists("missing.file") | ||
Expect(exists).To(BeFalse()) | ||
}) | ||
|
||
It("should return true if a file exists", func() { | ||
file, err := os.Create(TESTFILE_1) | ||
Expect(err).To(BeNil()) | ||
defer func() { | ||
file.Close() | ||
os.Remove(TESTFILE_1) | ||
}() | ||
|
||
exists := fileExists(TESTFILE_1) | ||
Expect(exists).To(BeTrue()) | ||
}) | ||
}) | ||
|
||
Describe("JC server", func() { | ||
var ( | ||
tagsOnAccount []jcapi.JCTag | ||
) | ||
|
||
BeforeEach(func() { | ||
tagsOnAccount = []jcapi.JCTag{ | ||
jcapi.JCTag{ | ||
Id: "1", | ||
Name: "tag1", | ||
Systems: []string{"system1", "system2"}, | ||
SystemUsers: []string{"user1", "user2"}, | ||
}, | ||
jcapi.JCTag{ | ||
Id: "2", | ||
Name: "tag2", | ||
Systems: []string{"system2", "system3"}, | ||
SystemUsers: []string{"user3", "user4"}, | ||
}, | ||
jcapi.JCTag{ | ||
Id: "3", | ||
Name: "tag3", | ||
Systems: []string{"system4", "system5"}, | ||
SystemUsers: []string{"user5", "user6"}, | ||
}, | ||
} | ||
}) | ||
|
||
Context("backup and restore", func() { | ||
It("should only back up zero tags when the regex matches none of them", func() { | ||
backedUpCount, tagCount, backupPath, err := backupTags(tagsOnAccount, "myTagNameRegex") | ||
Expect(err).To(BeNil()) | ||
defer os.RemoveAll(backupPath) | ||
|
||
Expect(backedUpCount).To(Equal(0)) | ||
Expect(tagCount).To(Equal(3)) | ||
}) | ||
|
||
It("should only back up one tag when the regex matches one", func() { | ||
backedUpCount, tagCount, backupPath, err := backupTags(tagsOnAccount, "tag1") | ||
Expect(err).To(BeNil()) | ||
defer os.RemoveAll(backupPath) | ||
|
||
Expect(backedUpCount).To(Equal(1)) | ||
Expect(tagCount).To(Equal(3)) | ||
}) | ||
|
||
It("should only back up two tags when the regex matches tw", func() { | ||
backedUpCount, tagCount, backupPath, err := backupTags(tagsOnAccount, "tag[12]") | ||
Expect(err).To(BeNil()) | ||
defer os.RemoveAll(backupPath) | ||
|
||
Expect(backedUpCount).To(Equal(2)) | ||
Expect(tagCount).To(Equal(3)) | ||
|
||
exists := fileExists(filepath.Join(backupPath, "tag1.jcback")) | ||
Expect(exists).To(BeTrue()) | ||
|
||
exists = fileExists(filepath.Join(backupPath, "tag2.jcback")) | ||
Expect(exists).To(BeTrue()) | ||
}) | ||
|
||
It("should read a backed up tag", func() { | ||
backedUpCount, tagCount, backupPath, err := backupTags(tagsOnAccount, "tag1") | ||
Expect(err).To(BeNil()) | ||
defer os.RemoveAll(backupPath) | ||
|
||
Expect(backedUpCount).To(Equal(1)) | ||
Expect(tagCount).To(Equal(3)) | ||
|
||
tagFileName := filepath.Join(backupPath, "tag1.jcback") | ||
|
||
exists := fileExists(tagFileName) | ||
Expect(exists).To(BeTrue()) | ||
|
||
newTag, err := readTagFile(tagFileName) | ||
Expect(err).To(BeNil()) | ||
|
||
Expect(newTag.Id).To(Equal("1")) | ||
Expect(newTag.Name).To(Equal("tag1")) | ||
Expect(newTag.Systems[0]).To(Equal("system1")) | ||
Expect(newTag.Systems[1]).To(Equal("system2")) | ||
Expect(newTag.SystemUsers[0]).To(Equal("user1")) | ||
Expect(newTag.SystemUsers[1]).To(Equal("user2")) | ||
}) | ||
}) | ||
}) | ||
}) |
176 changes: 176 additions & 0 deletions
176
api-utils/JumpCloud_API_Go_Examples/BackupRestoreTags/main.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"flag" | ||
"fmt" | ||
"io/ioutil" | ||
"log" | ||
"os" | ||
"path/filepath" | ||
"regexp" | ||
"time" | ||
|
||
"github.com/TheJumpCloud/jcapi" | ||
) | ||
|
||
const ( | ||
URL_BASE string = "https://console.jumpcloud.com/api" | ||
) | ||
|
||
func fileExists(fileName string) (exists bool) { | ||
if _, err := os.Stat(fileName); err == nil { | ||
exists = true | ||
} | ||
|
||
return | ||
} | ||
|
||
func readTagFile(backupFileName string) (tagData jcapi.JCTag, err error) { | ||
fileData, err := ioutil.ReadFile(backupFileName) | ||
if err != nil { | ||
return tagData, fmt.Errorf("Could not read file '%s', err='%s'", backupFileName, err) | ||
} | ||
|
||
err = json.Unmarshal(fileData, &tagData) | ||
if err != nil { | ||
return tagData, fmt.Errorf("Could not unmarshal tag data from file '%s', err='%s'", backupFileName, err) | ||
} | ||
|
||
return | ||
} | ||
|
||
func writeTagFile(tagFileName string, tag jcapi.JCTag) (err error) { | ||
tagData, err := json.Marshal(&tag) | ||
if err != nil { | ||
return fmt.Errorf("Cannot marshal tag data for tag '%s', err='%s'", tag.Name, err) | ||
} | ||
|
||
if fileExists(tagFileName) { | ||
return fmt.Errorf("Tag backup file '%s' exists in the current working directory, please move it before backing up.", tagFileName) | ||
} | ||
|
||
err = ioutil.WriteFile(tagFileName, tagData, 0600) | ||
if err != nil { | ||
return fmt.Errorf("Could not write tag data for tag '%s' to file '%s', err='%s'", tag.Name, tagFileName, err) | ||
} | ||
|
||
return | ||
} | ||
|
||
func getBackupDirName() (backupDirName string) { | ||
t := time.Now() | ||
tz, _ := t.Zone() | ||
|
||
backupDirName = "tagBackup-" + fmt.Sprintf("%d-%02d-%02dT%02d:%02d:%02d_%s", t.Year(), t.Month(), t.Day(), | ||
t.Hour(), t.Minute(), t.Second(), tz) | ||
|
||
return | ||
} | ||
|
||
func backupTags(tags []jcapi.JCTag, tagRegex string) (backedUpCount, tagCount int, backupDirName string, err error) { | ||
regex, err := regexp.Compile(tagRegex) | ||
if err != nil { | ||
return 0, 0, "", fmt.Errorf("Could not compile regex, err='%s'", err) | ||
} | ||
|
||
backupDirName = getBackupDirName() | ||
|
||
err = os.MkdirAll(backupDirName, 0700) | ||
if err != nil { | ||
return 0, 0, "", fmt.Errorf("Could not create backup directory '%s', err='%s'", backupDirName, err) | ||
} | ||
|
||
for _, value := range tags { | ||
if regex.FindString(value.Name) != "" { | ||
err := writeTagFile(filepath.Join(backupDirName, value.Name+".jcback"), value) | ||
if err != nil { | ||
return 0, 0, "", fmt.Errorf("Could not write tag '%s', err='%s'", value.Name, err) | ||
} | ||
|
||
backedUpCount++ | ||
} | ||
} | ||
|
||
tagCount = len(tags) | ||
|
||
return | ||
} | ||
|
||
func findTagByName(tags []jcapi.JCTag, tagName string) (idx int) { | ||
for idx, value := range tags { | ||
if value.Name == tagName { | ||
return idx | ||
} | ||
} | ||
|
||
return -1 | ||
} | ||
|
||
func restoreTags(jc jcapi.JCAPI, tags []jcapi.JCTag, backupFileName string) (tagId, tagName string, err error) { | ||
tagData, err := readTagFile(backupFileName) | ||
if err != nil { | ||
return "", "", fmt.Errorf("Could not read tag file '%s', err='%s'", backupFileName, err) | ||
} | ||
|
||
// Does the tag already exist on the JumpCloud account? | ||
if findTagByName(tags, tagData.Name) > -1 { | ||
// So we can't touch the tag... | ||
return "", "", fmt.Errorf("Cannot restore tag: a tag named '%s' already exists on your account.\n\nEither delete or rename the tag on your JumpCloud account to restore from a backup file.", tagData.Name) | ||
} | ||
|
||
// Add the tag to the account | ||
tagId, err = jc.AddUpdateTag(jcapi.Insert, tagData) | ||
if err != nil { | ||
return "", "", fmt.Errorf("Could not POST tag '%s' from file '%s' to your JumpCloud account, err='%s'", tagData.Name, backupFileName, err) | ||
} | ||
|
||
tagName = tagData.Name | ||
|
||
return | ||
} | ||
|
||
func main() { | ||
apiKey := flag.String("api-key", "", "Your JumpCloud Administrator API Key.") | ||
backupTagRegex := flag.String("backup", "", "Set this flag to a regular expression that matches the tag names you want to backup to your local file system.") | ||
restoreFile := flag.String("restore", "", "Set this flag to a filename that contains a tag you want to restore back to JumpCloud.") | ||
|
||
flag.Parse() | ||
|
||
if *apiKey == "" { | ||
log.Fatalf("api-key is required, please set it to the API key of a JumpCloud administrator on your JumpCloud account.") | ||
} | ||
|
||
if *backupTagRegex == "" && *restoreFile == "" { | ||
log.Fatalf("You must specify one of '-backup=<regexp-matching-your-tags>' or 'restore=<file-name-to-restore-to-jumpcloud>'") | ||
} | ||
|
||
if *backupTagRegex != "" && *restoreFile != "" { | ||
log.Fatalf("You may specific only one of 'backup' or 'restore'.") | ||
} | ||
|
||
jc := jcapi.NewJCAPI(*apiKey, URL_BASE) | ||
|
||
tags, err := jc.GetAllTags() | ||
if err != nil { | ||
log.Fatalf("Could not extract tags from your JumpCloud account, err='%s'", err) | ||
} | ||
|
||
if *backupTagRegex != "" { | ||
backedUpCount, tagCount, backupDirName, err := backupTags(tags, *backupTagRegex) | ||
if err != nil { | ||
log.Fatalf("Could not backup tags matching regex '%s', err='%s'", *backupTagRegex, err) | ||
} | ||
|
||
log.Printf("Backup complete, %d tags written out of %d tags total to '%s'", backedUpCount, tagCount, backupDirName) | ||
} | ||
|
||
if *restoreFile != "" { | ||
tagId, tagName, err := restoreTags(jc, tags, *restoreFile) | ||
if err != nil { | ||
log.Fatalf("Could not restore tag from file '%s', err='%s'", *restoreFile, err) | ||
} | ||
|
||
log.Printf("Tag '%s' restored from file '%s' as ID [%s]", tagName, *restoreFile, tagId) | ||
} | ||
} |
Oops, something went wrong.