Add Secrets() (#29)
This adds the `Secrets()` method, used to retrieve all secrets managed by the libvirt daemon.
This commit is contained in:
		| @@ -39,6 +39,7 @@ before_script: | |||||||
|   - sudo virsh define .travis/test-domain.xml |   - sudo virsh define .travis/test-domain.xml | ||||||
|   - sudo virsh start test |   - sudo virsh start test | ||||||
|   - sudo virsh pool-create .travis/test-pool.xml |   - sudo virsh pool-create .travis/test-pool.xml | ||||||
|  |   - sudo virsh secret-define .travis/test-secret.xml | ||||||
|  |  | ||||||
| script: | script: | ||||||
|   - ./scripts/licensecheck.sh |   - ./scripts/licensecheck.sh | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								.travis/test-secret.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.travis/test-secret.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | <secret ephemeral='no' private='yes'> | ||||||
|  |    <description>test</description> | ||||||
|  |    <uuid>19fdc2f2-fa64-46f3-bacf-42a8aafca6dd</uuid> | ||||||
|  |    <usage type='volume'> | ||||||
|  |       <volume>/tmp</volume> | ||||||
|  |    </usage> | ||||||
|  | </secret> | ||||||
| @@ -51,6 +51,7 @@ const ( | |||||||
| 	ProcDomainDestroyFlags         = 234 | 	ProcDomainDestroyFlags         = 234 | ||||||
| 	ProcConnectListAllDomains      = 273 | 	ProcConnectListAllDomains      = 273 | ||||||
| 	ProcConnectListAllStoragePools = 281 | 	ProcConnectListAllStoragePools = 281 | ||||||
|  | 	ProcConnectListAllSecrets      = 287 | ||||||
| 	ProcMigratePerformParams       = 305 | 	ProcMigratePerformParams       = 305 | ||||||
| 	ProcDomainDefineXMLFlags       = 350 | 	ProcDomainDefineXMLFlags       = 350 | ||||||
| ) | ) | ||||||
|   | |||||||
							
								
								
									
										60
									
								
								libvirt.go
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								libvirt.go
									
									
									
									
									
								
							| @@ -70,6 +70,13 @@ type DomainEvent struct { | |||||||
| 	Details      []byte | 	Details      []byte | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Secret represents a secret managed by the libvirt daemon. | ||||||
|  | type Secret struct { | ||||||
|  | 	UUID      [constants.UUIDSize]byte | ||||||
|  | 	UsageType SecretUsageType | ||||||
|  | 	UsageID   string | ||||||
|  | } | ||||||
|  |  | ||||||
| // StoragePool represents a storage pool as seen by libvirt. | // StoragePool represents a storage pool as seen by libvirt. | ||||||
| type StoragePool struct { | type StoragePool struct { | ||||||
| 	Name string | 	Name string | ||||||
| @@ -209,6 +216,20 @@ const ( | |||||||
| 	DomainStateLast | 	DomainStateLast | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | // SecretUsageType specifies the usage for a libvirt secret. | ||||||
|  | type SecretUsageType uint32 | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	// SecretUsageTypeNone specifies no usage. | ||||||
|  | 	SecretUsageTypeNone SecretUsageType = iota | ||||||
|  | 	// SecretUsageTypeVolume specifies a volume secret. | ||||||
|  | 	SecretUsageTypeVolume | ||||||
|  | 	// SecretUsageTypeCeph specifies secrets for ceph devices. | ||||||
|  | 	SecretUsageTypeCeph | ||||||
|  | 	// SecretUsageTypeISCSI specifies secrets for ISCSI devices. | ||||||
|  | 	SecretUsageTypeISCSI | ||||||
|  | ) | ||||||
|  |  | ||||||
| // StoragePoolsFlags specifies storage pools to list. | // StoragePoolsFlags specifies storage pools to list. | ||||||
| type StoragePoolsFlags uint32 | type StoragePoolsFlags uint32 | ||||||
|  |  | ||||||
| @@ -572,6 +593,45 @@ func (l *Libvirt) Run(dom string, cmd []byte) ([]byte, error) { | |||||||
| 	return bytes.TrimRight(data[4:], "\x00"), nil | 	return bytes.TrimRight(data[4:], "\x00"), nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Secrets returns all secrets managed by the libvirt daemon. | ||||||
|  | func (l *Libvirt) Secrets() ([]Secret, error) { | ||||||
|  | 	req := struct { | ||||||
|  | 		NeedResults uint32 | ||||||
|  | 		Flags       uint32 | ||||||
|  | 	}{ | ||||||
|  | 		NeedResults: 1, | ||||||
|  | 		Flags:       0, // unused per libvirt source, callers should pass 0 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	buf, err := encode(&req) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	resp, err := l.request(constants.ProcConnectListAllSecrets, constants.ProgramRemote, &buf) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	r := <-resp | ||||||
|  | 	if r.Status != StatusOK { | ||||||
|  | 		return nil, decodeError(r.Payload) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	result := struct { | ||||||
|  | 		Secrets []Secret | ||||||
|  | 		Count   uint32 | ||||||
|  | 	}{} | ||||||
|  |  | ||||||
|  | 	dec := xdr.NewDecoder(bytes.NewReader(r.Payload)) | ||||||
|  | 	_, err = dec.Decode(&result) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return result.Secrets, nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // StoragePool returns the storage pool associated with the provided name. | // StoragePool returns the storage pool associated with the provided name. | ||||||
| // An error is returned if the requested storage pool is not found. | // An error is returned if the requested storage pool is not found. | ||||||
| func (l *Libvirt) StoragePool(name string) (*StoragePool, error) { | func (l *Libvirt) StoragePool(name string) (*StoragePool, error) { | ||||||
|   | |||||||
| @@ -21,6 +21,8 @@ import ( | |||||||
| 	"net" | 	"net" | ||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/digitalocean/go-libvirt/internal/constants" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const testAddr = "127.0.0.1:16509" | const testAddr = "127.0.0.1:16509" | ||||||
| @@ -70,6 +72,47 @@ func TestCapabilities(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestSecretsIntegration(t *testing.T) { | ||||||
|  | 	l := New(testConn(t)) | ||||||
|  | 	defer l.Disconnect() | ||||||
|  |  | ||||||
|  | 	if err := l.Connect(); err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	secrets, err := l.Secrets() | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	wantLen := 1 | ||||||
|  | 	gotLen := len(secrets) | ||||||
|  | 	if gotLen != wantLen { | ||||||
|  | 		t.Fatal("expected %d secrets, got %d", wantLen, gotLen) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	s := secrets[0] | ||||||
|  |  | ||||||
|  | 	wantType := SecretUsageTypeVolume | ||||||
|  | 	if s.UsageType != wantType { | ||||||
|  | 		t.Error("expected usage type: %d, got %d", wantType, s.UsageType) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	wantID := "/tmp" | ||||||
|  | 	if s.UsageID != wantID { | ||||||
|  | 		t.Error("expected usage id: %q, got %q", wantID, s.UsageID) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// 19fdc2f2-fa64-46f3-bacf-42a8aafca6dd | ||||||
|  | 	wantUUID := [constants.UUIDSize]byte{ | ||||||
|  | 		0x19, 0xfd, 0xc2, 0xf2, 0xfa, 0x64, 0x46, 0xf3, | ||||||
|  | 		0xba, 0xcf, 0x42, 0xa8, 0xaa, 0xfc, 0xa6, 0xdd, | ||||||
|  | 	} | ||||||
|  | 	if s.UUID != wantUUID { | ||||||
|  | 		t.Errorf("expected UUID %q, got %q", wantUUID, s.UUID) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func TestStoragePoolIntegration(t *testing.T) { | func TestStoragePoolIntegration(t *testing.T) { | ||||||
| 	l := New(testConn(t)) | 	l := New(testConn(t)) | ||||||
| 	defer l.Disconnect() | 	defer l.Disconnect() | ||||||
|   | |||||||
| @@ -221,6 +221,42 @@ func TestRunFail(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestSecrets(t *testing.T) { | ||||||
|  | 	conn := libvirttest.New() | ||||||
|  | 	l := New(conn) | ||||||
|  |  | ||||||
|  | 	secrets, err := l.Secrets() | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	wantLen := 1 | ||||||
|  | 	gotLen := len(secrets) | ||||||
|  | 	if gotLen != wantLen { | ||||||
|  | 		t.Fatalf("expected %d secrets, got %d", wantLen, gotLen) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	s := secrets[0] | ||||||
|  | 	wantType := SecretUsageTypeVolume | ||||||
|  | 	if s.UsageType != wantType { | ||||||
|  | 		t.Errorf("expected usage type %d, got %d", wantType, s.UsageType) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	wantID := "/tmp" | ||||||
|  | 	if s.UsageID != wantID { | ||||||
|  | 		t.Errorf("expected usage id %q, got %q", wantID, s.UsageID) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// 19fdc2f2-fa64-46f3-bacf-42a8aafca6dd | ||||||
|  | 	wantUUID := [constants.UUIDSize]byte{ | ||||||
|  | 		0x19, 0xfd, 0xc2, 0xf2, 0xfa, 0x64, 0x46, 0xf3, | ||||||
|  | 		0xba, 0xcf, 0x42, 0xa8, 0xaa, 0xfc, 0xa6, 0xdd, | ||||||
|  | 	} | ||||||
|  | 	if s.UUID != wantUUID { | ||||||
|  | 		t.Errorf("expected UUID %q, got %q", wantUUID, s.UUID) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func TestStoragePool(t *testing.T) { | func TestStoragePool(t *testing.T) { | ||||||
| 	conn := libvirttest.New() | 	conn := libvirttest.New() | ||||||
| 	l := New(conn) | 	l := New(conn) | ||||||
|   | |||||||
| @@ -217,6 +217,33 @@ var testDomainStateReply = []byte{ | |||||||
| 	0x00, 0x00, 0x00, 0x01, // reason | 	0x00, 0x00, 0x00, 0x01, // reason | ||||||
| } | } | ||||||
|  |  | ||||||
|  | var testSecretsReply = []byte{ | ||||||
|  | 	0x00, 0x00, 0x00, 0x40, // length | ||||||
|  | 	0x20, 0x00, 0x80, 0x86, // program | ||||||
|  | 	0x00, 0x00, 0x00, 0x01, // version | ||||||
|  | 	0x00, 0x00, 0x01, 0x1f, // procedure | ||||||
|  | 	0x00, 0x00, 0x00, 0x01, // type | ||||||
|  | 	0x00, 0x00, 0x00, 0x00, // serial | ||||||
|  | 	0x00, 0x00, 0x00, 0x00, // status | ||||||
|  |  | ||||||
|  | 	// list of secrets | ||||||
|  | 	0x00, 0x00, 0x00, 0x01, | ||||||
|  |  | ||||||
|  | 	// first secret | ||||||
|  | 	// UUID: 19fdc2f2fa64-46f3bacf42a8aafca6dd | ||||||
|  | 	0x19, 0xfd, 0xc2, 0xf2, 0xfa, 0x64, 0x46, 0xf3, | ||||||
|  | 	0xba, 0xcf, 0x42, 0xa8, 0xaa, 0xfc, 0xa6, 0xdd, | ||||||
|  |  | ||||||
|  | 	// usage type: (1, volume) | ||||||
|  | 	0x00, 0x00, 0x00, 0x01, | ||||||
|  |  | ||||||
|  | 	// usage id: "/tmp" | ||||||
|  | 	0x00, 0x00, 0x00, 0x04, 0x2f, 0x74, 0x6d, 0x70, | ||||||
|  |  | ||||||
|  | 	// end of secrets | ||||||
|  | 	0x00, 0x00, 0x00, 0x01, | ||||||
|  | } | ||||||
|  |  | ||||||
| var testStoragePoolLookup = []byte{ | var testStoragePoolLookup = []byte{ | ||||||
| 	0x00, 0x00, 0x00, 0x38, // length | 	0x00, 0x00, 0x00, 0x38, // length | ||||||
| 	0x20, 0x00, 0x80, 0x86, // program | 	0x20, 0x00, 0x80, 0x86, // program | ||||||
| @@ -377,6 +404,8 @@ func (m *MockLibvirt) handleRemote(procedure uint32, conn net.Conn) { | |||||||
| 		conn.Write(m.reply(testDomainsReply)) | 		conn.Write(m.reply(testDomainsReply)) | ||||||
| 	case constants.ProcConnectListAllStoragePools: | 	case constants.ProcConnectListAllStoragePools: | ||||||
| 		conn.Write(m.reply(testListPoolsReply)) | 		conn.Write(m.reply(testListPoolsReply)) | ||||||
|  | 	case constants.ProcConnectListAllSecrets: | ||||||
|  | 		conn.Write(m.reply(testSecretsReply)) | ||||||
| 	case constants.ProcDomainGetState: | 	case constants.ProcDomainGetState: | ||||||
| 		conn.Write(m.reply(testDomainStateReply)) | 		conn.Write(m.reply(testDomainStateReply)) | ||||||
| 	case constants.ProcDomainMigrateSetMaxSpeed: | 	case constants.ProcDomainMigrateSetMaxSpeed: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user