Skip to content

Synpse Go client to orchestrate your IoT and server infrastructure

License

Notifications You must be signed in to change notification settings

synpse-hq/synpse-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation


The easiest way to bootstrap your devices and deploy applications.
Synpse manages OTA deployment & updates, provides SSH and network access.


WebsiteDiscussionsDocsDiscordCloud

Synpse v1 API client

Build Status Doc

Synpse provides your device fleet management, application deployment and their configuration. Whole process is simple with very low learning curve.

  • 🚧 This API client is still under active development, the methods can be changed 🚧 *

Prerequisites

Install

go get github.com/synpse-hq/synpse-go

Authentication

To authenticate, we recommend using a project level access key that you can generate here: https://cloud.synpse.net/service-accounts.

Alternatively, use Personal Access Keys, however, they will be able to manage multiple projects.

Examples

Let's start with creating an client API:

package main

import (
  "os"
  "fmt"

  "github.com/synpse-hq/synpse-go"
)

func main() {
  // Create a new API client with a specified access key. You can get your access key
  // from https://cloud.synpse.net/service-accounts
  apiClient, _ := synpse.NewWithProject(os.Getenv("SYNPSE_PROJECT_ACCESS_KEY"), os.Getenv("SYNPSE_PROJECT_ID"))    
}

Registering New Device

When automating your device fleet operations, you will most likely need to create and manage device registration tokens. These tokens can be created with a set of labels and environment variables which will then be inherited by any device that registers using it.

  // In this example we use user ID but it could be anything else like company name, location identifier, etc.
  var userID = "usr_mkalpxzlab"
  // Optional max registrations. It's a good practice to set these to sane limits. If you expect only one device
  // to register with this token, set it to 1.
  var maxRegistrations = 10

  // Create a registration token
  drt, _ := apiClient.CreateRegistrationToken(ctx, synpse.DeviceRegistrationToken{
    Name:                 "drt-" + userID,
    MaxRegistrations:     &maxRegistrations,                 // optional 
    Labels:               map[string]string{"user": userID}, // optional
  })

  // Use this token together with your project ID:
  // 
  // curl https://downloads.synpse.net/install.sh | \
  //   AGENT_PROJECT={{ PROJECT_ID }} \
  //   AGENT_REGISTRATION_TOKEN={{ DEVICE_REGISTRATION_TOKEN }} \
  //   bash


  // Once registration token is created, you can use device filtering to find it:
  devicesResp, _ := apiClient.ListDevices(context.Background(), &synpse.ListDevicesRequest{
    Labels: map[string]string{
      "user": userID, 
    },
  })

List Devices

  // List devices
  devicesResp, _ := apiClient.ListDevices(context.Background(), &synpse.ListDevicesRequest{})

  // Print device names
  for _, device := range devicesResp.Devices {
    fmt.Println(device.Name)
  }

Here we list an already registered devices. Default page size is 100, if you have more devices, use pagination options and iterate for as long as you have the next page token.

Filtering devices during the query is almost always the preferred solution. You can filter devices by labels:

  // List devices that have this label
  devicesResp, _ := apiClient.ListDevices(context.Background(), &synpse.ListDevicesRequest{
    Labels: map[string]string{
      "group": "one", 
    },
  })

Create Application

Applications in Synpse can either:

  • Run on all devices in the project
  • Run on devices with matching labels

To create an application that will run on all devices:

  // Create an application in 'default' namespace that will be deployed on all devices
  application, err := apiClient.CreateApplication(context.Background(), "default", synpse.Application{
    Name:        "app-name",
    Scheduling: synpse.Scheduling{
      Type: synpse.ScheduleTypeAllDevices,
    },
    Spec: synpse.ApplicationSpec{
      ContainerSpec: []synpse.ContainerSpec{
        {
          Name:  "hello",
          Image: "quay.io/synpse/hello-synpse-go:latest",
          Ports: []string{"8080:8080"},
        },
      },
    },
  })

or only on specific devices, based on label selector:

  // Create an application that will be deployed on devices that have our specified label
  application, err := apiClient.CreateApplication(context.Background(), "default", synpse.Application{
    Name:        "app-name",
    Scheduling: synpse.Scheduling{
      Type: synpse.ScheduleTypeConditional,
      Selector: {
        "location": "power-plant",
      }
    },
    Spec: synpse.ApplicationSpec{
      ContainerSpec: []synpse.ContainerSpec{
        {
          Name:  "hello",
          Image: "quay.io/synpse/hello-synpse-go:latest",
          Ports: []string{"8080:8080"},
        },
      },
    },
  })

Update Application

During the normal lifecycle, you will be updating application many times. For example if you want to update the Docker image or expose additional ports, use the UpdateApplication method:

  // Create an application that will be deployed on devices that have our specified label
  application, err := apiClient.UpdateApplication(context.Background(), "default", synpse.Application{
    ID:          app.ID,
    Name:        "app-name",
    Scheduling: synpse.Scheduling{
      Type: synpse.ScheduleTypeConditional,
      Selector: {
        "location": "power-plant",
      }
    },
    Spec: synpse.ApplicationSpec{
      ContainerSpec: []synpse.ContainerSpec{
        {
          Name:  "hello",
          Image: "quay.io/synpse/hello-synpse-go:new",
          Ports: []string{
            "8080:8080",
            "8888:8888",            
          },
        },
      },
    },
  })

List Applications

To list applications:

    applications, err := apiClient.ListApplications(
      context.Background(), 
      &synpse.ListApplicationsRequest{Namespace: "default"},
    )
    for _, app := range applications {
      fmt.Println(app.Name)
    }

Delete Applications:

You can remove applications by using name or ID:

  err := apiClient.DeleteApplication(context.Background(), "default", "app-name")