Skip to content
Snippets Groups Projects
Commit 044a4fc9 authored by ale's avatar ale
Browse files

Update radioctl for the new APIs

parent 10cfbc65
No related branches found
No related tags found
1 merge request!1v2.0
package main
import (
"context"
"encoding/json"
"flag"
"fmt"
......@@ -9,14 +10,21 @@ import (
"os"
"strconv"
"strings"
"time"
"git.autistici.org/ale/autoradio"
"git.autistici.org/ale/autoradio/client"
pb "git.autistici.org/ale/autoradio/proto"
"github.com/gonuts/commander"
gonutsflag "github.com/gonuts/flag"
"go.etcd.io/etcd/clientv3"
)
// Format for output of structured data.
var outputFormat = flag.String("format", "txt", "Output format for structured data (json, txt)")
var (
etcdEndpoints = flag.String("etcd", "http://localhost:2379", "Etcd endpoints (comma-separated list of URLs)")
outputFormat = flag.String("format", "txt", "Output format for structured data (json, txt)")
)
type optionalValue struct {
isSet bool
......@@ -135,15 +143,27 @@ func (b *BaseCommand) Command() *commander.Command {
func (b *BaseCommand) Run(args []string) {
}
func getClient() *autoradio.Client {
return autoradio.NewClient(autoradio.NewEtcdClient(false))
var auClient *client.Client
func getClient() *client.Client {
if auClient == nil {
cli, err := clientv3.New(clientv3.Config{
Endpoints: strings.Split(*etcdEndpoints, ","),
DialTimeout: 5 * time.Second,
})
if err != nil {
log.Fatalf("failed to connect to etcd: %v", err)
}
auClient = client.New(cli)
}
return auClient
}
func setRelay(m *autoradio.Mount, relayUrl string) {
func setRelay(m *pb.Mount, relayUrl string) {
if relayUrl == "" {
// Randomly generate source credentials.
m.Username = autoradio.GenerateUsername(m.Name)
m.Password = autoradio.GeneratePassword()
m.SourceUsername = autoradio.GenerateUsername(m.Path)
m.SourcePassword = autoradio.GeneratePassword()
} else {
// Validate the given relay URL.
u, err := url.Parse(relayUrl)
......@@ -151,30 +171,30 @@ func setRelay(m *autoradio.Mount, relayUrl string) {
log.Fatal(err)
}
m.RelayUrl = u.String()
m.Username = ""
m.Password = ""
m.SourceUsername = ""
m.SourcePassword = ""
}
}
func printMount(m *autoradio.Mount) {
func printMount(m *pb.Mount) {
switch *outputFormat {
case "json":
s, _ := json.MarshalIndent(m, "", " ")
os.Stdout.Write(s)
case "txt":
fmt.Printf("path=%s\n", m.Name)
if m.Username != "" {
fmt.Printf("username=%s\npassword=%s\n", m.Username, m.Password)
fmt.Printf("path=%s\n", m.Path)
if m.SourceUsername != "" {
fmt.Printf("username=%s\npassword=%s\n", m.SourceUsername, m.SourcePassword)
}
if m.RelayUrl != "" {
fmt.Printf("relay_url=%s\n", m.RelayUrl)
}
if m.Fallback != "" {
fmt.Printf("fallback_url=%s\n", m.Fallback)
if m.FallbackPath != "" {
fmt.Printf("fallback_url=%s\n", m.FallbackPath)
}
if t := m.Transcoding; t != nil {
fmt.Printf("transcode_source_url=%s\n", t.SourceName)
if t := m.TranscodeParams; t != nil {
fmt.Printf("transcode_source_url=%s\n", t.SourcePath)
fmt.Printf("transcode_format=%s\n", t.Format)
fmt.Printf("transcode_bitrate=%d\n", t.BitRate)
fmt.Printf("transcode_quality=%f\n", t.Quality)
......@@ -186,8 +206,8 @@ func printMount(m *autoradio.Mount) {
}
}
func mountExists(name string, client *autoradio.Client) bool {
m, _ := client.GetMount(name)
func mountExists(name string, c *client.Client) bool {
m, _ := c.GetMount(context.Background(), name)
return m != nil
}
......@@ -229,22 +249,22 @@ func (cmd *createMountCommand) Run(args []string) {
}
// Check if the mount already exists.
client := getClient()
if mountExists(path, client) {
c := getClient()
if mountExists(path, c) {
log.Fatal("ERROR: A mount with that name already exists!")
}
// Create the new mount and set the relevant fields (depending
// on the options passed to the command).
m := &autoradio.Mount{Name: path}
m := &pb.Mount{Path: path}
setRelay(m, cmd.relay)
m.Fallback = cmd.fallback
m.FallbackPath = cmd.fallback
if err := m.Valid(); err != nil {
log.Fatalf("ERROR: mount configuration is invalid: %v", err)
}
if err := client.SetMount(m); err != nil {
if err := c.SetMount(context.Background(), m); err != nil {
log.Fatalf("ERROR: creating mount: %v", err)
}
......@@ -254,8 +274,15 @@ func (cmd *createMountCommand) Run(args []string) {
// Create a submount (transcoded stream).
type createTranscodingMountCommand struct {
BaseCommand
params *autoradio.EncodingParams
fallback string
sourcePath string
format string
quality float64
bitRate int
sampleRate int
channels int
stereoMode string
fallback string
}
func newCreateTranscodingMountCommand() *createTranscodingMountCommand {
......@@ -268,22 +295,17 @@ Create a new stream that will transcode the parent stream with
different encoding parameters.
`,
},
params: autoradio.NewEncodingParams(),
}
}
func addEncodingFlags(f *gonutsflag.FlagSet, p *autoradio.EncodingParams) {
f.StringVar(&p.SourceName, "source", "", "Source mountpoint")
f.StringVar(&p.Format, "codec", p.Format, "Encoding format")
f.Float64Var(&p.Quality, "quality", p.Quality, "Quality (for VBR encoders)")
f.IntVar(&p.BitRate, "bitrate", p.BitRate, "Bitrate (kbps)")
f.IntVar(&p.SampleRate, "samplerate", p.SampleRate, "Sample rate (Hz)")
f.IntVar(&p.Channels, "channels", p.Channels, "Number of channels")
f.StringVar(&p.StereoMode, "stereo-mode", p.StereoMode, "Stereo mode for mp3 codec (stereo, joint_stereo)")
}
func (cmd *createTranscodingMountCommand) AddFlags(f *gonutsflag.FlagSet) {
addEncodingFlags(f, cmd.params)
f.StringVar(&cmd.sourcePath, "source", "", "Source mountpoint")
f.StringVar(&cmd.format, "codec", "mp3", "Encoding format")
f.Float64Var(&cmd.quality, "quality", 0, "Quality (for VBR encoders)")
f.IntVar(&cmd.bitRate, "bitrate", 32, "Bitrate (kbps)")
f.IntVar(&cmd.sampleRate, "samplerate", 44100, "Sample rate (Hz)")
f.IntVar(&cmd.channels, "channels", 2, "Number of channels")
f.StringVar(&cmd.stereoMode, "stereo-mode", "joint_stereo", "Stereo mode for mp3 codec (stereo, joint_stereo)")
f.StringVar(&cmd.fallback, "fallback", "", "Fallback stream URL")
}
......@@ -299,28 +321,37 @@ func (cmd *createTranscodingMountCommand) Run(args []string) {
}
// The mount path should not exist.
client := getClient()
if mountExists(path, client) {
c := getClient()
if mountExists(path, c) {
log.Fatal("ERROR: a mount with that name already exists!")
}
// The source mount should exist.
if !mountExists(cmd.params.SourceName, client) {
if !mountExists(cmd.sourcePath, c) {
log.Fatal("ERROR: the source mount does not exist!")
}
// Retrieve the parent mount point and add a TranscodingMount.
m := &autoradio.Mount{
Name: path,
Transcoding: cmd.params,
m := &pb.Mount{
Path: path,
FallbackPath: cmd.fallback,
Transcode: true,
TranscodeParams: &pb.EncodingParams{
SourcePath: cmd.sourcePath,
Format: cmd.format,
BitRate: int32(cmd.bitRate),
SampleRate: int32(cmd.sampleRate),
Channels: int32(cmd.channels),
StereoMode: cmd.stereoMode,
Quality: float32(cmd.quality),
},
}
setRelay(m, "")
m.Fallback = cmd.fallback
if err := m.Valid(); err != nil {
log.Fatalf("ERROR: mount configuration is invalid: %v", err)
}
if err := client.SetMount(m); err != nil {
if err := c.SetMount(context.Background(), m); err != nil {
log.Fatalf("ERROR: creating mount: %v", err)
}
......@@ -402,8 +433,8 @@ func (cmd *editMountCommand) Run(args []string) {
log.Fatal("Wrong number of arguments")
}
client := getClient()
m, err := client.GetMount(args[0])
c := getClient()
m, err := c.GetMount(context.Background(), args[0])
if err != nil {
log.Fatalf("ERROR: %v", err)
}
......@@ -413,43 +444,43 @@ func (cmd *editMountCommand) Run(args []string) {
// Only set those fields that were passed on the command line.
if cmd.fallback.IsSet() {
m.Fallback = cmd.fallback.Value()
m.FallbackPath = cmd.fallback.Value()
}
if cmd.relay.IsSet() {
setRelay(m, cmd.relay.Value())
}
if cmd.transcodingOptionsSet() && m.Transcoding == nil {
if cmd.transcodingOptionsSet() && !m.Transcode {
log.Fatal("ERROR: can't set transcoding options on a non-transcoding mount (delete and re-create)")
}
if cmd.transFormat.IsSet() {
m.Transcoding.Format = cmd.transFormat.Value()
m.TranscodeParams.Format = cmd.transFormat.Value()
}
if cmd.transSource.IsSet() {
m.Transcoding.SourceName = cmd.transSource.Value()
m.TranscodeParams.SourcePath = cmd.transSource.Value()
}
if cmd.transBitRate.IsSet() {
m.Transcoding.BitRate = cmd.transBitRate.Value()
m.TranscodeParams.BitRate = int32(cmd.transBitRate.Value())
}
if cmd.transSampleRate.IsSet() {
m.Transcoding.SampleRate = cmd.transSampleRate.Value()
m.TranscodeParams.SampleRate = int32(cmd.transSampleRate.Value())
}
if cmd.transQuality.IsSet() {
m.Transcoding.Quality = cmd.transQuality.Value()
m.TranscodeParams.Quality = float32(cmd.transQuality.Value())
}
if cmd.transChannels.IsSet() {
m.Transcoding.Channels = cmd.transChannels.Value()
m.TranscodeParams.Channels = int32(cmd.transChannels.Value())
}
if cmd.transStereoMode.IsSet() {
m.Transcoding.StereoMode = cmd.transStereoMode.Value()
m.TranscodeParams.StereoMode = cmd.transStereoMode.Value()
}
if err := m.Valid(); err != nil {
log.Fatalf("ERROR: mount configuration is invalid: %v", err)
}
if err := client.SetMount(m); err != nil {
if err := c.SetMount(context.Background(), m); err != nil {
log.Fatalf("ERROR: updating mount: %v", err)
}
......@@ -478,25 +509,25 @@ func (cmd *deleteMountCommand) Run(args []string) {
log.Fatal("Wrong number of arguments")
}
path := args[0]
client := getClient()
if !mountExists(path, client) {
c := getClient()
if !mountExists(path, c) {
log.Fatal("ERROR: mount not found")
}
if err := client.DelMount(path); err != nil {
if err := c.DeleteMount(context.Background(), path); err != nil {
log.Fatalf("ERROR: deleting mount: %v", err)
}
// Delete all the transcoding mounts that have this as a
// source.
mounts, err := client.ListMounts()
mounts, err := c.ListMounts(context.Background())
if err != nil {
log.Fatalf("ERROR: %v", err)
}
for _, m := range mounts {
if m.HasTranscoder() && m.Transcoding.SourceName == path {
if err := client.DelMount(m.Name); err != nil {
log.Printf("ERROR: deleting transcoded mount %s: %v", m.Name, err)
if m.HasTranscoder() && m.TranscodeParams.SourcePath == path {
if err := c.DeleteMount(context.Background(), m.Path); err != nil {
log.Printf("ERROR: deleting transcoded mount %s: %v", m.Path, err)
}
}
}
......@@ -526,13 +557,13 @@ func (cmd *listMountsCommand) Run(args []string) {
log.Fatal("Too many arguments")
}
mounts, err := getClient().ListMounts()
mounts, err := getClient().ListMounts(context.Background())
if err != nil {
log.Fatalf("ERROR: %v", err)
}
var names []string
for _, m := range mounts {
names = append(names, m.Name)
names = append(names, m.Path)
}
switch *outputFormat {
......@@ -571,7 +602,7 @@ func (cmd *showMountCommand) Run(args []string) {
log.Fatal("Wrong number of arguments")
}
m, err := getClient().GetMount(args[0])
m, err := getClient().GetMount(context.Background(), args[0])
if err != nil {
log.Fatalf("ERROR: %v", err)
}
......@@ -605,7 +636,7 @@ func (cmd *backupCommand) Run(args []string) {
log.Fatal("Too many arguments")
}
mounts, err := getClient().ListMounts()
mounts, err := getClient().ListMounts(context.Background())
if err != nil {
log.Fatalf("ERROR: %v", err)
}
......@@ -636,15 +667,15 @@ func (cmd *restoreCommand) Run(args []string) {
log.Fatal("Too many arguments")
}
var mounts []*autoradio.Mount
var mounts []*pb.Mount
if err := json.NewDecoder(os.Stdin).Decode(&mounts); err != nil {
log.Fatalf("ERROR: %v", err)
}
client := getClient()
c := getClient()
for _, m := range mounts {
if err := client.SetMount(m); err != nil {
log.Printf("ERROR: creating mount %s: %v", m.Name, err)
if err := c.SetMount(context.Background(), m); err != nil {
log.Printf("ERROR: creating mount %s: %v", m.Path, err)
}
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment