Skip to content

Commit

Permalink
Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasfrank committed Mar 29, 2023
1 parent 43f639d commit 691cb96
Show file tree
Hide file tree
Showing 11 changed files with 531 additions and 63 deletions.
6 changes: 6 additions & 0 deletions broker/volumebroker/api/v1alpha1/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ const (
AnnotationsAnnotation = "volumebroker.api.onmetal.de/annotations"

CreatedLabel = "volumebroker.api.onmetal.de/created"

PurposeLabel = "machinebroker.api.onmetal.de/purpose"
)

const (
VolumeEncryptionPurpose = "volume-encryption"
)

const (
Expand Down
4 changes: 4 additions & 0 deletions broker/volumebroker/apiutils/apiutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ func IsCreated(o metav1.Object) bool {
return metautils.HasLabel(o, volumebrokerv1alpha1.CreatedLabel)
}

func SetPurpose(o metav1.Object, purpose string) {
metautils.SetLabel(o, volumebrokerv1alpha1.PurposeLabel, purpose)
}

func PatchControlledBy(ctx context.Context, c client.Client, owner, controlled client.Object) error {
base := controlled.DeepCopyObject().(client.Object)
if err := ctrl.SetControllerReference(owner, controlled, c.Scheme()); err != nil {
Expand Down
8 changes: 8 additions & 0 deletions broker/volumebroker/server/volume_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func (s *Server) getOnmetalVolumeConfig(_ context.Context, volume *ori.Volume) (
Type: corev1.SecretTypeOpaque,
Data: encryption.SecretData,
}
apiutils.SetPurpose(encryptionSecret, volumebrokerv1alpha1.VolumeEncryptionPurpose)
}

var encryption *storagev1alpha1.VolumeEncryption
Expand Down Expand Up @@ -121,6 +122,13 @@ func (s *Server) createOnmetalVolume(ctx context.Context, log logr.Logger, volum
return nil
})

if volume.EncryptionSecret != nil {
log.V(1).Info("Patching encryption secret to be controlled by onmetal volume")
if err := apiutils.PatchControlledBy(ctx, s.client, volume.Volume, volume.EncryptionSecret); err != nil {
return fmt.Errorf("error patching encryption secret to be controlled by onmetal volume: %w", err)
}
}

log.V(1).Info("Patching onmetal volume as created")
if err := apiutils.PatchCreated(ctx, s.client, volume.Volume); err != nil {
return fmt.Errorf("error patching onmetal machine as created: %w", err)
Expand Down
15 changes: 0 additions & 15 deletions broker/volumebroker/server/volume_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ import (
ori "github.com/onmetal/onmetal-api/ori/apis/volume/v1alpha1"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func (s *Server) DeleteVolume(ctx context.Context, req *ori.DeleteVolumeRequest) (*ori.DeleteVolumeResponse, error) {
Expand All @@ -35,19 +33,6 @@ func (s *Server) DeleteVolume(ctx context.Context, req *ori.DeleteVolumeRequest)
return nil, err
}

if encryption := onmetalVolume.Volume.Spec.Encryption; encryption != nil {
log.V(1).Info("Deleting encryption secret")
if err := s.client.Delete(ctx, &corev1.Secret{ObjectMeta: metav1.ObjectMeta{
Name: encryption.SecretRef.Name,
Namespace: s.namespace,
}}); err != nil {
if !apierrors.IsNotFound(err) {
return nil, fmt.Errorf("error deleting onmetal encryption secret: %w", err)
}
return nil, status.Errorf(codes.NotFound, "secret %s not found", encryption.SecretRef.Name)
}
}

log.V(1).Info("Deleting volume")
if err := s.client.Delete(ctx, onmetalVolume.Volume); err != nil {
if !apierrors.IsNotFound(err) {
Expand Down
42 changes: 20 additions & 22 deletions broker/volumebroker/server/volume_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,7 @@ func (s *Server) listAggregateOnmetalVolumes(ctx context.Context) ([]AggregateOn
for i := range onmetalVolumeList.Items {
onmetalVolume := &onmetalVolumeList.Items[i]

var encryptionSecret *corev1.Secret
if encryption := onmetalVolume.Spec.Encryption; encryption != nil {
encryptionSecret, err = secretByNameGetter.Get(encryption.SecretRef.Name)
if err != nil {
return nil, fmt.Errorf("error getting onmetal encryption secret %s: %w", encryption.SecretRef.Name, err)
}
}

aggregateOnmetalVolume, err := s.aggregateOnmetalVolume(onmetalVolume, encryptionSecret, secretByNameGetter.Get)
aggregateOnmetalVolume, err := s.aggregateOnmetalVolume(onmetalVolume, secretByNameGetter.Get)
if err != nil {
return nil, fmt.Errorf("error aggregating onmetal volume %s: %w", onmetalVolume.Name, err)
}
Expand Down Expand Up @@ -117,19 +109,35 @@ func (s *Server) getOnmetalVolumeAccessSecretIfRequired(
return getSecret(secretName)
}

func (s *Server) getOnmetalVolumeEncryptionSecretIfRequired(
onmetalVolume *storagev1alpha1.Volume,
getSecret func(string) (*corev1.Secret, error),
) (*corev1.Secret, error) {
if onmetalVolume.Spec.Encryption == nil {
return nil, nil
}

secretName := onmetalVolume.Spec.Encryption.SecretRef.Name
return getSecret(secretName)
}

func (s *Server) aggregateOnmetalVolume(
onmetalVolume *storagev1alpha1.Volume,
onmetalEncryptionSecret *corev1.Secret,
getSecret func(string) (*corev1.Secret, error),
) (*AggregateOnmetalVolume, error) {
accessSecret, err := s.getOnmetalVolumeAccessSecretIfRequired(onmetalVolume, getSecret)
if err != nil {
return nil, fmt.Errorf("error getting onmetal volume access secret: %w", err)
}

encryptionSecret, err := s.getOnmetalVolumeEncryptionSecretIfRequired(onmetalVolume, getSecret)
if err != nil {
return nil, fmt.Errorf("error getting onmetal volume access secret: %w", err)
}

return &AggregateOnmetalVolume{
Volume: onmetalVolume,
EncryptionSecret: onmetalEncryptionSecret,
EncryptionSecret: encryptionSecret,
AccessSecret: accessSecret,
}, nil
}
Expand All @@ -143,17 +151,7 @@ func (s *Server) getAggregateOnmetalVolume(ctx context.Context, id string) (*Agg
return nil, status.Errorf(codes.NotFound, "volume %s not found", id)
}

onmetalEncryptionSecret := &corev1.Secret{}
if secret := onmetalVolume.Spec.Encryption; secret != nil {
if err := s.getManagedAndCreated(ctx, secret.SecretRef.Name, onmetalEncryptionSecret); err != nil {
if !apierrors.IsNotFound(err) {
return nil, fmt.Errorf("error getting onmetal encryption secret %s: %w", secret.SecretRef.Name, err)
}
return nil, status.Errorf(codes.NotFound, "encryption secret %s not found", secret.SecretRef.Name)
}
}

return s.aggregateOnmetalVolume(onmetalVolume, onmetalEncryptionSecret, s.clientGetSecretFunc(ctx))
return s.aggregateOnmetalVolume(onmetalVolume, s.clientGetSecretFunc(ctx))
}

func (s *Server) listVolumes(ctx context.Context) ([]*ori.Volume, error) {
Expand Down
29 changes: 29 additions & 0 deletions ori/apis/volume/volume.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2023 OnMetal authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package volume

import (
"context"

api "github.com/onmetal/onmetal-api/ori/apis/volume/v1alpha1"
)

type RuntimeService interface {
ListVolumes(context.Context, *api.ListVolumesRequest) (*api.ListVolumesResponse, error)
CreateVolume(context.Context, *api.CreateVolumeRequest) (*api.CreateVolumeResponse, error)
DeleteVolume(context.Context, *api.DeleteVolumeRequest) (*api.DeleteVolumeResponse, error)

ListVolumeClasses(context.Context, *api.ListVolumeClassesRequest) (*api.ListVolumeClassesResponse, error)
}
58 changes: 58 additions & 0 deletions ori/remote/volume/runtime.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2022 OnMetal authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package volume

import (
"context"
"fmt"

"github.com/onmetal/onmetal-api/ori/apis/volume"
ori "github.com/onmetal/onmetal-api/ori/apis/volume/v1alpha1"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)

type remoteRuntime struct {
client ori.VolumeRuntimeClient
}

func NewRemoteRuntime(endpoint string) (volume.RuntimeService, error) {
conn, err := grpc.Dial(endpoint,
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
return nil, fmt.Errorf("error dialing: %w", err)
}

return &remoteRuntime{
client: ori.NewVolumeRuntimeClient(conn),
}, nil
}

func (r *remoteRuntime) ListVolumes(ctx context.Context, request *ori.ListVolumesRequest) (*ori.ListVolumesResponse, error) {
return r.client.ListVolumes(ctx, request)
}

func (r *remoteRuntime) CreateVolume(ctx context.Context, request *ori.CreateVolumeRequest) (*ori.CreateVolumeResponse, error) {
return r.client.CreateVolume(ctx, request)
}

func (r *remoteRuntime) DeleteVolume(ctx context.Context, request *ori.DeleteVolumeRequest) (*ori.DeleteVolumeResponse, error) {
return r.client.DeleteVolume(ctx, request)
}

func (r *remoteRuntime) ListVolumeClasses(ctx context.Context, request *ori.ListVolumeClassesRequest) (*ori.ListVolumeClassesResponse, error) {
return r.client.ListVolumeClasses(ctx, request)
}
37 changes: 12 additions & 25 deletions ori/testing/volume/fake.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@ package volume

import (
"context"
"crypto/rand"
"encoding/hex"
"strconv"
"sync"
"time"

"github.com/onmetal/onmetal-api/broker/common/idgen"
ori "github.com/onmetal/onmetal-api/ori/apis/volume/v1alpha1"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"k8s.io/apimachinery/pkg/labels"
Expand All @@ -32,23 +31,6 @@ func filterInLabels(labelSelector, lbls map[string]string) bool {
return labels.SelectorFromSet(labelSelector).Matches(labels.Set(lbls))
}

const defaultIDLength = 63

func generateID(length int) string {
data := make([]byte, (length/2)+1)
for {
_, _ = rand.Read(data)
id := hex.EncodeToString(data)

// Truncated versions of the id should not be numerical.
if _, err := strconv.ParseInt(id[:12], 10, 64); err != nil {
continue
}

return id[:length]
}
}

type FakeVolume struct {
ori.Volume
}
Expand All @@ -60,12 +42,16 @@ type FakeVolumeClass struct {
type FakeRuntimeService struct {
sync.Mutex

idGen idgen.IDGen

Volumes map[string]*FakeVolume
VolumeClasses map[string]*FakeVolumeClass
}

func NewFakeRuntimeService() *FakeRuntimeService {
return &FakeRuntimeService{
idGen: idgen.Default,

Volumes: make(map[string]*FakeVolume),
VolumeClasses: make(map[string]*FakeVolumeClass),
}
Expand All @@ -91,7 +77,7 @@ func (r *FakeRuntimeService) SetVolumeClasses(volumeClasses []*FakeVolumeClass)
}
}

func (r *FakeRuntimeService) ListVolumes(ctx context.Context, req *ori.ListVolumesRequest) (*ori.ListVolumesResponse, error) {
func (r *FakeRuntimeService) ListVolumes(ctx context.Context, req *ori.ListVolumesRequest, opts ...grpc.CallOption) (*ori.ListVolumesResponse, error) {
r.Lock()
defer r.Unlock()

Expand All @@ -114,13 +100,14 @@ func (r *FakeRuntimeService) ListVolumes(ctx context.Context, req *ori.ListVolum
return &ori.ListVolumesResponse{Volumes: res}, nil
}

func (r *FakeRuntimeService) CreateVolume(ctx context.Context, req *ori.CreateVolumeRequest) (*ori.CreateVolumeResponse, error) {
func (r *FakeRuntimeService) CreateVolume(ctx context.Context, req *ori.CreateVolumeRequest, opts ...grpc.CallOption) (*ori.CreateVolumeResponse, error) {
r.Lock()
defer r.Unlock()

volume := *req.Volume
volume.Metadata.Id = generateID(defaultIDLength)
volume.Metadata.Id = r.idGen.Generate()
volume.Metadata.CreatedAt = time.Now().UnixNano()
volume.Status = &ori.VolumeStatus{}

r.Volumes[volume.Metadata.Id] = &FakeVolume{
Volume: volume,
Expand All @@ -131,7 +118,7 @@ func (r *FakeRuntimeService) CreateVolume(ctx context.Context, req *ori.CreateVo
}, nil
}

func (r *FakeRuntimeService) DeleteVolume(ctx context.Context, req *ori.DeleteVolumeRequest) (*ori.DeleteVolumeResponse, error) {
func (r *FakeRuntimeService) DeleteVolume(ctx context.Context, req *ori.DeleteVolumeRequest, opts ...grpc.CallOption) (*ori.DeleteVolumeResponse, error) {
r.Lock()
defer r.Unlock()

Expand All @@ -144,7 +131,7 @@ func (r *FakeRuntimeService) DeleteVolume(ctx context.Context, req *ori.DeleteVo
return &ori.DeleteVolumeResponse{}, nil
}

func (r *FakeRuntimeService) ListVolumeClasses(ctx context.Context, req *ori.ListVolumeClassesRequest) (*ori.ListVolumeClassesResponse, error) {
func (r *FakeRuntimeService) ListVolumeClasses(ctx context.Context, req *ori.ListVolumeClassesRequest, opts ...grpc.CallOption) (*ori.ListVolumeClassesResponse, error) {
r.Lock()
defer r.Unlock()

Expand Down
Loading

0 comments on commit 691cb96

Please sign in to comment.