Repository: clouditor/clouditor
Pull request #479 (2022-02-02 20:23:54)

Implementing write access to metric database via REST API
This adds two new RPC calls to create and update metrics via gRPC. They are also exposed via the REST API

codecov[bot]: # [Codecov](https://codecov.io/gh/clouditor/clouditor/pull/479?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor) Report
> Merging [#479](https://codecov.io/gh/clouditor/clouditor/pull/479?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor) (66499c8) into [main](https://codecov.io/gh/clouditor/clouditor/commit/ef02d75a70ddb4d77d118f8e7689f534dc7681ef?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor) (ef02d75) will **decrease** coverage by `0.23%`.
> The diff coverage is `66.25%`.

[![Impacted file tree graph](https://codecov.io/gh/clouditor/clouditor/pull/479/graphs/tree.svg?width=650&height=150&src=pr&token=syrXsw5LTX&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor)](https://codecov.io/gh/clouditor/clouditor/pull/479?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor)

```diff
@@            Coverage Diff             @@
##             main     #479      +/-   ##
==========================================
- Coverage   76.36%   76.12%   -0.24%     
==========================================
  Files          44       45       +1     
  Lines        3795     3845      +50     
==========================================
+ Hits         2898     2927      +29     
- Misses        766      780      +14     
- Partials      131      138       +7     
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `76.12% <66.25%> (-0.24%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/clouditor/clouditor/pull/479?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor) | Coverage Δ | |
|---|---|---|
| [api/assessment/assessment.go](https://codecov.io/gh/clouditor/clouditor/pull/479/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor#diff-YXBpL2Fzc2Vzc21lbnQvYXNzZXNzbWVudC5nbw==) | `88.46% <ø> (ø)` | |
| [service/orchestrator/orchestrator.go](https://codecov.io/gh/clouditor/clouditor/pull/479/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor#diff-c2VydmljZS9vcmNoZXN0cmF0b3Ivb3JjaGVzdHJhdG9yLmdv) | `85.47% <ø> (+1.11%)` | :arrow_up: |
| [api/assessment/metric.go](https://codecov.io/gh/clouditor/clouditor/pull/479/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor#diff-YXBpL2Fzc2Vzc21lbnQvbWV0cmljLmdv) | `62.16% <43.75%> (-14.03%)` | :arrow_down: |
| [service/orchestrator/metrics.go](https://codecov.io/gh/clouditor/clouditor/pull/479/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor#diff-c2VydmljZS9vcmNoZXN0cmF0b3IvbWV0cmljcy5nbw==) | `71.87% <71.87%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/clouditor/clouditor/pull/479?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/clouditor/clouditor/pull/479?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor). Last update [ef02d75...66499c8](https://codecov.io/gh/clouditor/clouditor/pull/479?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=clouditor).


Patch:
diff --git a/api/assessment/assessment.go b/api/assessment/assessment.go
index 0f2a0c34..adfe3342 100644
--- a/api/assessment/assessment.go
+++ b/api/assessment/assessment.go
@@ -38,7 +38,7 @@ var (
 	ErrEvidenceIdInvalidFormat               = errors.New("evidence id not in expected format (UUID) or missing")
 	ErrTimestampMissing                      = errors.New("timestamp in assessment result is missing")
 	ErrResourceIdMissing                     = errors.New("resource id in assessment result is missing")
-	ErrMetricIdMissing                       = errors.New("metric id in assessment result is missing")
+	ErrMetricIdMissing                       = errors.New("metric id is missing")
 	ErrMetricConfigurationMissing            = errors.New("metric configuration in assessment result is missing")
 	ErrMetricConfigurationOperatorMissing    = errors.New("operator in metric data is missing")
 	ErrMetricConfigurationTargetValueMissing = errors.New("target value in metric data is missing")
diff --git a/api/assessment/metric.go b/api/assessment/metric.go
index 971f49ae..ea33fc5a 100644
--- a/api/assessment/metric.go
+++ b/api/assessment/metric.go
@@ -2,10 +2,16 @@ package assessment
 
 import (
 	"encoding/json"
+	"errors"
+)
+
+var (
+	ErrMetricNameMissing = errors.New("metric name is missing")
+	ErrMetricEmpty       = errors.New("metric is missing or empty")
 )
 
 func (r *Range) UnmarshalJSON(b []byte) (err error) {
-	// check for the different range types
+	// Check for the different range types
 	var (
 		r1 Range_AllowedValues
 		r2 Range_Order
@@ -29,3 +35,37 @@ func (r *Range) UnmarshalJSON(b []byte) (err error) {
 
 	return
 }
+
+// MetricValidationOption is a function-style option to fine-tune metric validation.
+type MetricValidationOption func(*Metric) error
+
+// WithMetricRequiresId is a validation option that specifies that Id must not be empty.
+func WithMetricRequiresId() MetricValidationOption {
+	return func(m *Metric) error {
+		if m.Id == "" {
+			return ErrMetricIdMissing
+		}
+		return nil
+	}
+}
+
+// Validate validates the metric according to several required fields.
+func (m *Metric) Validate(opts ...MetricValidationOption) (err error) {
+	if m == nil {
+		return ErrMetricEmpty
+	}
+
+	// Check for extra validation options
+	for _, o := range opts {
+		err = o(m)
+		if err != nil {
+			return err
+		}
+	}
+
+	if m.Name == "" {
+		return ErrMetricNameMissing
+	}
+
+	return nil
+}
diff --git a/api/orchestrator/orchestrator.pb.go b/api/orchestrator/orchestrator.pb.go
index 72e91a44..74472bc3 100644
--- a/api/orchestrator/orchestrator.pb.go
+++ b/api/orchestrator/orchestrator.pb.go
@@ -425,16 +425,16 @@ func (*StoreAssessmentResultResponse) Descriptor() ([]byte, []int) {
 	return file_orchestrator_proto_rawDescGZIP(), []int{7}
 }
 
-type GetMetricsRequest struct {
+type CreateMetricRequest struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	MetricId string `protobuf:"bytes,1,opt,name=metric_id,json=metricId,proto3" json:"metric_id,omitempty"`
+	Metric *assessment.Metric `protobuf:"bytes,1,opt,name=metric,proto3" json:"metric,omitempty"`
 }
 
-func (x *GetMetricsRequest) Reset() {
-	*x = GetMetricsRequest{}
+func (x *CreateMetricRequest) Reset() {
+	*x = CreateMetricRequest{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_orchestrator_proto_msgTypes[8]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -442,13 +442,13 @@ func (x *GetMetricsRequest) Reset() {
 	}
 }
 
-func (x *GetMetricsRequest) String() string {
+func (x *CreateMetricRequest) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*GetMetricsRequest) ProtoMessage() {}
+func (*CreateMetricRequest) ProtoMessage() {}
 
-func (x *GetMetricsRequest) ProtoReflect() protoreflect.Message {
+func (x *CreateMetricRequest) ProtoReflect() protoreflect.Message {
 	mi := &file_orchestrator_proto_msgTypes[8]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -460,12 +460,114 @@ func (x *GetMetricsRequest) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use GetMetricsRequest.ProtoReflect.Descriptor instead.
-func (*GetMetricsRequest) Descriptor() ([]byte, []int) {
+// Deprecated: Use CreateMetricRequest.ProtoReflect.Descriptor instead.
+func (*CreateMetricRequest) Descriptor() ([]byte, []int) {
 	return file_orchestrator_proto_rawDescGZIP(), []int{8}
 }
 
-func (x *GetMetricsRequest) GetMetricId() string {
+func (x *CreateMetricRequest) GetMetric() *assessment.Metric {
+	if x != nil {
+		return x.Metric
+	}
+	return nil
+}
+
+type UpdateMetricRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	MetricId string             `protobuf:"bytes,1,opt,name=metric_id,json=metricId,proto3" json:"metric_id,omitempty"`
+	Metric   *assessment.Metric `protobuf:"bytes,2,opt,name=metric,proto3" json:"metric,omitempty"`
+}
+
+func (x *UpdateMetricRequest) Reset() {
+	*x = UpdateMetricRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_orchestrator_proto_msgTypes[9]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *UpdateMetricRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*UpdateMetricRequest) ProtoMessage() {}
+
+func (x *UpdateMetricRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_orchestrator_proto_msgTypes[9]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use UpdateMetricRequest.ProtoReflect.Descriptor instead.
+func (*UpdateMetricRequest) Descriptor() ([]byte, []int) {
+	return file_orchestrator_proto_rawDescGZIP(), []int{9}
+}
+
+func (x *UpdateMetricRequest) GetMetricId() string {
+	if x != nil {
+		return x.MetricId
+	}
+	return ""
+}
+
+func (x *UpdateMetricRequest) GetMetric() *assessment.Metric {
+	if x != nil {
+		return x.Metric
+	}
+	return nil
+}
+
+type GetMetricRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	MetricId string `protobuf:"bytes,1,opt,name=metric_id,json=metricId,proto3" json:"metric_id,omitempty"`
+}
+
+func (x *GetMetricRequest) Reset() {
+	*x = GetMetricRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_orchestrator_proto_msgTypes[10]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *GetMetricRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetMetricRequest) ProtoMessage() {}
+
+func (x *GetMetricRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_orchestrator_proto_msgTypes[10]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetMetricRequest.ProtoReflect.Descriptor instead.
+func (*GetMetricRequest) Descriptor() ([]byte, []int) {
+	return file_orchestrator_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *GetMetricRequest) GetMetricId() string {
 	if x != nil {
 		return x.MetricId
 	}
@@ -481,7 +583,7 @@ type ListMetricsRequest struct {
 func (x *ListMetricsRequest) Reset() {
 	*x = ListMetricsRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_orchestrator_proto_msgTypes[9]
+		mi := &file_orchestrator_proto_msgTypes[11]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -494,7 +596,7 @@ func (x *ListMetricsRequest) String() string {
 func (*ListMetricsRequest) ProtoMessage() {}
 
 func (x *ListMetricsRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_orchestrator_proto_msgTypes[9]
+	mi := &file_orchestrator_proto_msgTypes[11]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -507,7 +609,7 @@ func (x *ListMetricsRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ListMetricsRequest.ProtoReflect.Descriptor instead.
 func (*ListMetricsRequest) Descriptor() ([]byte, []int) {
-	return file_orchestrator_proto_rawDescGZIP(), []int{9}
+	return file_orchestrator_proto_rawDescGZIP(), []int{11}
 }
 
 type ListMetricsResponse struct {
@@ -521,7 +623,7 @@ type ListMetricsResponse struct {
 func (x *ListMetricsResponse) Reset() {
 	*x = ListMetricsResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_orchestrator_proto_msgTypes[10]
+		mi := &file_orchestrator_proto_msgTypes[12]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -534,7 +636,7 @@ func (x *ListMetricsResponse) String() string {
 func (*ListMetricsResponse) ProtoMessage() {}
 
 func (x *ListMetricsResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_orchestrator_proto_msgTypes[10]
+	mi := &file_orchestrator_proto_msgTypes[12]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -547,7 +649,7 @@ func (x *ListMetricsResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ListMetricsResponse.ProtoReflect.Descriptor instead.
 func (*ListMetricsResponse) Descriptor() ([]byte, []int) {
-	return file_orchestrator_proto_rawDescGZIP(), []int{10}
+	return file_orchestrator_proto_rawDescGZIP(), []int{12}
 }
 
 func (x *ListMetricsResponse) GetMetrics() []*assessment.Metric {
@@ -568,7 +670,7 @@ type GetCloudServiceRequest struct {
 func (x *GetCloudServiceRequest) Reset() {
 	*x = GetCloudServiceRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_orchestrator_proto_msgTypes[11]
+		mi := &file_orchestrator_proto_msgTypes[13]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -581,7 +683,7 @@ func (x *GetCloudServiceRequest) String() string {
 func (*GetCloudServiceRequest) ProtoMessage() {}
 
 func (x *GetCloudServiceRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_orchestrator_proto_msgTypes[11]
+	mi := &file_orchestrator_proto_msgTypes[13]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -594,7 +696,7 @@ func (x *GetCloudServiceRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use GetCloudServiceRequest.ProtoReflect.Descriptor instead.
 func (*GetCloudServiceRequest) Descriptor() ([]byte, []int) {
-	return file_orchestrator_proto_rawDescGZIP(), []int{11}
+	return file_orchestrator_proto_rawDescGZIP(), []int{13}
 }
 
 func (x *GetCloudServiceRequest) GetServiceId() string {
@@ -615,7 +717,7 @@ type RegisterCloudServiceRequest struct {
 func (x *RegisterCloudServiceRequest) Reset() {
 	*x = RegisterCloudServiceRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_orchestrator_proto_msgTypes[12]
+		mi := &file_orchestrator_proto_msgTypes[14]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -628,7 +730,7 @@ func (x *RegisterCloudServiceRequest) String() string {
 func (*RegisterCloudServiceRequest) ProtoMessage() {}
 
 func (x *RegisterCloudServiceRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_orchestrator_proto_msgTypes[12]
+	mi := &file_orchestrator_proto_msgTypes[14]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -641,7 +743,7 @@ func (x *RegisterCloudServiceRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use RegisterCloudServiceRequest.ProtoReflect.Descriptor instead.
 func (*RegisterCloudServiceRequest) Descriptor() ([]byte, []int) {
-	return file_orchestrator_proto_rawDescGZIP(), []int{12}
+	return file_orchestrator_proto_rawDescGZIP(), []int{14}
 }
 
 func (x *RegisterCloudServiceRequest) GetService() *CloudService {
@@ -663,7 +765,7 @@ type UpdateCloudServiceRequest struct {
 func (x *UpdateCloudServiceRequest) Reset() {
 	*x = UpdateCloudServiceRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_orchestrator_proto_msgTypes[13]
+		mi := &file_orchestrator_proto_msgTypes[15]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -676,7 +778,7 @@ func (x *UpdateCloudServiceRequest) String() string {
 func (*UpdateCloudServiceRequest) ProtoMessage() {}
 
 func (x *UpdateCloudServiceRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_orchestrator_proto_msgTypes[13]
+	mi := &file_orchestrator_proto_msgTypes[15]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -689,7 +791,7 @@ func (x *UpdateCloudServiceRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use UpdateCloudServiceRequest.ProtoReflect.Descriptor instead.
 func (*UpdateCloudServiceRequest) Descriptor() ([]byte, []int) {
-	return file_orchestrator_proto_rawDescGZIP(), []int{13}
+	return file_orchestrator_proto_rawDescGZIP(), []int{15}
 }
 
 func (x *UpdateCloudServiceRequest) GetServiceId() string {
@@ -717,7 +819,7 @@ type RemoveCloudServiceRequest struct {
 func (x *RemoveCloudServiceRequest) Reset() {
 	*x = RemoveCloudServiceRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_orchestrator_proto_msgTypes[14]
+		mi := &file_orchestrator_proto_msgTypes[16]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -730,7 +832,7 @@ func (x *RemoveCloudServiceRequest) String() string {
 func (*RemoveCloudServiceRequest) ProtoMessage() {}
 
 func (x *RemoveCloudServiceRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_orchestrator_proto_msgTypes[14]
+	mi := &file_orchestrator_proto_msgTypes[16]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -743,7 +845,7 @@ func (x *RemoveCloudServiceRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use RemoveCloudServiceRequest.ProtoReflect.Descriptor instead.
 func (*RemoveCloudServiceRequest) Descriptor() ([]byte, []int) {
-	return file_orchestrator_proto_rawDescGZIP(), []int{14}
+	return file_orchestrator_proto_rawDescGZIP(), []int{16}
 }
 
 func (x *RemoveCloudServiceRequest) GetServiceId() string {
@@ -762,7 +864,7 @@ type ListCloudServicesRequest struct {
 func (x *ListCloudServicesRequest) Reset() {
 	*x = ListCloudServicesRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_orchestrator_proto_msgTypes[15]
+		mi := &file_orchestrator_proto_msgTypes[17]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -775,7 +877,7 @@ func (x *ListCloudServicesRequest) String() string {
 func (*ListCloudServicesRequest) ProtoMessage() {}
 
 func (x *ListCloudServicesRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_orchestrator_proto_msgTypes[15]
+	mi := &file_orchestrator_proto_msgTypes[17]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -788,7 +890,7 @@ func (x *ListCloudServicesRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ListCloudServicesRequest.ProtoReflect.Descriptor instead.
 func (*ListCloudServicesRequest) Descriptor() ([]byte, []int) {
-	return file_orchestrator_proto_rawDescGZIP(), []int{15}
+	return file_orchestrator_proto_rawDescGZIP(), []int{17}
 }
 
 type ListCloudServicesResponse struct {
@@ -802,7 +904,7 @@ type ListCloudServicesResponse struct {
 func (x *ListCloudServicesResponse) Reset() {
 	*x = ListCloudServicesResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_orchestrator_proto_msgTypes[16]
+		mi := &file_orchestrator_proto_msgTypes[18]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -815,7 +917,7 @@ func (x *ListCloudServicesResponse) String() string {
 func (*ListCloudServicesResponse) ProtoMessage() {}
 
 func (x *ListCloudServicesResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_orchestrator_proto_msgTypes[16]
+	mi := &file_orchestrator_proto_msgTypes[18]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -828,7 +930,7 @@ func (x *ListCloudServicesResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ListCloudServicesResponse.ProtoReflect.Descriptor instead.
 func (*ListCloudServicesResponse) Descriptor() ([]byte, []int) {
-	return file_orchestrator_proto_rawDescGZIP(), []int{16}
+	return file_orchestrator_proto_rawDescGZIP(), []int{18}
 }
 
 func (x *ListCloudServicesResponse) GetServices() []*CloudService {
@@ -850,7 +952,7 @@ type GetMetricConfigurationRequest struct {
 func (x *GetMetricConfigurationRequest) Reset() {
 	*x = GetMetricConfigurationRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_orchestrator_proto_msgTypes[17]
+		mi := &file_orchestrator_proto_msgTypes[19]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -863,7 +965,7 @@ func (x *GetMetricConfigurationRequest) String() string {
 func (*GetMetricConfigurationRequest) ProtoMessage() {}
 
 func (x *GetMetricConfigurationRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_orchestrator_proto_msgTypes[17]
+	mi := &file_orchestrator_proto_msgTypes[19]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -876,7 +978,7 @@ func (x *GetMetricConfigurationRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use GetMetricConfigurationRequest.ProtoReflect.Descriptor instead.
 func (*GetMetricConfigurationRequest) Descriptor() ([]byte, []int) {
-	return file_orchestrator_proto_rawDescGZIP(), []int{17}
+	return file_orchestrator_proto_rawDescGZIP(), []int{19}
 }
 
 func (x *GetMetricConfigurationRequest) GetServiceId() string {
@@ -904,7 +1006,7 @@ type ListMetricConfigurationRequest struct {
 func (x *ListMetricConfigurationRequest) Reset() {
 	*x = ListMetricConfigurationRequest{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_orchestrator_proto_msgTypes[18]
+		mi := &file_orchestrator_proto_msgTypes[20]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -917,7 +1019,7 @@ func (x *ListMetricConfigurationRequest) String() string {
 func (*ListMetricConfigurationRequest) ProtoMessage() {}
 
 func (x *ListMetricConfigurationRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_orchestrator_proto_msgTypes[18]
+	mi := &file_orchestrator_proto_msgTypes[20]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -930,7 +1032,7 @@ func (x *ListMetricConfigurationRequest) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ListMetricConfigurationRequest.ProtoReflect.Descriptor instead.
 func (*ListMetricConfigurationRequest) Descriptor() ([]byte, []int) {
-	return file_orchestrator_proto_rawDescGZIP(), []int{18}
+	return file_orchestrator_proto_rawDescGZIP(), []int{20}
 }
 
 func (x *ListMetricConfigurationRequest) GetServiceId() string {
@@ -952,7 +1054,7 @@ type ListMetricConfigurationResponse struct {
 func (x *ListMetricConfigurationResponse) Reset() {
 	*x = ListMetricConfigurationResponse{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_orchestrator_proto_msgTypes[19]
+		mi := &file_orchestrator_proto_msgTypes[21]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -965,7 +1067,7 @@ func (x *ListMetricConfigurationResponse) String() string {
 func (*ListMetricConfigurationResponse) ProtoMessage() {}
 
 func (x *ListMetricConfigurationResponse) ProtoReflect() protoreflect.Message {
-	mi := &file_orchestrator_proto_msgTypes[19]
+	mi := &file_orchestrator_proto_msgTypes[21]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -978,7 +1080,7 @@ func (x *ListMetricConfigurationResponse) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use ListMetricConfigurationResponse.ProtoReflect.Descriptor instead.
 func (*ListMetricConfigurationResponse) Descriptor() ([]byte, []int) {
-	return file_orchestrator_proto_rawDescGZIP(), []int{19}
+	return file_orchestrator_proto_rawDescGZIP(), []int{21}
 }
 
 func (x *ListMetricConfigurationResponse) GetConfigurations() map[string]*assessment.MetricConfiguration {
@@ -1005,7 +1107,7 @@ type AssessmentTool struct {
 func (x *AssessmentTool) Reset() {
 	*x = AssessmentTool{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_orchestrator_proto_msgTypes[20]
+		mi := &file_orchestrator_proto_msgTypes[22]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1018,7 +1120,7 @@ func (x *AssessmentTool) String() string {
 func (*AssessmentTool) ProtoMessage() {}
 
 func (x *AssessmentTool) ProtoReflect() protoreflect.Message {
-	mi := &file_orchestrator_proto_msgTypes[20]
+	mi := &file_orchestrator_proto_msgTypes[22]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1031,7 +1133,7 @@ func (x *AssessmentTool) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use AssessmentTool.ProtoReflect.Descriptor instead.
 func (*AssessmentTool) Descriptor() ([]byte, []int) {
-	return file_orchestrator_proto_rawDescGZIP(), []int{20}
+	return file_orchestrator_proto_rawDescGZIP(), []int{22}
 }
 
 func (x *AssessmentTool) GetId() string {
@@ -1075,7 +1177,7 @@ type CloudService struct {
 func (x *CloudService) Reset() {
 	*x = CloudService{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_orchestrator_proto_msgTypes[21]
+		mi := &file_orchestrator_proto_msgTypes[23]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1088,7 +1190,7 @@ func (x *CloudService) String() string {
 func (*CloudService) ProtoMessage() {}
 
 func (x *CloudService) ProtoReflect() protoreflect.Message {
-	mi := &file_orchestrator_proto_msgTypes[21]
+	mi := &file_orchestrator_proto_msgTypes[23]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1101,7 +1203,7 @@ func (x *CloudService) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use CloudService.ProtoReflect.Descriptor instead.
 func (*CloudService) Descriptor() ([]byte, []int) {
-	return file_orchestrator_proto_rawDescGZIP(), []int{21}
+	return file_orchestrator_proto_rawDescGZIP(), []int{23}
 }
 
 func (x *CloudService) GetId() string {
@@ -1170,8 +1272,18 @@ var file_orchestrator_proto_rawDesc = []byte{
 	0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75,
 	0x6c, 0x74, 0x22, 0x1f, 0x0a, 0x1d, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x41, 0x73, 0x73, 0x65, 0x73,
 	0x73, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x22, 0x30, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
-	0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x65, 0x74, 0x72,
+	0x6e, 0x73, 0x65, 0x22, 0x40, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74,
+	0x72, 0x69, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x06, 0x6d, 0x65,
+	0x74, 0x72, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6c, 0x6f,
+	0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x06, 0x6d,
+	0x65, 0x74, 0x72, 0x69, 0x63, 0x22, 0x5d, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d,
+	0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09,
+	0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x08, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x06, 0x6d, 0x65, 0x74,
+	0x72, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6c, 0x6f, 0x75,
+	0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x06, 0x6d, 0x65,
+	0x74, 0x72, 0x69, 0x63, 0x22, 0x2f, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69,
+	0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x65, 0x74, 0x72,
 	0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x65, 0x74,
 	0x72, 0x69, 0x63, 0x49, 0x64, 0x22, 0x14, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x74,
 	0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x42, 0x0a, 0x13, 0x4c,
@@ -1243,7 +1355,7 @@ var file_orchestrator_proto_rawDesc = []byte{
 	0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
 	0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65,
 	0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xbc, 0x13, 0x0a,
+	0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x95, 0x15, 0x0a,
 	0x0c, 0x4f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x8e, 0x01,
 	0x0a, 0x16, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x41, 0x73, 0x73, 0x65, 0x73, 0x73,
 	0x6d, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x6f, 0x6c, 0x12, 0x28, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
@@ -1318,90 +1430,103 @@ var file_orchestrator_proto_rawDesc = []byte{
 	0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02,
 	0x25, 0x12, 0x23, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61,
 	0x74, 0x6f, 0x72, 0x2f, 0x61, 0x73, 0x73, 0x65, 0x73, 0x73, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x72,
-	0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x6a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74,
-	0x72, 0x69, 0x63, 0x12, 0x1c, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e,
-	0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x1a, 0x11, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x4d, 0x65,
-	0x74, 0x72, 0x69, 0x63, 0x22, 0x2c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, 0x2f, 0x76,
-	0x31, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x6d,
-	0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x7b, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x69,
-	0x64, 0x7d, 0x12, 0x6e, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
-	0x73, 0x12, 0x1d, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x4c, 0x69,
-	0x73, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x1e, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x4c, 0x69, 0x73,
-	0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72,
-	0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
-	0x63, 0x73, 0x12, 0x89, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43,
-	0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x26, 0x2e, 0x63, 0x6c,
-	0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
+	0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x6b, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
+	0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x1e, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74,
+	0x6f, 0x72, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74,
+	0x6f, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02,
+	0x22, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61,
+	0x74, 0x6f, 0x72, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x3a, 0x06, 0x6d, 0x65, 0x74,
+	0x72, 0x69, 0x63, 0x12, 0x6b, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74,
+	0x72, 0x69, 0x63, 0x12, 0x1e, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e,
+	0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e,
+	0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x1a, 0x18,
+	0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72,
+	0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x3a, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+	0x12, 0x69, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x1b, 0x2e,
+	0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74,
+	0x72, 0x69, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x63, 0x6c, 0x6f,
+	0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x22, 0x2c, 0x82,
+	0xd3, 0xe4, 0x93, 0x02, 0x26, 0x12, 0x24, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65,
+	0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
+	0x7b, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x6e, 0x0a, 0x0b, 0x4c,
+	0x69, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x1d, 0x2e, 0x63, 0x6c, 0x6f,
+	0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69,
+	0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6c, 0x6f, 0x75,
+	0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+	0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02,
+	0x1a, 0x12, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61,
+	0x74, 0x6f, 0x72, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x89, 0x01, 0x0a, 0x14,
+	0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72,
+	0x76, 0x69, 0x63, 0x65, 0x12, 0x26, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72,
+	0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65,
+	0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63,
+	0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65,
+	0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x22, 0x1f, 0x2f,
+	0x76, 0x31, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2f,
+	0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3a, 0x07,
+	0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x92, 0x01, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61,
+	0x74, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24,
+	0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74,
+	0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72,
+	0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x3d, 0x82,
+	0xd3, 0xe4, 0x93, 0x02, 0x37, 0x1a, 0x2c, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65,
+	0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65,
+	0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f,
+	0x69, 0x64, 0x7d, 0x3a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x83, 0x01, 0x0a,
+	0x0f, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
+	0x12, 0x21, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x47, 0x65, 0x74,
 	0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75,
 	0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e,
-	0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x30, 0x82, 0xd3,
-	0xe4, 0x93, 0x02, 0x2a, 0x22, 0x1f, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73,
+	0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x34, 0x82, 0xd3,
+	0xe4, 0x93, 0x02, 0x2e, 0x12, 0x2c, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73,
 	0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65, 0x72,
-	0x76, 0x69, 0x63, 0x65, 0x73, 0x3a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x92,
-	0x01, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f,
-	0x72, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72,
-	0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6c,
-	0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72,
-	0x76, 0x69, 0x63, 0x65, 0x22, 0x3d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x37, 0x1a, 0x2c, 0x2f, 0x76,
-	0x31, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63,
-	0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x73,
-	0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x07, 0x73, 0x65, 0x72, 0x76,
-	0x69, 0x63, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x6f, 0x75, 0x64,
-	0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x21, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69,
-	0x74, 0x6f, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76,
-	0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6c, 0x6f,
-	0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76,
-	0x69, 0x63, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x12, 0x2c, 0x2f, 0x76, 0x31,
+	0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69,
+	0x64, 0x7d, 0x12, 0x87, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x6f, 0x75, 0x64,
+	0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
+	0x69, 0x74, 0x6f, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65,
+	0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e,
+	0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c,
+	0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, 0x1f, 0x2f, 0x76, 0x31,
 	0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6c,
-	0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x87, 0x01, 0x0a, 0x11, 0x4c, 0x69,
-	0x73, 0x74, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12,
-	0x23, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74,
-	0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72,
-	0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
-	0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93,
-	0x02, 0x21, 0x12, 0x1f, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72,
-	0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69,
-	0x63, 0x65, 0x73, 0x12, 0x88, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6c,
-	0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x2e, 0x63, 0x6c, 0x6f,
-	0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6c, 0x6f,
-	0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
-	0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e,
-	0x2a, 0x2c, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74,
+	0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x88, 0x01, 0x0a,
+	0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76,
+	0x69, 0x63, 0x65, 0x12, 0x24, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e,
+	0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69,
+	0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+	0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
+	0x79, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x2a, 0x2c, 0x2f, 0x76, 0x31, 0x2f, 0x6f,
+	0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6c, 0x6f, 0x75,
+	0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x65, 0x72, 0x76,
+	0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0xba, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x4d,
+	0x65, 0x74, 0x72, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x12, 0x28, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x47,
+	0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72,
+	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63,
+	0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x43,
+	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x56, 0x82, 0xd3,
+	0xe4, 0x93, 0x02, 0x50, 0x12, 0x4e, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73,
+	0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65, 0x72,
+	0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69,
+	0x64, 0x7d, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+	0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+	0x5f, 0x69, 0x64, 0x7d, 0x12, 0xbd, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x74,
+	0x72, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+	0x73, 0x12, 0x29, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x4c, 0x69,
+	0x73, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72,
+	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63,
+	0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x74,
+	0x72, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x44,
+	0x12, 0x42, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74,
 	0x6f, 0x72, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
-	0x73, 0x2f, 0x7b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0xba,
-	0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66,
-	0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x2e, 0x63, 0x6c, 0x6f, 0x75,
-	0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x43,
-	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e,
-	0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74,
-	0x69, 0x6f, 0x6e, 0x22, 0x56, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x50, 0x12, 0x4e, 0x2f, 0x76, 0x31,
-	0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6c,
-	0x6f, 0x75, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x65,
-	0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
-	0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f,
-	0x7b, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0xbd, 0x01, 0x0a, 0x18,
-	0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-	0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64,
-	0x69, 0x74, 0x6f, 0x72, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x43,
-	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x2e,
-	0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
-	0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
-	0x4a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x44, 0x12, 0x42, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x63,
-	0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f,
-	0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
-	0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x63, 0x6f, 0x6e,
-	0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x12, 0x5a, 0x10, 0x61,
-	0x70, 0x69, 0x2f, 0x6f, 0x72, 0x63, 0x68, 0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x62,
-	0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x73, 0x2f, 0x7b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x6d,
+	0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74,
+	0x69, 0x6f, 0x6e, 0x73, 0x42, 0x12, 0x5a, 0x10, 0x61, 0x70, 0x69, 0x2f, 0x6f, 0x72, 0x63, 0x68,
+	0x65, 0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -1416,7 +1541,7 @@ func file_orchestrator_proto_rawDescGZIP() []byte {
 	return file_orchestrator_proto_rawDescData
 }
 
-var file_orchestrator_proto_msgTypes = make([]protoimpl.MessageInfo, 23)
+var file_orchestrator_proto_msgTypes = make([]protoimpl.MessageInfo, 25)
 var file_orchestrator_proto_goTypes = []interface{}{
 	(*RegisterAssessmentToolRequest)(nil),            // 0: clouditor.RegisterAssessmentToolRequest
 	(*ListAssessmentToolsRequest)(nil),               // 1: clouditor.ListAssessmentToolsRequest
@@ -1426,78 +1551,86 @@ var file_orchestrator_proto_goTypes = []interface{}{
 	(*DeregisterAssessmentToolRequest)(nil),          // 5: clouditor.DeregisterAssessmentToolRequest
 	(*StoreAssessmentResultRequest)(nil),             // 6: clouditor.StoreAssessmentResultRequest
 	(*StoreAssessmentResultResponse)(nil),            // 7: clouditor.StoreAssessmentResultResponse
-	(*GetMetricsRequest)(nil),                        // 8: clouditor.GetMetricsRequest
-	(*ListMetricsRequest)(nil),                       // 9: clouditor.ListMetricsRequest
-	(*ListMetricsResponse)(nil),                      // 10: clouditor.ListMetricsResponse
-	(*GetCloudServiceRequest)(nil),                   // 11: clouditor.GetCloudServiceRequest
-	(*RegisterCloudServiceRequest)(nil),              // 12: clouditor.RegisterCloudServiceRequest
-	(*UpdateCloudServiceRequest)(nil),                // 13: clouditor.UpdateCloudServiceRequest
-	(*RemoveCloudServiceRequest)(nil),                // 14: clouditor.RemoveCloudServiceRequest
-	(*ListCloudServicesRequest)(nil),                 // 15: clouditor.ListCloudServicesRequest
-	(*ListCloudServicesResponse)(nil),                // 16: clouditor.ListCloudServicesResponse
-	(*GetMetricConfigurationRequest)(nil),            // 17: clouditor.GetMetricConfigurationRequest
-	(*ListMetricConfigurationRequest)(nil),           // 18: clouditor.ListMetricConfigurationRequest
-	(*ListMetricConfigurationResponse)(nil),          // 19: clouditor.ListMetricConfigurationResponse
-	(*AssessmentTool)(nil),                           // 20: clouditor.AssessmentTool
-	(*CloudService)(nil),                             // 21: clouditor.CloudService
-	nil,                                              // 22: clouditor.ListMetricConfigurationResponse.ConfigurationsEntry
-	(*assessment.AssessmentResult)(nil),              // 23: clouditor.AssessmentResult
-	(*assessment.Metric)(nil),                        // 24: clouditor.Metric
-	(*assessment.MetricConfiguration)(nil),           // 25: clouditor.MetricConfiguration
-	(*assessment.ListAssessmentResultsRequest)(nil),  // 26: clouditor.ListAssessmentResultsRequest
-	(*emptypb.Empty)(nil),                            // 27: google.protobuf.Empty
-	(*assessment.ListAssessmentResultsResponse)(nil), // 28: clouditor.ListAssessmentResultsResponse
+	(*CreateMetricRequest)(nil),                      // 8: clouditor.CreateMetricRequest
+	(*UpdateMetricRequest)(nil),                      // 9: clouditor.UpdateMetricRequest
+	(*GetMetricRequest)(nil),                         // 10: clouditor.GetMetricRequest
+	(*ListMetricsRequest)(nil),                       // 11: clouditor.ListMetricsRequest
+	(*ListMetricsResponse)(nil),                      // 12: clouditor.ListMetricsResponse
+	(*GetCloudServiceRequest)(nil),                   // 13: clouditor.GetCloudServiceRequest
+	(*RegisterCloudServiceRequest)(nil),              // 14: clouditor.RegisterCloudServiceRequest
+	(*UpdateCloudServiceRequest)(nil),                // 15: clouditor.UpdateCloudServiceRequest
+	(*RemoveCloudServiceRequest)(nil),                // 16: clouditor.RemoveCloudServiceRequest
+	(*ListCloudServicesRequest)(nil),                 // 17: clouditor.ListCloudServicesRequest
+	(*ListCloudServicesResponse)(nil),                // 18: clouditor.ListCloudServicesResponse
+	(*GetMetricConfigurationRequest)(nil),            // 19: clouditor.GetMetricConfigurationRequest
+	(*ListMetricConfigurationRequest)(nil),           // 20: clouditor.ListMetricConfigurationRequest
+	(*ListMetricConfigurationResponse)(nil),          // 21: clouditor.ListMetricConfigurationResponse
+	(*AssessmentTool)(nil),                           // 22: clouditor.AssessmentTool
+	(*CloudService)(nil),                             // 23: clouditor.CloudService
+	nil,                                              // 24: clouditor.ListMetricConfigurationResponse.ConfigurationsEntry
+	(*assessment.AssessmentResult)(nil),              // 25: clouditor.AssessmentResult
+	(*assessment.Metric)(nil),                        // 26: clouditor.Metric
+	(*assessment.MetricConfiguration)(nil),           // 27: clouditor.MetricConfiguration
+	(*assessment.ListAssessmentResultsRequest)(nil),  // 28: clouditor.ListAssessmentResultsRequest
+	(*emptypb.Empty)(nil),                            // 29: google.protobuf.Empty
+	(*assessment.ListAssessmentResultsResponse)(nil), // 30: clouditor.ListAssessmentResultsResponse
 }
 var file_orchestrator_proto_depIdxs = []int32{
-	20, // 0: clouditor.RegisterAssessmentToolRequest.tool:type_name -> clouditor.AssessmentTool
-	20, // 1: clouditor.ListAssessmentToolsResponse.tools:type_name -> clouditor.AssessmentTool
-	20, // 2: clouditor.UpdateAssessmentToolRequest.tool:type_name -> clouditor.AssessmentTool
-	23, // 3: clouditor.StoreAssessmentResultRequest.result:type_name -> clouditor.AssessmentResult
-	24, // 4: clouditor.ListMetricsResponse.metrics:type_name -> clouditor.Metric
-	21, // 5: clouditor.RegisterCloudServiceRequest.service:type_name -> clouditor.CloudService
-	21, // 6: clouditor.UpdateCloudServiceRequest.service:type_name -> clouditor.CloudService
-	21, // 7: clouditor.ListCloudServicesResponse.services:type_name -> clouditor.CloudService
-	22, // 8: clouditor.ListMetricConfigurationResponse.configurations:type_name -> clouditor.ListMetricConfigurationResponse.ConfigurationsEntry
-	25, // 9: clouditor.ListMetricConfigurationResponse.ConfigurationsEntry.value:type_name -> clouditor.MetricConfiguration
-	0,  // 10: clouditor.Orchestrator.RegisterAssessmentTool:input_type -> clouditor.RegisterAssessmentToolRequest
-	1,  // 11: clouditor.Orchestrator.ListAssessmentTools:input_type -> clouditor.ListAssessmentToolsRequest
-	3,  // 12: clouditor.Orchestrator.GetAssessmentTool:input_type -> clouditor.GetAssessmentToolRequest
-	4,  // 13: clouditor.Orchestrator.UpdateAssessmentTool:input_type -> clouditor.UpdateAssessmentToolRequest
-	5,  // 14: clouditor.Orchestrator.DeregisterAssessmentTool:input_type -> clouditor.DeregisterAssessmentToolRequest
-	6,  // 15: clouditor.Orchestrator.StoreAssessmentResult:input_type -> clouditor.StoreAssessmentResultRequest
-	23, // 16: clouditor.Orchestrator.StoreAssessmentResults:input_type -> clouditor.AssessmentResult
-	26, // 17: clouditor.Orchestrator.ListAssessmentResults:input_type -> clouditor.ListAssessmentResultsRequest
-	8,  // 18: clouditor.Orchestrator.GetMetric:input_type -> clouditor.GetMetricsRequest
-	9,  // 19: clouditor.Orchestrator.ListMetrics:input_type -> clouditor.ListMetricsRequest
-	12, // 20: clouditor.Orchestrator.RegisterCloudService:input_type -> clouditor.RegisterCloudServiceRequest
-	13, // 21: clouditor.Orchestrator.UpdateCloudService:input_type -> clouditor.UpdateCloudServiceRequest
-	11, // 22: clouditor.Orchestrator.GetCloudService:input_type -> clouditor.GetCloudServiceRequest
-	15, // 23: clouditor.Orchestrator.ListCloudServices:input_type -> clouditor.ListCloudServicesRequest
-	14, // 24: clouditor.Orchestrator.RemoveCloudService:input_type -> clouditor.RemoveCloudServiceRequest
-	17, // 25: clouditor.Orchestrator.GetMetricConfiguration:input_type -> clouditor.GetMetricConfigurationRequest
-	18, // 26: clouditor.Orchestrator.ListMetricConfigurations:input_type -> clouditor.ListMetricConfigurationRequest
-	20, // 27: clouditor.Orchestrator.RegisterAssessmentTool:output_type -> clouditor.AssessmentTool
-	2,  // 28: clouditor.Orchestrator.ListAssessmentTools:output_type -> clouditor.ListAssessmentToolsResponse
-	20, // 29: clouditor.Orchestrator.GetAssessmentTool:output_type -> clouditor.AssessmentTool
-	20, // 30: clouditor.Orchestrator.UpdateAssessmentTool:output_type -> clouditor.AssessmentTool
-	27, // 31: clouditor.Orchestrator.DeregisterAssessmentTool:output_type -> google.protobuf.Empty
-	7,  // 32: clouditor.Orchestrator.StoreAssessmentResult:output_type -> clouditor.StoreAssessmentResultResponse
-	27, // 33: clouditor.Orchestrator.StoreAssessmentResults:output_type -> google.protobuf.Empty
-	28, // 34: clouditor.Orchestrator.ListAssessmentResults:output_type -> clouditor.ListAssessmentResultsResponse
-	24, // 35: clouditor.Orchestrator.GetMetric:output_type -> clouditor.Metric
-	10, // 36: clouditor.Orchestrator.ListMetrics:output_type -> clouditor.ListMetricsResponse
-	21, // 37: clouditor.Orchestrator.RegisterCloudService:output_type -> clouditor.CloudService
-	21, // 38: clouditor.Orchestrator.UpdateCloudService:output_type -> clouditor.CloudService
-	21, // 39: clouditor.Orchestrator.GetCloudService:output_type -> clouditor.CloudService
-	16, // 40: clouditor.Orchestrator.ListCloudServices:output_type -> clouditor.ListCloudServicesResponse
-	27, // 41: clouditor.Orchestrator.RemoveCloudService:output_type -> google.protobuf.Empty
-	25, // 42: clouditor.Orchestrator.GetMetricConfiguration:output_type -> clouditor.MetricConfiguration
-	19, // 43: clouditor.Orchestrator.ListMetricConfigurations:output_type -> clouditor.ListMetricConfigurationResponse
-	27, // [27:44] is the sub-list for method output_type
-	10, // [10:27] is the sub-list for method input_type
-	10, // [10:10] is the sub-list for extension type_name
-	10, // [10:10] is the sub-list for extension extendee
-	0,  // [0:10] is the sub-list for field type_name
+	22, // 0: clouditor.RegisterAssessmentToolRequest.tool:type_name -> clouditor.AssessmentTool
+	22, // 1: clouditor.ListAssessmentToolsResponse.tools:type_name -> clouditor.AssessmentTool
+	22, // 2: clouditor.UpdateAssessmentToolRequest.tool:type_name -> clouditor.AssessmentTool
+	25, // 3: clouditor.StoreAssessmentResultRequest.result:type_name -> clouditor.AssessmentResult
+	26, // 4: clouditor.CreateMetricRequest.metric:type_name -> clouditor.Metric
+	26, // 5: clouditor.UpdateMetricRequest.metric:type_name -> clouditor.Metric
+	26, // 6: clouditor.ListMetricsResponse.metrics:type_name -> clouditor.Metric
+	23, // 7: clouditor.RegisterCloudServiceRequest.service:type_name -> clouditor.CloudService
+	23, // 8: clouditor.UpdateCloudServiceRequest.service:type_name -> clouditor.CloudService
+	23, // 9: clouditor.ListCloudServicesResponse.services:type_name -> clouditor.CloudService
+	24, // 10: clouditor.ListMetricConfigurationResponse.configurations:type_name -> clouditor.ListMetricConfigurationResponse.ConfigurationsEntry
+	27, // 11: clouditor.ListMetricConfigurationResponse.ConfigurationsEntry.value:type_name -> clouditor.MetricConfiguration
+	0,  // 12: clouditor.Orchestrator.RegisterAssessmentTool:input_type -> clouditor.RegisterAssessmentToolRequest
+	1,  // 13: clouditor.Orchestrator.ListAssessmentTools:input_type -> clouditor.ListAssessmentToolsRequest
+	3,  // 14: clouditor.Orchestrator.GetAssessmentTool:input_type -> clouditor.GetAssessmentToolRequest
+	4,  // 15: clouditor.Orchestrator.UpdateAssessmentTool:input_type -> clouditor.UpdateAssessmentToolRequest
+	5,  // 16: clouditor.Orchestrator.DeregisterAssessmentTool:input_type -> clouditor.DeregisterAssessmentToolRequest
+	6,  // 17: clouditor.Orchestrator.StoreAssessmentResult:input_type -> clouditor.StoreAssessmentResultRequest
+	25, // 18: clouditor.Orchestrator.StoreAssessmentResults:input_type -> clouditor.AssessmentResult
+	28, // 19: clouditor.Orchestrator.ListAssessmentResults:input_type -> clouditor.ListAssessmentResultsRequest
+	8,  // 20: clouditor.Orchestrator.CreateMetric:input_type -> clouditor.CreateMetricRequest
+	9,  // 21: clouditor.Orchestrator.UpdateMetric:input_type -> clouditor.UpdateMetricRequest
+	10, // 22: clouditor.Orchestrator.GetMetric:input_type -> clouditor.GetMetricRequest
+	11, // 23: clouditor.Orchestrator.ListMetrics:input_type -> clouditor.ListMetricsRequest
+	14, // 24: clouditor.Orchestrator.RegisterCloudService:input_type -> clouditor.RegisterCloudServiceRequest
+	15, // 25: clouditor.Orchestrator.UpdateCloudService:input_type -> clouditor.UpdateCloudServiceRequest
+	13, // 26: clouditor.Orchestrator.GetCloudService:input_type -> clouditor.GetCloudServiceRequest
+	17, // 27: clouditor.Orchestrator.ListCloudServices:input_type -> clouditor.ListCloudServicesRequest
+	16, // 28: clouditor.Orchestrator.RemoveCloudService:input_type -> clouditor.RemoveCloudServiceRequest
+	19, // 29: clouditor.Orchestrator.GetMetricConfiguration:input_type -> clouditor.GetMetricConfigurationRequest
+	20, // 30: clouditor.Orchestrator.ListMetricConfigurations:input_type -> clouditor.ListMetricConfigurationRequest
+	22, // 31: clouditor.Orchestrator.RegisterAssessmentTool:output_type -> clouditor.AssessmentTool
+	2,  // 32: clouditor.Orchestrator.ListAssessmentTools:output_type -> clouditor.ListAssessmentToolsResponse
+	22, // 33: clouditor.Orchestrator.GetAssessmentTool:output_type -> clouditor.AssessmentTool
+	22, // 34: clouditor.Orchestrator.UpdateAssessmentTool:output_type -> clouditor.AssessmentTool
+	29, // 35: clouditor.Orchestrator.DeregisterAssessmentTool:output_type -> google.protobuf.Empty
+	7,  // 36: clouditor.Orchestrator.StoreAssessmentResult:output_type -> clouditor.StoreAssessmentResultResponse
+	29, // 37: clouditor.Orchestrator.StoreAssessmentResults:output_type -> google.protobuf.Empty
+	30, // 38: clouditor.Orchestrator.ListAssessmentResults:output_type -> clouditor.ListAssessmentResultsResponse
+	26, // 39: clouditor.Orchestrator.CreateMetric:output_type -> clouditor.Metric
+	26, // 40: clouditor.Orchestrator.UpdateMetric:output_type -> clouditor.Metric
+	26, // 41: clouditor.Orchestrator.GetMetric:output_type -> clouditor.Metric
+	12, // 42: clouditor.Orchestrator.ListMetrics:output_type -> clouditor.ListMetricsResponse
+	23, // 43: clouditor.Orchestrator.RegisterCloudService:output_type -> clouditor.CloudService
+	23, // 44: clouditor.Orchestrator.UpdateCloudService:output_type -> clouditor.CloudService
+	23, // 45: clouditor.Orchestrator.GetCloudService:output_type -> clouditor.CloudService
+	18, // 46: clouditor.Orchestrator.ListCloudServices:output_type -> clouditor.ListCloudServicesResponse
+	29, // 47: clouditor.Orchestrator.RemoveCloudService:output_type -> google.protobuf.Empty
+	27, // 48: clouditor.Orchestrator.GetMetricConfiguration:output_type -> clouditor.MetricConfiguration
+	21, // 49: clouditor.Orchestrator.ListMetricConfigurations:output_type -> clouditor.ListMetricConfigurationResponse
+	31, // [31:50] is the sub-list for method output_type
+	12, // [12:31] is the sub-list for method input_type
+	12, // [12:12] is the sub-list for extension type_name
+	12, // [12:12] is the sub-list for extension extendee
+	0,  // [0:12] is the sub-list for field type_name
 }
 
 func init() { file_orchestrator_proto_init() }
@@ -1603,7 +1736,7 @@ func file_orchestrator_proto_init() {
 			}
 		}
 		file_orchestrator_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GetMetricsRequest); i {
+			switch v := v.(*CreateMetricRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1615,7 +1748,7 @@ func file_orchestrator_proto_init() {
 			}
 		}
 		file_orchestrator_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ListMetricsRequest); i {
+			switch v := v.(*UpdateMetricRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1627,7 +1760,7 @@ func file_orchestrator_proto_init() {
 			}
 		}
 		file_orchestrator_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ListMetricsResponse); i {
+			switch v := v.(*GetMetricRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1639,7 +1772,7 @@ func file_orchestrator_proto_init() {
 			}
 		}
 		file_orchestrator_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GetCloudServiceRequest); i {
+			switch v := v.(*ListMetricsRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1651,7 +1784,7 @@ func file_orchestrator_proto_init() {
 			}
 		}
 		file_orchestrator_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*RegisterCloudServiceRequest); i {
+			switch v := v.(*ListMetricsResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1663,7 +1796,7 @@ func file_orchestrator_proto_init() {
 			}
 		}
 		file_orchestrator_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*UpdateCloudServiceRequest); i {
+			switch v := v.(*GetCloudServiceRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1675,7 +1808,7 @@ func file_orchestrator_proto_init() {
 			}
 		}
 		file_orchestrator_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*RemoveCloudServiceRequest); i {
+			switch v := v.(*RegisterCloudServiceRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1687,7 +1820,7 @@ func file_orchestrator_proto_init() {
 			}
 		}
 		file_orchestrator_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ListCloudServicesRequest); i {
+			switch v := v.(*UpdateCloudServiceRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1699,7 +1832,7 @@ func file_orchestrator_proto_init() {
 			}
 		}
 		file_orchestrator_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ListCloudServicesResponse); i {
+			switch v := v.(*RemoveCloudServiceRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1711,7 +1844,7 @@ func file_orchestrator_proto_init() {
 			}
 		}
 		file_orchestrator_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*GetMetricConfigurationRequest); i {
+			switch v := v.(*ListCloudServicesRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1723,7 +1856,7 @@ func file_orchestrator_proto_init() {
 			}
 		}
 		file_orchestrator_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ListMetricConfigurationRequest); i {
+			switch v := v.(*ListCloudServicesResponse); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1735,7 +1868,7 @@ func file_orchestrator_proto_init() {
 			}
 		}
 		file_orchestrator_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ListMetricConfigurationResponse); i {
+			switch v := v.(*GetMetricConfigurationRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1747,7 +1880,7 @@ func file_orchestrator_proto_init() {
 			}
 		}
 		file_orchestrator_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*AssessmentTool); i {
+			switch v := v.(*ListMetricConfigurationRequest); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1759,6 +1892,30 @@ func file_orchestrator_proto_init() {
 			}
 		}
 		file_orchestrator_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*ListMetricConfigurationResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_orchestrator_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*AssessmentTool); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_orchestrator_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*CloudService); i {
 			case 0:
 				return &v.state
@@ -1777,7 +1934,7 @@ func file_orchestrator_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_orchestrator_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   23,
+			NumMessages:   25,
 			NumExtensions: 0,
 			NumServices:   1,
 		},
diff --git a/api/orchestrator/orchestrator.pb.gw.go b/api/orchestrator/orchestrator.pb.gw.go
index 632bbd95..7b266bb6 100644
--- a/api/orchestrator/orchestrator.pb.gw.go
+++ b/api/orchestrator/orchestrator.pb.gw.go
@@ -378,8 +378,94 @@ func local_request_Orchestrator_ListAssessmentResults_0(ctx context.Context, mar
 
 }
 
+func request_Orchestrator_CreateMetric_0(ctx context.Context, marshaler runtime.Marshaler, client OrchestratorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var protoReq CreateMetricRequest
+	var metadata runtime.ServerMetadata
+
+	newReader, berr := utilities.IOReaderFactory(req.Body)
+	if berr != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+	}
+	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Metric); err != nil && err != io.EOF {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+
+	msg, err := client.CreateMetric(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+	return msg, metadata, err
+
+}
+
+func local_request_Orchestrator_CreateMetric_0(ctx context.Context, marshaler runtime.Marshaler, server OrchestratorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var protoReq CreateMetricRequest
+	var metadata runtime.ServerMetadata
+
+	newReader, berr := utilities.IOReaderFactory(req.Body)
+	if berr != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+	}
+	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Metric); err != nil && err != io.EOF {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+
+	msg, err := server.CreateMetric(ctx, &protoReq)
+	return msg, metadata, err
+
+}
+
+var (
+	filter_Orchestrator_UpdateMetric_0 = &utilities.DoubleArray{Encoding: map[string]int{"metric": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
+)
+
+func request_Orchestrator_UpdateMetric_0(ctx context.Context, marshaler runtime.Marshaler, client OrchestratorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var protoReq UpdateMetricRequest
+	var metadata runtime.ServerMetadata
+
+	newReader, berr := utilities.IOReaderFactory(req.Body)
+	if berr != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+	}
+	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Metric); err != nil && err != io.EOF {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+
+	if err := req.ParseForm(); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Orchestrator_UpdateMetric_0); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+
+	msg, err := client.UpdateMetric(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+	return msg, metadata, err
+
+}
+
+func local_request_Orchestrator_UpdateMetric_0(ctx context.Context, marshaler runtime.Marshaler, server OrchestratorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var protoReq UpdateMetricRequest
+	var metadata runtime.ServerMetadata
+
+	newReader, berr := utilities.IOReaderFactory(req.Body)
+	if berr != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
+	}
+	if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Metric); err != nil && err != io.EOF {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+
+	if err := req.ParseForm(); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Orchestrator_UpdateMetric_0); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+
+	msg, err := server.UpdateMetric(ctx, &protoReq)
+	return msg, metadata, err
+
+}
+
 func request_Orchestrator_GetMetric_0(ctx context.Context, marshaler runtime.Marshaler, client OrchestratorClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetMetricsRequest
+	var protoReq GetMetricRequest
 	var metadata runtime.ServerMetadata
 
 	var (
@@ -405,7 +491,7 @@ func request_Orchestrator_GetMetric_0(ctx context.Context, marshaler runtime.Mar
 }
 
 func local_request_Orchestrator_GetMetric_0(ctx context.Context, marshaler runtime.Marshaler, server OrchestratorServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetMetricsRequest
+	var protoReq GetMetricRequest
 	var metadata runtime.ServerMetadata
 
 	var (
@@ -986,6 +1072,52 @@ func RegisterOrchestratorHandlerServer(ctx context.Context, mux *runtime.ServeMu
 
 	})
 
+	mux.Handle("POST", pattern_Orchestrator_CreateMetric_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+		ctx, cancel := context.WithCancel(req.Context())
+		defer cancel()
+		var stream runtime.ServerTransportStream
+		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+		rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/clouditor.Orchestrator/CreateMetric", runtime.WithHTTPPathPattern("/v1/orchestrator/metrics"))
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		resp, md, err := local_request_Orchestrator_CreateMetric_0(rctx, inboundMarshaler, server, req, pathParams)
+		md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+		ctx = runtime.NewServerMetadataContext(ctx, md)
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+
+		forward_Orchestrator_CreateMetric_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+	})
+
+	mux.Handle("PUT", pattern_Orchestrator_UpdateMetric_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+		ctx, cancel := context.WithCancel(req.Context())
+		defer cancel()
+		var stream runtime.ServerTransportStream
+		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+		rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/clouditor.Orchestrator/UpdateMetric", runtime.WithHTTPPathPattern("/v1/orchestrator/metrics"))
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		resp, md, err := local_request_Orchestrator_UpdateMetric_0(rctx, inboundMarshaler, server, req, pathParams)
+		md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+		ctx = runtime.NewServerMetadataContext(ctx, md)
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+
+		forward_Orchestrator_UpdateMetric_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+	})
+
 	mux.Handle("GET", pattern_Orchestrator_GetMetric_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
@@ -1394,6 +1526,46 @@ func RegisterOrchestratorHandlerClient(ctx context.Context, mux *runtime.ServeMu
 
 	})
 
+	mux.Handle("POST", pattern_Orchestrator_CreateMetric_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+		ctx, cancel := context.WithCancel(req.Context())
+		defer cancel()
+		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+		rctx, err := runtime.AnnotateContext(ctx, mux, req, "/clouditor.Orchestrator/CreateMetric", runtime.WithHTTPPathPattern("/v1/orchestrator/metrics"))
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		resp, md, err := request_Orchestrator_CreateMetric_0(rctx, inboundMarshaler, client, req, pathParams)
+		ctx = runtime.NewServerMetadataContext(ctx, md)
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+
+		forward_Orchestrator_CreateMetric_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+	})
+
+	mux.Handle("PUT", pattern_Orchestrator_UpdateMetric_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+		ctx, cancel := context.WithCancel(req.Context())
+		defer cancel()
+		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+		rctx, err := runtime.AnnotateContext(ctx, mux, req, "/clouditor.Orchestrator/UpdateMetric", runtime.WithHTTPPathPattern("/v1/orchestrator/metrics"))
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		resp, md, err := request_Orchestrator_UpdateMetric_0(rctx, inboundMarshaler, client, req, pathParams)
+		ctx = runtime.NewServerMetadataContext(ctx, md)
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+
+		forward_Orchestrator_UpdateMetric_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+	})
+
 	mux.Handle("GET", pattern_Orchestrator_GetMetric_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
@@ -1594,6 +1766,10 @@ var (
 
 	pattern_Orchestrator_ListAssessmentResults_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "orchestrator", "assessment_results"}, ""))
 
+	pattern_Orchestrator_CreateMetric_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "orchestrator", "metrics"}, ""))
+
+	pattern_Orchestrator_UpdateMetric_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "orchestrator", "metrics"}, ""))
+
 	pattern_Orchestrator_GetMetric_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "orchestrator", "metrics", "metric_id"}, ""))
 
 	pattern_Orchestrator_ListMetrics_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "orchestrator", "metrics"}, ""))
@@ -1630,6 +1806,10 @@ var (
 
 	forward_Orchestrator_ListAssessmentResults_0 = runtime.ForwardResponseMessage
 
+	forward_Orchestrator_CreateMetric_0 = runtime.ForwardResponseMessage
+
+	forward_Orchestrator_UpdateMetric_0 = runtime.ForwardResponseMessage
+
 	forward_Orchestrator_GetMetric_0 = runtime.ForwardResponseMessage
 
 	forward_Orchestrator_ListMetrics_0 = runtime.ForwardResponseMessage
diff --git a/api/orchestrator/orchestrator_grpc.pb.go b/api/orchestrator/orchestrator_grpc.pb.go
index 3d7b0366..123821fa 100644
--- a/api/orchestrator/orchestrator_grpc.pb.go
+++ b/api/orchestrator/orchestrator_grpc.pb.go
@@ -42,8 +42,12 @@ type OrchestratorClient interface {
 	StoreAssessmentResults(ctx context.Context, opts ...grpc.CallOption) (Orchestrator_StoreAssessmentResultsClient, error)
 	// List all assessment results. Part of the public API, also exposed as REST.
 	ListAssessmentResults(ctx context.Context, in *assessment.ListAssessmentResultsRequest, opts ...grpc.CallOption) (*assessment.ListAssessmentResultsResponse, error)
+	// Creates a new metric
+	CreateMetric(ctx context.Context, in *CreateMetricRequest, opts ...grpc.CallOption) (*assessment.Metric, error)
+	// Updates an existing metric
+	UpdateMetric(ctx context.Context, in *UpdateMetricRequest, opts ...grpc.CallOption) (*assessment.Metric, error)
 	// Returns the metric with the passed metric id
-	GetMetric(ctx context.Context, in *GetMetricsRequest, opts ...grpc.CallOption) (*assessment.Metric, error)
+	GetMetric(ctx context.Context, in *GetMetricRequest, opts ...grpc.CallOption) (*assessment.Metric, error)
 	// List all metrics provided by the metric catalog
 	ListMetrics(ctx context.Context, in *ListMetricsRequest, opts ...grpc.CallOption) (*ListMetricsResponse, error)
 	// Registers a new target cloud service
@@ -167,7 +171,25 @@ func (c *orchestratorClient) ListAssessmentResults(ctx context.Context, in *asse
 	return out, nil
 }
 
-func (c *orchestratorClient) GetMetric(ctx context.Context, in *GetMetricsRequest, opts ...grpc.CallOption) (*assessment.Metric, error) {
+func (c *orchestratorClient) CreateMetric(ctx context.Context, in *CreateMetricRequest, opts ...grpc.CallOption) (*assessment.Metric, error) {
+	out := new(assessment.Metric)
+	err := c.cc.Invoke(ctx, "/clouditor.Orchestrator/CreateMetric", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *orchestratorClient) UpdateMetric(ctx context.Context, in *UpdateMetricRequest, opts ...grpc.CallOption) (*assessment.Metric, error) {
+	out := new(assessment.Metric)
+	err := c.cc.Invoke(ctx, "/clouditor.Orchestrator/UpdateMetric", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *orchestratorClient) GetMetric(ctx context.Context, in *GetMetricRequest, opts ...grpc.CallOption) (*assessment.Metric, error) {
 	out := new(assessment.Metric)
 	err := c.cc.Invoke(ctx, "/clouditor.Orchestrator/GetMetric", in, out, opts...)
 	if err != nil {
@@ -270,8 +292,12 @@ type OrchestratorServer interface {
 	StoreAssessmentResults(Orchestrator_StoreAssessmentResultsServer) error
 	// List all assessment results. Part of the public API, also exposed as REST.
 	ListAssessmentResults(context.Context, *assessment.ListAssessmentResultsRequest) (*assessment.ListAssessmentResultsResponse, error)
+	// Creates a new metric
+	CreateMetric(context.Context, *CreateMetricRequest) (*assessment.Metric, error)
+	// Updates an existing metric
+	UpdateMetric(context.Context, *UpdateMetricRequest) (*assessment.Metric, error)
 	// Returns the metric with the passed metric id
-	GetMetric(context.Context, *GetMetricsRequest) (*assessment.Metric, error)
+	GetMetric(context.Context, *GetMetricRequest) (*assessment.Metric, error)
 	// List all metrics provided by the metric catalog
 	ListMetrics(context.Context, *ListMetricsRequest) (*ListMetricsResponse, error)
 	// Registers a new target cloud service
@@ -319,7 +345,13 @@ func (UnimplementedOrchestratorServer) StoreAssessmentResults(Orchestrator_Store
 func (UnimplementedOrchestratorServer) ListAssessmentResults(context.Context, *assessment.ListAssessmentResultsRequest) (*assessment.ListAssessmentResultsResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method ListAssessmentResults not implemented")
 }
-func (UnimplementedOrchestratorServer) GetMetric(context.Context, *GetMetricsRequest) (*assessment.Metric, error) {
+func (UnimplementedOrchestratorServer) CreateMetric(context.Context, *CreateMetricRequest) (*assessment.Metric, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method CreateMetric not implemented")
+}
+func (UnimplementedOrchestratorServer) UpdateMetric(context.Context, *UpdateMetricRequest) (*assessment.Metric, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method UpdateMetric not implemented")
+}
+func (UnimplementedOrchestratorServer) GetMetric(context.Context, *GetMetricRequest) (*assessment.Metric, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method GetMetric not implemented")
 }
 func (UnimplementedOrchestratorServer) ListMetrics(context.Context, *ListMetricsRequest) (*ListMetricsResponse, error) {
@@ -511,8 +543,44 @@ func _Orchestrator_ListAssessmentResults_Handler(srv interface{}, ctx context.Co
 	return interceptor(ctx, in, info, handler)
 }
 
+func _Orchestrator_CreateMetric_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(CreateMetricRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(OrchestratorServer).CreateMetric(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/clouditor.Orchestrator/CreateMetric",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(OrchestratorServer).CreateMetric(ctx, req.(*CreateMetricRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Orchestrator_UpdateMetric_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(UpdateMetricRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(OrchestratorServer).UpdateMetric(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/clouditor.Orchestrator/UpdateMetric",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(OrchestratorServer).UpdateMetric(ctx, req.(*UpdateMetricRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 func _Orchestrator_GetMetric_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(GetMetricsRequest)
+	in := new(GetMetricRequest)
 	if err := dec(in); err != nil {
 		return nil, err
 	}
@@ -524,7 +592,7 @@ func _Orchestrator_GetMetric_Handler(srv interface{}, ctx context.Context, dec f
 		FullMethod: "/clouditor.Orchestrator/GetMetric",
 	}
 	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(OrchestratorServer).GetMetric(ctx, req.(*GetMetricsRequest))
+		return srv.(OrchestratorServer).GetMetric(ctx, req.(*GetMetricRequest))
 	}
 	return interceptor(ctx, in, info, handler)
 }
@@ -708,6 +776,14 @@ var Orchestrator_ServiceDesc = grpc.ServiceDesc{
 			MethodName: "ListAssessmentResults",
 			Handler:    _Orchestrator_ListAssessmentResults_Handler,
 		},
+		{
+			MethodName: "CreateMetric",
+			Handler:    _Orchestrator_CreateMetric_Handler,
+		},
+		{
+			MethodName: "UpdateMetric",
+			Handler:    _Orchestrator_UpdateMetric_Handler,
+		},
 		{
 			MethodName: "GetMetric",
 			Handler:    _Orchestrator_GetMetric_Handler,
diff --git a/cli/commands/metric/metric.go b/cli/commands/metric/metric.go
index 4411d49f..f83fa664 100644
--- a/cli/commands/metric/metric.go
+++ b/cli/commands/metric/metric.go
@@ -90,7 +90,7 @@ func NewGetMetricCommand() *cobra.Command {
 
 			metricID := args[0]
 
-			res, err = client.GetMetric(context.Background(), &orchestrator.GetMetricsRequest{MetricId: metricID})
+			res, err = client.GetMetric(context.Background(), &orchestrator.GetMetricRequest{MetricId: metricID})
 
 			return session.HandleResponse(res, err)
 		},
diff --git a/clouditor.code-workspace b/clouditor.code-workspace
index c2e233d6..d563903c 100644
--- a/clouditor.code-workspace
+++ b/clouditor.code-workspace
@@ -8,6 +8,7 @@
 		"cSpell.words": [
 			"AISEC",
 			"clouditor",
+			"Clouditor",
 			"Debugf",
 			"emptypb",
 			"garuppel",
diff --git a/openapi/orchestrator/openapi.yaml b/openapi/orchestrator/openapi.yaml
index be31045e..c7baed05 100644
--- a/openapi/orchestrator/openapi.yaml
+++ b/openapi/orchestrator/openapi.yaml
@@ -282,6 +282,47 @@ paths:
                         application/json:
                             schema:
                                 $ref: '#/components/schemas/ListMetricsResponse'
+        put:
+            tags:
+                - Orchestrator
+            description: Updates an existing metric
+            operationId: Orchestrator_UpdateMetric
+            parameters:
+                - name: metricId
+                  in: query
+                  schema:
+                    type: string
+            requestBody:
+                content:
+                    application/json:
+                        schema:
+                            $ref: '#/components/schemas/Metric'
+                required: true
+            responses:
+                "200":
+                    description: OK
+                    content:
+                        application/json:
+                            schema:
+                                $ref: '#/components/schemas/Metric'
+        post:
+            tags:
+                - Orchestrator
+            description: Creates a new metric
+            operationId: Orchestrator_CreateMetric
+            requestBody:
+                content:
+                    application/json:
+                        schema:
+                            $ref: '#/components/schemas/Metric'
+                required: true
+            responses:
+                "200":
+                    description: OK
+                    content:
+                        application/json:
+                            schema:
+                                $ref: '#/components/schemas/Metric'
     /v1/orchestrator/metrics/{metricId}:
         get:
             tags:
diff --git a/proto/orchestrator.proto b/proto/orchestrator.proto
index 4d0d70f0..4977c62f 100644
--- a/proto/orchestrator.proto
+++ b/proto/orchestrator.proto
@@ -52,7 +52,9 @@ service Orchestrator {
       returns (ListAssessmentToolsResponse) {
     option (google.api.http) = {
       get : "/v1/orchestrator/assessment_tools"
-      additional_bindings {get : "/v1/orchestrator/{metric_id}/assessment_tools"}
+      additional_bindings {
+        get : "/v1/orchestrator/{metric_id}/assessment_tools"
+      }
     };
   }
 
@@ -102,8 +104,24 @@ service Orchestrator {
     };
   }
 
+  // Creates a new metric
+  rpc CreateMetric(CreateMetricRequest) returns (Metric) {
+    option (google.api.http) = {
+      post : "/v1/orchestrator/metrics"
+      body : "metric"
+    };
+  }
+
+  // Updates an existing metric
+  rpc UpdateMetric(UpdateMetricRequest) returns (Metric) {
+    option (google.api.http) = {
+      put : "/v1/orchestrator/metrics"
+      body : "metric"
+    };
+  }
+
   // Returns the metric with the passed metric id
-  rpc GetMetric(GetMetricsRequest) returns (Metric) {
+  rpc GetMetric(GetMetricRequest) returns (Metric) {
     option (google.api.http) = {
       get : "/v1/orchestrator/metrics/{metric_id}"
     };
@@ -160,8 +178,8 @@ service Orchestrator {
       returns (MetricConfiguration) {
     option (google.api.http) = {
       get : "/v1/orchestrator/cloud_services/{service_id}/"
-          "metric_configurations/"
-          "{metric_id}"
+            "metric_configurations/"
+            "{metric_id}"
     };
   }
 
@@ -194,7 +212,14 @@ message DeregisterAssessmentToolRequest { string tool_id = 1; }
 message StoreAssessmentResultRequest { AssessmentResult result = 1; }
 message StoreAssessmentResultResponse {}
 
-message GetMetricsRequest { string metric_id = 1; }
+message CreateMetricRequest { Metric metric = 1; }
+
+message UpdateMetricRequest {
+  string metric_id = 1;
+  Metric metric = 2;
+}
+
+message GetMetricRequest { string metric_id = 1; }
 
 message ListMetricsRequest {}
 message ListMetricsResponse { repeated Metric metrics = 1; }
diff --git a/service/orchestrator/metrics.go b/service/orchestrator/metrics.go
new file mode 100644
index 00000000..2ed234c6
--- /dev/null
+++ b/service/orchestrator/metrics.go
@@ -0,0 +1,124 @@
+// Copyright 2022 Fraunhofer AISEC
+//
+// 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.
+//
+//           $$\                           $$\ $$\   $$\
+//           $$ |                          $$ |\__|  $$ |
+//  $$$$$$$\ $$ | $$$$$$\  $$\   $$\  $$$$$$$ |$$\ $$$$$$\    $$$$$$\   $$$$$$\
+// $$  _____|$$ |$$  __$$\ $$ |  $$ |$$  __$$ |$$ |\_$$  _|  $$  __$$\ $$  __$$\
+// $$ /      $$ |$$ /  $$ |$$ |  $$ |$$ /  $$ |$$ |  $$ |    $$ /  $$ |$$ | \__|
+// $$ |      $$ |$$ |  $$ |$$ |  $$ |$$ |  $$ |$$ |  $$ |$$\ $$ |  $$ |$$ |
+// \$$$$$$\  $$ |\$$$$$   |\$$$$$   |\$$$$$$  |$$ |  \$$$   |\$$$$$   |$$ |
+//  \_______|\__| \______/  \______/  \_______|\__|   \____/  \______/ \__|
+//
+// This file is part of Clouditor Community Edition.
+
+package orchestrator
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+
+	"clouditor.io/clouditor/api/assessment"
+	"clouditor.io/clouditor/api/orchestrator"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+)
+
+// LoadMetrics loads metrics definitions from a JSON file.
+func LoadMetrics(metricsFile string) (err error) {
+	var (
+		b []byte
+	)
+
+	b, err = f.ReadFile(metricsFile)
+	if err != nil {
+		return fmt.Errorf("error while loading %s: %w", metricsFile, err)
+	}
+
+	err = json.Unmarshal(b, &metrics)
+	if err != nil {
+		return fmt.Errorf("error in JSON marshal: %w", err)
+	}
+
+	return nil
+}
+
+// CreateMetric creates a new metric in the database.
+func (*Service) CreateMetric(_ context.Context, req *orchestrator.CreateMetricRequest) (metric *assessment.Metric, err error) {
+	// Validate the metric request
+	err = req.Metric.Validate(assessment.WithMetricRequiresId())
+	if err != nil {
+		return nil, status.Errorf(codes.InvalidArgument, "Validation of metric failed: %v", err)
+	}
+
+	// Check, if metric id already exists
+	if _, ok := metricIndex[req.Metric.Id]; ok {
+		return nil, status.Error(codes.AlreadyExists, "Metric with identifer already exists")
+	}
+
+	// Build a new metric out of the request
+	metric = req.Metric
+
+	// Append metric
+	metricIndex[req.Metric.Id] = metric
+	metrics = append(metrics, metric)
+
+	return
+}
+
+// UpdateMetric updates an existing metric, specified by the identifier in req.MetricId.
+func (*Service) UpdateMetric(_ context.Context, req *orchestrator.UpdateMetricRequest) (metric *assessment.Metric, err error) {
+	var ok bool
+
+	// Validate the metric request
+	err = req.Metric.Validate()
+	if err != nil {
+		return nil, status.Errorf(codes.InvalidArgument, "Validation of metric failed: %v", err)
+	}
+
+	// Check, if metric exists according to req.MetricId
+	if metric, ok = metricIndex[req.MetricId]; !ok {
+		return nil, status.Error(codes.NotFound, "Metric with identifer does not exist")
+	}
+
+	// Update metric
+	metric.Name = req.Metric.Name
+	metric.Description = req.Metric.Description
+	metric.Category = req.Metric.Category
+	metric.Range = req.Metric.Range
+	metric.Scale = req.Metric.Scale
+
+	return
+}
+
+// ListMetrics lists all available metrics.
+func (*Service) ListMetrics(_ context.Context, _ *orchestrator.ListMetricsRequest) (response *orchestrator.ListMetricsResponse, err error) {
+	response = &orchestrator.ListMetricsResponse{
+		Metrics: metrics,
+	}
+
+	return response, nil
+}
+
+// GetMetric retrieves a metric specified by req.MetridId
+func (*Service) GetMetric(_ context.Context, req *orchestrator.GetMetricRequest) (metric *assessment.Metric, err error) {
+	var ok bool
+
+	if metric, ok = metricIndex[req.MetricId]; !ok {
+		return nil, status.Errorf(codes.NotFound, "could not find metric with id %s", req.MetricId)
+	}
+
+	return
+}
diff --git a/service/orchestrator/orchestrator.go b/service/orchestrator/orchestrator.go
index 06203b83..5f8f1d64 100644
--- a/service/orchestrator/orchestrator.go
+++ b/service/orchestrator/orchestrator.go
@@ -30,11 +30,12 @@ import (
 	"embed"
 	"encoding/json"
 	"fmt"
-	"google.golang.org/protobuf/types/known/emptypb"
 	"io"
 	"io/ioutil"
 	"sync"
 
+	"google.golang.org/protobuf/types/known/emptypb"
+
 	"clouditor.io/clouditor/api/assessment"
 	"clouditor.io/clouditor/api/orchestrator"
 	"clouditor.io/clouditor/persistence"
@@ -70,19 +71,37 @@ type Service struct {
 	mu sync.Mutex
 
 	db *gorm.DB
+
+	metricsFile string
 }
 
 func init() {
 	log = logrus.WithField("component", "orchestrator")
 }
 
-func NewService() *Service {
+// ServiceOption is a function-style option to configure the Orchestrator Service
+type ServiceOption func(*Service)
+
+// WithMetricsFile can be used to load a different metrics file
+func WithMetricsFile(file string) ServiceOption {
+	return func(s *Service) {
+		s.metricsFile = file
+	}
+}
+
+func NewService(opts ...ServiceOption) *Service {
 	s := Service{
 		results:              make(map[string]*assessment.AssessmentResult),
 		metricConfigurations: make(map[string]map[string]*assessment.MetricConfiguration),
+		metricsFile:          DefaultMetricsFile,
 	}
 
-	if err := LoadMetrics(DefaultMetricsFile); err != nil {
+	// Apply service options
+	for _, o := range opts {
+		o(&s)
+	}
+
+	if err := LoadMetrics(s.metricsFile); err != nil {
 		log.Errorf("Could not load embedded metrics. Will continue with empty metric list: %v", err)
 	}
 
@@ -118,46 +137,6 @@ func NewService() *Service {
 	return &s
 }
 
-// LoadMetrics loads metrics definitions from a JSON file.
-func LoadMetrics(metricsFile string) (err error) {
-	var (
-		b []byte
-	)
-
-	b, err = f.ReadFile(metricsFile)
-	if err != nil {
-		return fmt.Errorf("error while loading %s: %w", metricsFile, err)
-	}
-
-	err = json.Unmarshal(b, &metrics)
-	if err != nil {
-		return fmt.Errorf("error in JSON marshal: %w", err)
-	}
-
-	return nil
-}
-
-func (*Service) ListMetrics(_ context.Context, _ *orchestrator.ListMetricsRequest) (response *orchestrator.ListMetricsResponse, err error) {
-	response = &orchestrator.ListMetricsResponse{
-		Metrics: metrics,
-	}
-
-	return response, nil
-}
-
-func (*Service) GetMetric(_ context.Context, request *orchestrator.GetMetricsRequest) (response *assessment.Metric, err error) {
-	var ok bool
-	var metric *assessment.Metric
-
-	if metric, ok = metricIndex[request.MetricId]; !ok {
-		return nil, status.Errorf(codes.NotFound, "could not find metric with id %s", request.MetricId)
-	}
-
-	response = metric
-
-	return response, nil
-}
-
 func (s *Service) GetMetricConfiguration(_ context.Context, req *orchestrator.GetMetricConfigurationRequest) (response *assessment.MetricConfiguration, err error) {
 	// Check, if we have a specific configuration for the metric
 	if config, ok := s.metricConfigurations[req.ServiceId][req.MetricId]; ok {


Test patch:
diff --git a/api/assessment/metric_test.go b/api/assessment/metric_test.go
new file mode 100644
index 00000000..deec2e67
--- /dev/null
+++ b/api/assessment/metric_test.go
@@ -0,0 +1,80 @@
+package assessment
+
+import (
+	"fmt"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestMetric_Validate(t *testing.T) {
+	type fields struct {
+		metric *Metric
+	}
+	type args struct {
+		opts []MetricValidationOption
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr assert.ErrorAssertionFunc
+	}{
+		{
+			name: "Metric is nil",
+			fields: fields{
+				metric: nil,
+			},
+			args: args{opts: []MetricValidationOption{
+				WithMetricRequiresId(),
+			}},
+			wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
+				return assert.ErrorIs(t, ErrMetricEmpty, err)
+			},
+		},
+		{
+			name: "Metric ID is empty",
+			fields: fields{
+				metric: &Metric{Id: ""},
+			},
+			args: args{opts: []MetricValidationOption{
+				WithMetricRequiresId(),
+			}},
+			wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
+				return assert.ErrorIs(t, ErrMetricIdMissing, err)
+			},
+		},
+		{
+			name: "Metric Name is empty",
+			fields: fields{
+				metric: &Metric{Id: "123"},
+			},
+			args: args{opts: []MetricValidationOption{
+				WithMetricRequiresId(),
+			}},
+			wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
+				return assert.ErrorIs(t, ErrMetricNameMissing, err)
+			},
+		},
+		{
+			name: "Successful Validation",
+			fields: fields{
+				metric: &Metric{
+					Id:   "SomeId",
+					Name: "SomeName1",
+				},
+			},
+			args: args{opts: []MetricValidationOption{
+				WithMetricRequiresId(),
+			}},
+			wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
+				return assert.Nil(t, err)
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			m := tt.fields.metric
+			tt.wantErr(t, m.Validate(tt.args.opts...), fmt.Sprintf("Validate(%v)", tt.args.opts))
+		})
+	}
+}
diff --git a/service/orchestrator/metrics_test.go b/service/orchestrator/metrics_test.go
new file mode 100644
index 00000000..93c83130
--- /dev/null
+++ b/service/orchestrator/metrics_test.go
@@ -0,0 +1,235 @@
+// Copyright 2022 Fraunhofer AISEC
+//
+// 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.
+//
+//           $$\                           $$\ $$\   $$\
+//           $$ |                          $$ |\__|  $$ |
+//  $$$$$$$\ $$ | $$$$$$\  $$\   $$\  $$$$$$$ |$$\ $$$$$$\    $$$$$$\   $$$$$$\
+// $$  _____|$$ |$$  __$$\ $$ |  $$ |$$  __$$ |$$ |\_$$  _|  $$  __$$\ $$  __$$\
+// $$ /      $$ |$$ /  $$ |$$ |  $$ |$$ /  $$ |$$ |  $$ |    $$ /  $$ |$$ | \__|
+// $$ |      $$ |$$ |  $$ |$$ |  $$ |$$ |  $$ |$$ |  $$ |$$\ $$ |  $$ |$$ |
+// \$$$$$$\  $$ |\$$$$$   |\$$$$$   |\$$$$$$  |$$ |  \$$$   |\$$$$$   |$$ |
+//  \_______|\__| \______/  \______/  \_______|\__|   \____/  \______/ \__|
+//
+// This file is part of Clouditor Community Edition.
+
+package orchestrator
+
+import (
+	"context"
+	"io/fs"
+	"testing"
+
+	"clouditor.io/clouditor/api/assessment"
+	"clouditor.io/clouditor/api/orchestrator"
+	"github.com/stretchr/testify/assert"
+	"google.golang.org/protobuf/proto"
+	"google.golang.org/protobuf/types/known/structpb"
+)
+
+func TestLoadMetrics(t *testing.T) {
+	var err = LoadMetrics("notfound.json")
+
+	assert.ErrorIs(t, err, fs.ErrNotExist)
+
+	err = LoadMetrics("metrics.json")
+
+	assert.Nil(t, err)
+}
+
+func TestService_CreateMetric(t *testing.T) {
+	type args struct {
+		in0 context.Context
+		req *orchestrator.CreateMetricRequest
+	}
+	tests := []struct {
+		name       string
+		args       args
+		wantMetric *assessment.Metric
+		wantErr    bool
+	}{
+		{
+			name: "Create valid metric",
+			args: args{
+				context.TODO(),
+				&orchestrator.CreateMetricRequest{
+					Metric: &assessment.Metric{
+						Id:   "MyTransportEncryptionEnabled",
+						Name: "A very good metric",
+					},
+				},
+			},
+			wantMetric: &assessment.Metric{
+				Id:   "MyTransportEncryptionEnabled",
+				Name: "A very good metric",
+			},
+			wantErr: false,
+		},
+		{
+			name: "Create invalid metric",
+			args: args{
+				context.TODO(),
+				&orchestrator.CreateMetricRequest{
+					Metric: &assessment.Metric{},
+				},
+			},
+			wantMetric: nil,
+			wantErr:    true,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			gotMetric, err := service.CreateMetric(tt.args.in0, tt.args.req)
+
+			if (err != nil) != tt.wantErr {
+				t.Errorf("Service.CreateMetric() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !proto.Equal(gotMetric, tt.wantMetric) {
+				t.Errorf("Service.CreateMetric() = %v, want %v", gotMetric, tt.wantMetric)
+			}
+		})
+	}
+}
+
+func TestService_UpdateMetric(t *testing.T) {
+	type args struct {
+		in0 context.Context
+		req *orchestrator.UpdateMetricRequest
+	}
+	tests := []struct {
+		name       string
+		args       args
+		wantMetric *assessment.Metric
+		wantErr    bool
+	}{
+		{
+			name: "Update existing metric",
+			args: args{
+				context.TODO(),
+				&orchestrator.UpdateMetricRequest{
+					MetricId: "TransportEncryptionEnabled",
+					Metric: &assessment.Metric{
+						Name: "A slightly updated metric",
+					},
+				},
+			},
+			wantMetric: &assessment.Metric{
+				Id:   "TransportEncryptionEnabled",
+				Name: "A slightly updated metric",
+			},
+			wantErr: false,
+		},
+		{
+			name: "Update non-existing metric",
+			args: args{
+				context.TODO(),
+				&orchestrator.UpdateMetricRequest{
+					MetricId: "DoesProbablyNotExist",
+				},
+			},
+			wantMetric: nil,
+			wantErr:    true,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			service = NewService()
+			gotMetric, err := service.UpdateMetric(tt.args.in0, tt.args.req)
+
+			if (err != nil) != tt.wantErr {
+				t.Errorf("Service.UpdateMetric() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !proto.Equal(gotMetric, tt.wantMetric) {
+				t.Errorf("Service.UpdateMetric() = %v, want %v", gotMetric, tt.wantMetric)
+			}
+		})
+	}
+}
+
+func TestService_GetMetric(t *testing.T) {
+	type args struct {
+		in0 context.Context
+		req *orchestrator.GetMetricRequest
+	}
+	tests := []struct {
+		name       string
+		args       args
+		wantMetric *assessment.Metric
+		wantErr    bool
+	}{
+		{
+			name: "Get existing metric",
+			args: args{
+				context.TODO(),
+				&orchestrator.GetMetricRequest{
+					MetricId: "TransportEncryptionEnabled",
+				},
+			},
+			wantMetric: &assessment.Metric{
+				Id:          "TransportEncryptionEnabled",
+				Name:        "Transport Encryption: Enabled",
+				Description: "This metric describes, whether transport encryption is turned on or not",
+				Scale:       assessment.Metric_ORDINAL,
+				Range: &assessment.Range{
+					Range: &assessment.Range_AllowedValues{AllowedValues: &assessment.AllowedValues{
+						Values: []*structpb.Value{
+							structpb.NewBoolValue(false),
+							structpb.NewBoolValue(true),
+						}}}},
+			},
+			wantErr: false,
+		},
+		{
+			name: "Get non-existing metric",
+			args: args{
+				context.TODO(),
+				&orchestrator.GetMetricRequest{
+					MetricId: "DoesProbablyNotExist",
+				},
+			},
+			wantMetric: nil,
+			wantErr:    true,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			service = NewService()
+			gotMetric, err := service.GetMetric(tt.args.in0, tt.args.req)
+
+			if (err != nil) != tt.wantErr {
+				t.Errorf("Service.GetMetric() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !proto.Equal(gotMetric, tt.wantMetric) {
+				t.Errorf("Service.GetMetric() = %v, want %v", gotMetric, tt.wantMetric)
+			}
+		})
+	}
+}
+
+func TestService_ListMetrics(t *testing.T) {
+	var (
+		response *orchestrator.ListMetricsResponse
+		err      error
+	)
+
+	response, err = service.ListMetrics(context.TODO(), &orchestrator.ListMetricsRequest{})
+
+	assert.Nil(t, err)
+	assert.NotEmpty(t, response.Metrics)
+}
diff --git a/service/orchestrator/orchestrator_test.go b/service/orchestrator/orchestrator_test.go
index 511496eb..386adabd 100644
--- a/service/orchestrator/orchestrator_test.go
+++ b/service/orchestrator/orchestrator_test.go
@@ -28,7 +28,6 @@ package orchestrator
 import (
 	"context"
 	"io"
-	"io/fs"
 	"os"
 	"reflect"
 	"runtime"
@@ -177,18 +176,6 @@ func TestAssessmentResultHook(t *testing.T) {
 	}
 }
 
-func TestListMetrics(t *testing.T) {
-	var (
-		response *orchestrator.ListMetricsResponse
-		err      error
-	)
-
-	response, err = service.ListMetrics(context.TODO(), &orchestrator.ListMetricsRequest{})
-
-	assert.Nil(t, err)
-	assert.NotEmpty(t, response.Metrics)
-}
-
 func TestListMetricConfigurations(t *testing.T) {
 	var (
 		response *orchestrator.ListMetricConfigurationResponse
@@ -201,24 +188,6 @@ func TestListMetricConfigurations(t *testing.T) {
 	assert.NotEmpty(t, response.Configurations)
 }
 
-func TestGetMetric(t *testing.T) {
-	var (
-		request *orchestrator.GetMetricsRequest
-		metric  *assessment.Metric
-		err     error
-	)
-
-	request = &orchestrator.GetMetricsRequest{
-		MetricId: "TransportEncryptionEnabled",
-	}
-
-	metric, err = service.GetMetric(context.TODO(), request)
-
-	assert.Nil(t, err)
-	assert.NotNil(t, metric)
-	assert.Equal(t, request.MetricId, metric.Id)
-}
-
 func TestStoreAssessmentResult(t *testing.T) {
 	type args struct {
 		in0        context.Context
@@ -328,16 +297,6 @@ func TestStoreAssessmentResults(t *testing.T) {
 	}
 }
 
-func TestLoad(t *testing.T) {
-	var err = LoadMetrics("notfound.json")
-
-	assert.ErrorIs(t, err, fs.ErrNotExist)
-
-	err = LoadMetrics("metrics.json")
-
-	assert.Nil(t, err)
-}
-
 type mockStreamer struct {
 	counter int
 }