<commit_before>package storage

import (
	"io"
	"time"

	"github.com/lxc/lxd/lxd/backup"
	backupConfig "github.com/lxc/lxd/lxd/backup/config"
	"github.com/lxc/lxd/lxd/cluster/request"
	"github.com/lxc/lxd/lxd/instance"
	"github.com/lxc/lxd/lxd/migration"
	"github.com/lxc/lxd/lxd/operations"
	"github.com/lxc/lxd/lxd/revert"
	"github.com/lxc/lxd/lxd/state"
	"github.com/lxc/lxd/lxd/storage/drivers"
	"github.com/lxc/lxd/shared/api"
	"github.com/lxc/lxd/shared/instancewriter"
	"github.com/lxc/lxd/shared/logger"
)

type mockBackend struct {
	name   string
	state  *state.State
	logger logger.Logger
	driver drivers.Driver
}

func (b *mockBackend) ID() int64 {
	return 1 //  The tests expect the storage pool ID to be 1.
}

func (b *mockBackend) Name() string {
	return b.name
}

func (b *mockBackend) Description() string {
	return ""
}

func (b *mockBackend) ValidateName(value string) error {
	return nil
}

func (b *mockBackend) Validate(config map[string]string) error {
	return nil
}

func (b *mockBackend) Status() string {
	return api.NetworkStatusUnknown
}

func (b *mockBackend) LocalStatus() string {
	return api.NetworkStatusUnknown
}

func (b *mockBackend) ToAPI() api.StoragePool {
	return api.StoragePool{}
}

func (b *mockBackend) Driver() drivers.Driver {
	return b.driver
}

func (b *mockBackend) MigrationTypes(contentType drivers.ContentType, refresh bool) []migration.Type {
	return []migration.Type{
		{
			FSType:   FallbackMigrationType(contentType),
			Features: []string{"xattrs", "delete", "compress", "bidirectional"},
		},
	}
}

func (b *mockBackend) GetResources() (*api.ResourcesStoragePool, error) {
	return nil, nil
}

func (b *mockBackend) IsUsed() (bool, error) {
	return false, nil
}

func (b *mockBackend) Delete(clientType request.ClientType, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) Update(clientType request.ClientType, newDescription string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) Create(clientType request.ClientType, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) Mount() (bool, error) {
	return true, nil
}

func (b *mockBackend) Unmount() (bool, error) {
	return true, nil
}

func (b *mockBackend) ApplyPatch(name string) error {
	return nil
}

func (b *mockBackend) GetVolume(volType drivers.VolumeType, contentType drivers.ContentType, volName string, volConfig map[string]string) drivers.Volume {
	return drivers.Volume{}
}

func (b *mockBackend) CreateInstance(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceFromBackup(srcBackup backup.Info, srcData io.ReadSeeker, op *operations.Operation) (func(instance.Instance) error, revert.Hook, error) {
	return nil, nil, nil
}

func (b *mockBackend) CreateInstanceFromCopy(inst instance.Instance, src instance.Instance, snapshots bool, allowInconsistent bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceFromImage(inst instance.Instance, fingerprint string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceFromMigration(inst instance.Instance, conn io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameInstance(inst instance.Instance, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteInstance(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateInstance(inst instance.Instance, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) GenerateCustomVolumeBackupConfig(projectName string, volName string, snapshots bool, op *operations.Operation) (*backupConfig.Config, error) {
	return nil, nil
}

func (b *mockBackend) GenerateInstanceBackupConfig(inst instance.Instance, snapshots bool, op *operations.Operation) (*backupConfig.Config, error) {
	return nil, nil
}

func (b *mockBackend) UpdateInstanceBackupFile(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CheckInstanceBackupFileSnapshots(backupConf *backupConfig.Config, projectName string, deleteMissing bool, op *operations.Operation) ([]*api.InstanceSnapshot, error) {
	return nil, nil
}

func (b *mockBackend) ListUnknownVolumes(op *operations.Operation) (map[string][]*backupConfig.Config, error) {
	return nil, nil
}

func (b *mockBackend) ImportInstance(inst instance.Instance, poolVol *backupConfig.Config, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MigrateInstance(inst instance.Instance, conn io.ReadWriteCloser, args *migration.VolumeSourceArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RefreshCustomVolume(projectName string, srcProjectName string, volName string, desc string, config map[string]string, srcPoolName, srcVolName string, srcVolOnly bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RefreshInstance(inst instance.Instance, src instance.Instance, srcSnapshots []instance.Instance, allowInconsistent bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) BackupInstance(inst instance.Instance, tarWriter *instancewriter.InstanceTarWriter, optimized bool, snapshots bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) GetInstanceUsage(inst instance.Instance) (int64, error) {
	return 0, nil
}

func (b *mockBackend) SetInstanceQuota(inst instance.Instance, size string, vmStateSize string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MountInstance(inst instance.Instance, op *operations.Operation) (*MountInfo, error) {
	return &MountInfo{}, nil
}

func (b *mockBackend) UnmountInstance(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceSnapshot(i instance.Instance, src instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameInstanceSnapshot(inst instance.Instance, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteInstanceSnapshot(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RestoreInstanceSnapshot(inst instance.Instance, src instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MountInstanceSnapshot(inst instance.Instance, op *operations.Operation) (*MountInfo, error) {
	return &MountInfo{}, nil
}

func (b *mockBackend) UnmountInstanceSnapshot(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateInstanceSnapshot(inst instance.Instance, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) EnsureImage(fingerprint string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteImage(fingerprint string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateImage(fingerprint, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolume(projectName string, volName string, desc string, config map[string]string, contentType drivers.ContentType, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeFromCopy(projectName string, srcProjectName string, volName string, desc string, config map[string]string, srcPoolName string, srcVolName string, srcVolOnly bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameCustomVolume(projectName string, volName string, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateCustomVolume(projectName string, volName string, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return drivers.ErrNotImplemented
}

func (b *mockBackend) DeleteCustomVolume(projectName string, volName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MigrateCustomVolume(projectName string, conn io.ReadWriteCloser, args *migration.VolumeSourceArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeFromMigration(projectName string, conn io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) GetCustomVolumeDisk(projectName string, volName string) (string, error) {
	return "", nil
}

func (b *mockBackend) GetCustomVolumeUsage(projectName string, volName string) (int64, error) {
	return 0, nil
}

func (b *mockBackend) MountCustomVolume(projectName string, volName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UnmountCustomVolume(projectName string, volName string, op *operations.Operation) (bool, error) {
	return true, nil
}

func (b *mockBackend) ImportCustomVolume(projectName string, poolVol *backupConfig.Config, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeSnapshot(projectName string, volName string, newSnapshotName string, expiryDate time.Time, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameCustomVolumeSnapshot(projectName string, volName string, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteCustomVolumeSnapshot(projectName string, volName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateCustomVolumeSnapshot(projectName string, volName string, newDesc string, newConfig map[string]string, expiryDate time.Time, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RestoreCustomVolume(projectName string, volName string, snapshotName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) BackupCustomVolume(projectName string, volName string, tarWriter *instancewriter.InstanceTarWriter, optimized bool, snapshots bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeFromBackup(srcBackup backup.Info, srcData io.ReadSeeker, op *operations.Operation) error {
	return nil
}
<commit_msg>lxd/storage/backend/mock: Removes use of drivers.ErrNotImplemented<commit_after>package storage

import (
	"io"
	"time"

	"github.com/lxc/lxd/lxd/backup"
	backupConfig "github.com/lxc/lxd/lxd/backup/config"
	"github.com/lxc/lxd/lxd/cluster/request"
	"github.com/lxc/lxd/lxd/instance"
	"github.com/lxc/lxd/lxd/migration"
	"github.com/lxc/lxd/lxd/operations"
	"github.com/lxc/lxd/lxd/revert"
	"github.com/lxc/lxd/lxd/state"
	"github.com/lxc/lxd/lxd/storage/drivers"
	"github.com/lxc/lxd/shared/api"
	"github.com/lxc/lxd/shared/instancewriter"
	"github.com/lxc/lxd/shared/logger"
)

type mockBackend struct {
	name   string
	state  *state.State
	logger logger.Logger
	driver drivers.Driver
}

func (b *mockBackend) ID() int64 {
	return 1 //  The tests expect the storage pool ID to be 1.
}

func (b *mockBackend) Name() string {
	return b.name
}

func (b *mockBackend) Description() string {
	return ""
}

func (b *mockBackend) ValidateName(value string) error {
	return nil
}

func (b *mockBackend) Validate(config map[string]string) error {
	return nil
}

func (b *mockBackend) Status() string {
	return api.NetworkStatusUnknown
}

func (b *mockBackend) LocalStatus() string {
	return api.NetworkStatusUnknown
}

func (b *mockBackend) ToAPI() api.StoragePool {
	return api.StoragePool{}
}

func (b *mockBackend) Driver() drivers.Driver {
	return b.driver
}

func (b *mockBackend) MigrationTypes(contentType drivers.ContentType, refresh bool) []migration.Type {
	return []migration.Type{
		{
			FSType:   FallbackMigrationType(contentType),
			Features: []string{"xattrs", "delete", "compress", "bidirectional"},
		},
	}
}

func (b *mockBackend) GetResources() (*api.ResourcesStoragePool, error) {
	return nil, nil
}

func (b *mockBackend) IsUsed() (bool, error) {
	return false, nil
}

func (b *mockBackend) Delete(clientType request.ClientType, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) Update(clientType request.ClientType, newDescription string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) Create(clientType request.ClientType, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) Mount() (bool, error) {
	return true, nil
}

func (b *mockBackend) Unmount() (bool, error) {
	return true, nil
}

func (b *mockBackend) ApplyPatch(name string) error {
	return nil
}

func (b *mockBackend) GetVolume(volType drivers.VolumeType, contentType drivers.ContentType, volName string, volConfig map[string]string) drivers.Volume {
	return drivers.Volume{}
}

func (b *mockBackend) CreateInstance(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceFromBackup(srcBackup backup.Info, srcData io.ReadSeeker, op *operations.Operation) (func(instance.Instance) error, revert.Hook, error) {
	return nil, nil, nil
}

func (b *mockBackend) CreateInstanceFromCopy(inst instance.Instance, src instance.Instance, snapshots bool, allowInconsistent bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceFromImage(inst instance.Instance, fingerprint string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceFromMigration(inst instance.Instance, conn io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameInstance(inst instance.Instance, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteInstance(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateInstance(inst instance.Instance, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) GenerateCustomVolumeBackupConfig(projectName string, volName string, snapshots bool, op *operations.Operation) (*backupConfig.Config, error) {
	return nil, nil
}

func (b *mockBackend) GenerateInstanceBackupConfig(inst instance.Instance, snapshots bool, op *operations.Operation) (*backupConfig.Config, error) {
	return nil, nil
}

func (b *mockBackend) UpdateInstanceBackupFile(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CheckInstanceBackupFileSnapshots(backupConf *backupConfig.Config, projectName string, deleteMissing bool, op *operations.Operation) ([]*api.InstanceSnapshot, error) {
	return nil, nil
}

func (b *mockBackend) ListUnknownVolumes(op *operations.Operation) (map[string][]*backupConfig.Config, error) {
	return nil, nil
}

func (b *mockBackend) ImportInstance(inst instance.Instance, poolVol *backupConfig.Config, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MigrateInstance(inst instance.Instance, conn io.ReadWriteCloser, args *migration.VolumeSourceArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RefreshCustomVolume(projectName string, srcProjectName string, volName string, desc string, config map[string]string, srcPoolName, srcVolName string, srcVolOnly bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RefreshInstance(inst instance.Instance, src instance.Instance, srcSnapshots []instance.Instance, allowInconsistent bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) BackupInstance(inst instance.Instance, tarWriter *instancewriter.InstanceTarWriter, optimized bool, snapshots bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) GetInstanceUsage(inst instance.Instance) (int64, error) {
	return 0, nil
}

func (b *mockBackend) SetInstanceQuota(inst instance.Instance, size string, vmStateSize string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MountInstance(inst instance.Instance, op *operations.Operation) (*MountInfo, error) {
	return &MountInfo{}, nil
}

func (b *mockBackend) UnmountInstance(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateInstanceSnapshot(i instance.Instance, src instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameInstanceSnapshot(inst instance.Instance, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteInstanceSnapshot(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RestoreInstanceSnapshot(inst instance.Instance, src instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MountInstanceSnapshot(inst instance.Instance, op *operations.Operation) (*MountInfo, error) {
	return &MountInfo{}, nil
}

func (b *mockBackend) UnmountInstanceSnapshot(inst instance.Instance, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateInstanceSnapshot(inst instance.Instance, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) EnsureImage(fingerprint string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteImage(fingerprint string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateImage(fingerprint, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolume(projectName string, volName string, desc string, config map[string]string, contentType drivers.ContentType, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeFromCopy(projectName string, srcProjectName string, volName string, desc string, config map[string]string, srcPoolName string, srcVolName string, srcVolOnly bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameCustomVolume(projectName string, volName string, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateCustomVolume(projectName string, volName string, newDesc string, newConfig map[string]string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteCustomVolume(projectName string, volName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) MigrateCustomVolume(projectName string, conn io.ReadWriteCloser, args *migration.VolumeSourceArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeFromMigration(projectName string, conn io.ReadWriteCloser, args migration.VolumeTargetArgs, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) GetCustomVolumeDisk(projectName string, volName string) (string, error) {
	return "", nil
}

func (b *mockBackend) GetCustomVolumeUsage(projectName string, volName string) (int64, error) {
	return 0, nil
}

func (b *mockBackend) MountCustomVolume(projectName string, volName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UnmountCustomVolume(projectName string, volName string, op *operations.Operation) (bool, error) {
	return true, nil
}

func (b *mockBackend) ImportCustomVolume(projectName string, poolVol *backupConfig.Config, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeSnapshot(projectName string, volName string, newSnapshotName string, expiryDate time.Time, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RenameCustomVolumeSnapshot(projectName string, volName string, newName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) DeleteCustomVolumeSnapshot(projectName string, volName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) UpdateCustomVolumeSnapshot(projectName string, volName string, newDesc string, newConfig map[string]string, expiryDate time.Time, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) RestoreCustomVolume(projectName string, volName string, snapshotName string, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) BackupCustomVolume(projectName string, volName string, tarWriter *instancewriter.InstanceTarWriter, optimized bool, snapshots bool, op *operations.Operation) error {
	return nil
}

func (b *mockBackend) CreateCustomVolumeFromBackup(srcBackup backup.Info, srcData io.ReadSeeker, op *operations.Operation) error {
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Knative Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package resources

import (
	"context"
	"fmt"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"knative.dev/eventing/pkg/apis/eventing"
	v1 "knative.dev/eventing/pkg/apis/eventing/v1"
	"knative.dev/pkg/kmeta"

	"knative.dev/eventing-autoscaler-keda/pkg/reconciler/keda"

	kedav1alpha1 "knative.dev/eventing-autoscaler-keda/third_party/pkg/apis/keda/v1alpha1"
)

// This has to stay in sync with:
// https://github.com/knative-sandbox/eventing-rabbitmq/blob/master/pkg/reconciler/broker/resources/secret.go#L29
const brokerURLSecretKey = "brokerURL"

// DispatcherLabels generates the labels present on all resources representing the dispatcher of the given
// Broker.
func dispatcherLabels(brokerName string) map[string]string {
	return map[string]string{
		eventing.BrokerLabelKey:           brokerName,
		"eventing.knative.dev/brokerRole": "dispatcher",
	}
}

// Consider refactoring this so that we can reuse more of the pkg/reconciler/keda/resources
const (
	defaultPollingInterval = 30
	defaultCooldownPeriod  = 300
	defaultMinReplicaCount = 0
	defaultMaxReplicaCount = 50
	defaultQueueLength     = "1"
)

func MakeDispatcherScaledObject(ctx context.Context, b *v1.Broker, t *v1.Trigger) (*kedav1alpha1.ScaledObject, error) {
	cooldownPeriod, err := keda.GetInt32ValueFromMap(b.GetAnnotations(), keda.KedaAutoscalingCooldownPeriodAnnotation, defaultCooldownPeriod)
	if err != nil {
		return nil, err
	}
	pollingInterval, err := keda.GetInt32ValueFromMap(b.GetAnnotations(), keda.KedaAutoscalingPollingIntervalAnnotation, defaultPollingInterval)
	if err != nil {
		return nil, err
	}
	minReplicaCount, err := keda.GetInt32ValueFromMap(b.GetAnnotations(), keda.AutoscalingMinScaleAnnotation, defaultMinReplicaCount)
	if err != nil {
		return nil, err
	}
	maxReplicaCount, err := keda.GetInt32ValueFromMap(b.GetAnnotations(), keda.AutoscalingMaxScaleAnnotation, defaultMaxReplicaCount)
	if err != nil {
		return nil, err
	}

	queueLength := b.GetAnnotations()[keda.KedaAutoscalingRabbitMQQueueLength]
	if queueLength == "" {
		queueLength = defaultQueueLength
	}

	// TODO(vaikas): https://github.com/knative-sandbox/eventing-rabbitmq/issues/61
	// queueName := fmt.Sprintf("%s/%s", t.Namespace, t.Name)
	queueName := fmt.Sprintf("%s-%s", t.Namespace, t.Name)
	deploymentName := fmt.Sprintf("%s-dispatcher", t.Name)
	triggerAuthenticationName := fmt.Sprintf("%s-trigger-auth", t.Spec.Broker)

	return &kedav1alpha1.ScaledObject{
		ObjectMeta: metav1.ObjectMeta{
			Name:      t.Name,
			Namespace: t.Namespace,
			Labels:    dispatcherLabels(t.Spec.Broker),
			OwnerReferences: []metav1.OwnerReference{
				*kmeta.NewControllerRef(t),
			},
		},
		Spec: kedav1alpha1.ScaledObjectSpec{
			ScaleTargetRef: &kedav1alpha1.ScaleTarget{
				Name:       deploymentName,
				APIVersion: "apps/v1",
				Kind:       "Deployment",
			},
			PollingInterval: pollingInterval,
			CooldownPeriod:  cooldownPeriod,
			MinReplicaCount: minReplicaCount,
			MaxReplicaCount: maxReplicaCount,
			Triggers: []kedav1alpha1.ScaleTriggers{
				{
					Type: "rabbitmq",
					Metadata: map[string]string{
						"queueName":   queueName,
						"host":        brokerURLSecretKey,
						"queueLength": queueLength,
					},
					AuthenticationRef: &kedav1alpha1.ScaledObjectAuthRef{
						Name: triggerAuthenticationName,
					},
				},
			},
		},
	}, nil
}
<commit_msg>update rabbitmq queue name to match eventing-rabbitmq (#287)<commit_after>/*
Copyright 2020 The Knative Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package resources

import (
	"context"
	"fmt"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"knative.dev/eventing/pkg/apis/eventing"
	v1 "knative.dev/eventing/pkg/apis/eventing/v1"
	"knative.dev/pkg/kmeta"

	"knative.dev/eventing-autoscaler-keda/pkg/reconciler/keda"

	kedav1alpha1 "knative.dev/eventing-autoscaler-keda/third_party/pkg/apis/keda/v1alpha1"
)

// This has to stay in sync with:
// https://github.com/knative-sandbox/eventing-rabbitmq/blob/master/pkg/reconciler/broker/resources/secret.go#L29
const brokerURLSecretKey = "brokerURL"

// DispatcherLabels generates the labels present on all resources representing the dispatcher of the given
// Broker.
func dispatcherLabels(brokerName string) map[string]string {
	return map[string]string{
		eventing.BrokerLabelKey:           brokerName,
		"eventing.knative.dev/brokerRole": "dispatcher",
	}
}

// Consider refactoring this so that we can reuse more of the pkg/reconciler/keda/resources
const (
	defaultPollingInterval = 30
	defaultCooldownPeriod  = 300
	defaultMinReplicaCount = 0
	defaultMaxReplicaCount = 50
	defaultQueueLength     = "1"
)

func MakeDispatcherScaledObject(ctx context.Context, b *v1.Broker, t *v1.Trigger) (*kedav1alpha1.ScaledObject, error) {
	cooldownPeriod, err := keda.GetInt32ValueFromMap(b.GetAnnotations(), keda.KedaAutoscalingCooldownPeriodAnnotation, defaultCooldownPeriod)
	if err != nil {
		return nil, err
	}
	pollingInterval, err := keda.GetInt32ValueFromMap(b.GetAnnotations(), keda.KedaAutoscalingPollingIntervalAnnotation, defaultPollingInterval)
	if err != nil {
		return nil, err
	}
	minReplicaCount, err := keda.GetInt32ValueFromMap(b.GetAnnotations(), keda.AutoscalingMinScaleAnnotation, defaultMinReplicaCount)
	if err != nil {
		return nil, err
	}
	maxReplicaCount, err := keda.GetInt32ValueFromMap(b.GetAnnotations(), keda.AutoscalingMaxScaleAnnotation, defaultMaxReplicaCount)
	if err != nil {
		return nil, err
	}

	queueLength := b.GetAnnotations()[keda.KedaAutoscalingRabbitMQQueueLength]
	if queueLength == "" {
		queueLength = defaultQueueLength
	}

	queueName := fmt.Sprintf("%s.%s.%s", t.Namespace, t.Name, b.GetUID())
	deploymentName := fmt.Sprintf("%s-dispatcher", t.Name)
	triggerAuthenticationName := fmt.Sprintf("%s-trigger-auth", t.Spec.Broker)

	return &kedav1alpha1.ScaledObject{
		ObjectMeta: metav1.ObjectMeta{
			Name:      t.Name,
			Namespace: t.Namespace,
			Labels:    dispatcherLabels(t.Spec.Broker),
			OwnerReferences: []metav1.OwnerReference{
				*kmeta.NewControllerRef(t),
			},
		},
		Spec: kedav1alpha1.ScaledObjectSpec{
			ScaleTargetRef: &kedav1alpha1.ScaleTarget{
				Name:       deploymentName,
				APIVersion: "apps/v1",
				Kind:       "Deployment",
			},
			PollingInterval: pollingInterval,
			CooldownPeriod:  cooldownPeriod,
			MinReplicaCount: minReplicaCount,
			MaxReplicaCount: maxReplicaCount,
			Triggers: []kedav1alpha1.ScaleTriggers{
				{
					Type: "rabbitmq",
					Metadata: map[string]string{
						"queueName":   queueName,
						"host":        brokerURLSecretKey,
						"queueLength": queueLength,
					},
					AuthenticationRef: &kedav1alpha1.ScaledObjectAuthRef{
						Name: triggerAuthenticationName,
					},
				},
			},
		},
	}, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package main

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"io"
	"log"
	"os"
	"strings"
	"time"

	"github.com/m3db/m3/src/cmd/tools"
	"github.com/m3db/m3/src/dbnode/encoding"
	"github.com/m3db/m3/src/dbnode/encoding/m3tsz"
	"github.com/m3db/m3/src/dbnode/persist"
	"github.com/m3db/m3/src/dbnode/persist/fs"
	"github.com/m3db/m3/src/x/ident"

	"github.com/pborman/getopt"
	"go.uber.org/zap"
)

const snapshotType = "snapshot"
const flushType = "flush"

func main() {
	var (
		optPathPrefix  = getopt.StringLong("path-prefix", 'p', "", "Path prefix [e.g. /var/lib/m3db]")
		optNamespace   = getopt.StringLong("namespace", 'n', "", "Namespace [e.g. metrics]")
		optShard       = getopt.Uint32Long("shard", 's', 0, "Shard [expected format uint32]")
		optBlockstart  = getopt.Int64Long("block-start", 'b', 0, "Block Start Time [in nsec]")
		volume         = getopt.Int64Long("volume", 'v', 0, "Volume number")
		fileSetTypeArg = getopt.StringLong("fileset-type", 't', flushType, fmt.Sprintf("%s|%s", flushType, snapshotType))
		idFilter       = getopt.StringLong("id-filter", 'f', "", "ID Contains Filter (optional)")
	)
	getopt.Parse()

	rawLogger, err := zap.NewDevelopment()
	if err != nil {
		log.Fatalf("unable to create logger: %+v", err)
	}
	log := rawLogger.Sugar()

	if *optPathPrefix == "" ||
		*optNamespace == "" ||
		*optShard < 0 ||
		*optBlockstart <= 0 ||
		*volume < 0 ||
		(*fileSetTypeArg != snapshotType && *fileSetTypeArg != flushType) {
		getopt.Usage()
		os.Exit(1)
	}

	var fileSetType persist.FileSetType
	switch *fileSetTypeArg {
	case flushType:
		fileSetType = persist.FileSetFlushType
	case snapshotType:
		fileSetType = persist.FileSetSnapshotType
	default:
		log.Fatalf("unknown fileset type: %s", *fileSetTypeArg)
	}

	bytesPool := tools.NewCheckedBytesPool()
	bytesPool.Init()

	encodingOpts := encoding.NewOptions().SetBytesPool(bytesPool)

	fsOpts := fs.NewOptions().SetFilePathPrefix(*optPathPrefix)
	reader, err := fs.NewReader(bytesPool, fsOpts)
	if err != nil {
		log.Fatalf("could not create new reader: %v", err)
	}

	openOpts := fs.DataReaderOpenOptions{
		Identifier: fs.FileSetFileIdentifier{
			Namespace:   ident.StringID(*optNamespace),
			Shard:       *optShard,
			BlockStart:  time.Unix(0, *optBlockstart),
			VolumeIndex: int(*volume),
		},
		FileSetType: fileSetType,
	}

	err = reader.Open(openOpts)
	if err != nil {
		log.Fatalf("unable to open reader: %v", err)
	}

	for {
		id, _, data, _, err := reader.Read()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatalf("err reading metadata: %v", err)
		}

		if *idFilter != "" && !strings.Contains(id.String(), *idFilter) {
			continue
		}

		data.IncRef()
		iter := m3tsz.NewReaderIterator(bytes.NewReader(data.Bytes()), true, encodingOpts)
		for iter.Next() {
			dp, _, annotation := iter.Current()
			// Use fmt package so it goes to stdout instead of stderr
			fmt.Printf("{id: %s, dp: %+v", id.String(), dp)
			if len(annotation) > 0 {
				fmt.Printf(", annotation: %s", base64.StdEncoding.EncodeToString(annotation))
			}
			fmt.Println("}")
		}
		if err := iter.Err(); err != nil {
			log.Fatalf("unable to iterate original data: %v", err)
		}
		iter.Close()

		data.DecRef()
		data.Finalize()
	}
}
<commit_msg>[tools] Add benchmarking support to read_data_files (#2986)<commit_after>// Copyright (c) 2018 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package main

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"io"
	"log"
	"os"
	"strings"
	"time"

	"github.com/m3db/m3/src/cmd/tools"
	"github.com/m3db/m3/src/dbnode/encoding"
	"github.com/m3db/m3/src/dbnode/encoding/m3tsz"
	"github.com/m3db/m3/src/dbnode/persist"
	"github.com/m3db/m3/src/dbnode/persist/fs"
	"github.com/m3db/m3/src/x/ident"

	"github.com/pborman/getopt"
	"go.uber.org/zap"
)

const (
	snapshotType = "snapshot"
	flushType    = "flush"
)

type benchmarkMode uint8

const (
	// benchmarkNone prints the data read to the standard output and does not measure performance.
	benchmarkNone benchmarkMode = iota

	// benchmarkSeries benchmarks time series read performance (skipping datapoint decoding).
	benchmarkSeries

	// benchmarkDatapoints benchmarks series read, including datapoint decoding.
	benchmarkDatapoints
)

func main() {
	var (
		optPathPrefix  = getopt.StringLong("path-prefix", 'p', "", "Path prefix [e.g. /var/lib/m3db]")
		optNamespace   = getopt.StringLong("namespace", 'n', "default", "Namespace [e.g. metrics]")
		optShard       = getopt.Uint32Long("shard", 's', 0, "Shard [expected format uint32]")
		optBlockstart  = getopt.Int64Long("block-start", 'b', 0, "Block Start Time [in nsec]")
		volume         = getopt.Int64Long("volume", 'v', 0, "Volume number")
		fileSetTypeArg = getopt.StringLong("fileset-type", 't', flushType, fmt.Sprintf("%s|%s", flushType, snapshotType))
		idFilter       = getopt.StringLong("id-filter", 'f', "", "ID Contains Filter (optional)")
		benchmark      = getopt.StringLong(
			"benchmark", 'B', "", "benchmark mode (optional), [series/datapoints]")
	)
	getopt.Parse()

	rawLogger, err := zap.NewDevelopment()
	if err != nil {
		log.Fatalf("unable to create logger: %+v", err)
	}
	log := rawLogger.Sugar()

	if *optPathPrefix == "" ||
		*optNamespace == "" ||
		*optShard < 0 ||
		*optBlockstart <= 0 ||
		*volume < 0 ||
		(*fileSetTypeArg != snapshotType && *fileSetTypeArg != flushType) {
		getopt.Usage()
		os.Exit(1)
	}

	var fileSetType persist.FileSetType
	switch *fileSetTypeArg {
	case flushType:
		fileSetType = persist.FileSetFlushType
	case snapshotType:
		fileSetType = persist.FileSetSnapshotType
	default:
		log.Fatalf("unknown fileset type: %s", *fileSetTypeArg)
	}

	var benchMode benchmarkMode
	switch *benchmark {
	case "":
	case "series":
		benchMode = benchmarkSeries
	case "datapoints":
		benchMode = benchmarkDatapoints
	default:
		log.Fatalf("unknown benchmark type: %s", *benchmark)
	}

	bytesPool := tools.NewCheckedBytesPool()
	bytesPool.Init()

	encodingOpts := encoding.NewOptions().SetBytesPool(bytesPool)

	fsOpts := fs.NewOptions().SetFilePathPrefix(*optPathPrefix)

	var (
		seriesCount    = 0
		datapointCount = 0
		start          = time.Now()
	)

	reader, err := fs.NewReader(bytesPool, fsOpts)
	if err != nil {
		log.Fatalf("could not create new reader: %v", err)
	}

	openOpts := fs.DataReaderOpenOptions{
		Identifier: fs.FileSetFileIdentifier{
			Namespace:   ident.StringID(*optNamespace),
			Shard:       *optShard,
			BlockStart:  time.Unix(0, *optBlockstart),
			VolumeIndex: int(*volume),
		},
		FileSetType: fileSetType,
	}

	err = reader.Open(openOpts)
	if err != nil {
		log.Fatalf("unable to open reader: %v", err)
	}

	for {
		id, _, data, _, err := reader.Read()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatalf("err reading metadata: %v", err)
		}

		if *idFilter != "" && !strings.Contains(id.String(), *idFilter) {
			continue
		}

		if benchMode != benchmarkSeries {
			data.IncRef()

			iter := m3tsz.NewReaderIterator(bytes.NewReader(data.Bytes()), true, encodingOpts)
			for iter.Next() {
				dp, _, annotation := iter.Current()
				if benchMode == benchmarkNone {
					// Use fmt package so it goes to stdout instead of stderr
					fmt.Printf("{id: %s, dp: %+v", id.String(), dp)
					if len(annotation) > 0 {
						fmt.Printf(", annotation: %s", base64.StdEncoding.EncodeToString(annotation))
					}
					fmt.Println("}")
				}
				datapointCount++
			}
			if err := iter.Err(); err != nil {
				log.Fatalf("unable to iterate original data: %v", err)
			}
			iter.Close()

			data.DecRef()
		}

		data.Finalize()
		seriesCount++
	}

	if benchMode != benchmarkNone {
		runTime := time.Since(start)
		fmt.Printf("Running time: %s\n", runTime)
		fmt.Printf("\n%d series read\n", seriesCount)
		if runTime > 0 {
			fmt.Printf("(%.2f series/second)\n", float64(seriesCount)/runTime.Seconds())
		}

		if benchMode == benchmarkDatapoints {
			fmt.Printf("\n%d datapoints decoded\n", datapointCount)
			fmt.Printf("(%.2f datapoints/second)\n", float64(datapointCount)/runTime.Seconds())
		}
	}
}
<|endoftext|>


<commit_before>package checks

import (
	"bytes"
	"encoding/json"
	"errors"
	"log"
	"net"
	"os"
	"strings"

	"github.com/jonog/redalert/utils"

	"golang.org/x/crypto/ssh"
	"golang.org/x/crypto/ssh/agent"
)

func init() {
	Register("remote-docker", NewDockerRemoteDocker)
}

type RemoteDocker struct {
	User string
	Host string
	Tool string
	log  *log.Logger
}

var NewDockerRemoteDocker = func(config Config, logger *log.Logger) (Checker, error) {

	tool := utils.StringDefault(config.Tool, "nc")
	if !utils.FindStringInArray(tool, []string{"nc", "socat"}) {
		return nil, errors.New("checks: unknown tool in remote docker config")
	}

	return Checker(&RemoteDocker{
		User: config.User,
		Host: config.Host,
		Tool: tool,
		log:  logger,
	}), nil
}

func runCommand(client *ssh.Client, cmd string) (string, error) {
	session, err := client.NewSession()
	if err != nil {
		return "", nil
	}
	defer session.Close()
	var b bytes.Buffer
	session.Stdout = &b
	err = session.Run(cmd)
	if err != nil {
		return "", nil
	}
	output := b.String()
	return output, nil
}

func parseAndUnmarshal(raw string, data interface{}) error {

	httpRawSplit := strings.Split(raw, "\n\r\n")
	if len(httpRawSplit) < 2 {
		return errors.New("invalid format")
	}

	jsonStr := httpRawSplit[1]
	return json.Unmarshal([]byte(jsonStr), data)
}

func (r *RemoteDocker) dockerAPISocketAccess() string {
	if r.Tool == "nc" {
		return "nc -U /var/run/docker.sock"
	}
	if r.Tool == "socat" {
		return "socat - UNIX-CONNECT:/var/run/docker.sock"
	}
	return ""
}

func (r *RemoteDocker) dockerAPIStreamSocketAccess() string {
	if r.Tool == "nc" {
		return "nc -U /var/run/docker.sock"
	}
	if r.Tool == "socat" {
		return "socat -t 2 - UNIX-CONNECT:/var/run/docker.sock"
	}
	return ""
}

func (r *RemoteDocker) Check() (Metrics, error) {

	output := Metrics(make(map[string]*float64))

	// TODO:
	// add SSH auth options involving password / key

	sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK"))
	if err != nil {
		return output, nil
	}
	auth := ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)
	defer sshAgent.Close()

	client, err := ssh.Dial("tcp", r.Host+":"+"22", &ssh.ClientConfig{
		User: r.User,
		Auth: []ssh.AuthMethod{auth},
	})
	if err != nil {
		return output, nil
	}

	// TODO:
	// give user choice of nc -U or socat

	sshOutput, err := runCommand(client, `echo -e "GET /containers/json HTTP/1.0\r\n" | `+r.dockerAPISocketAccess())
	if err != nil {
		return output, nil
	}

	if len(sshOutput) == 0 {
		r.log.Println("ERROR: cannot get list of containers from docker remote API")
		return output, nil
	}

	var containers []Container
	err = parseAndUnmarshal(sshOutput, &containers)
	if err != nil {
		return output, nil

	}

	for _, c := range containers {

		cmd := `(timeout 3 <<<'GET /containers/` + c.Id + `/stats HTTP/1.0'$'\r'$'\n' ` + r.dockerAPIStreamSocketAccess() + ` | cat) | tail -2`

		sshOutput, err := runCommand(client, cmd)
		if err != nil {
			r.log.Println("ERROR: unable to successfully ssh to obtain container stats", err)
			continue
		}

		if len(sshOutput) == 0 {
			r.log.Println("ERROR: cannot get container stats from docker remote API")
			continue
		}

		readings := strings.Split(sshOutput, "\n")
		if len(readings) < 2 {
			r.log.Println("ERROR: two readings were not obtained from docker remote API")
			continue
		}

		var containerStats1 ContainerStats
		err = json.Unmarshal([]byte(readings[0]), &containerStats1)
		if err != nil {
			r.log.Println("ERROR: unmarshalling container stats json (1st reading)", err)
			continue
		}
		var containerStats2 ContainerStats
		err = json.Unmarshal([]byte(readings[1]), &containerStats2)
		if err != nil {
			r.log.Println("ERROR: unmarshalling container stats json (2nd reading)", err)
			continue
		}

		containerName, err := getContainerName(c.Names)
		if err != nil {
			r.log.Println("ERROR: establishing container name", err)
			continue
		}

		// TODO: collect all the metrics
		containerMemory := float64(containerStats2.MemoryStats.Usage / 1000000.0)
		output[containerName+"_memory"] = &containerMemory

		cpuUsageDelta := float64(containerStats2.CpuStats.CpuUsage.TotalUsage) - float64(containerStats1.CpuStats.CpuUsage.TotalUsage)
		systemCpuUsageDelta := float64(containerStats2.CpuStats.SystemCpuUsage) - float64(containerStats1.CpuStats.SystemCpuUsage)
		cpuUsagePercent := cpuUsageDelta * 100 / systemCpuUsageDelta

		output[containerName+"_cpu"] = &cpuUsagePercent

	}

	containerCount := float64(len(containers))
	output["container_count"] = &containerCount

	return output, nil
}

func getContainerName(names []string) string {

	// remove prefix '/'
	for _, name := range names {
		namePrefixRemoved := name[1:]

		// find container without '/' within name
		if len(strings.Split(namePrefixRemoved, "/")) == 1 {
			return namePrefixRemoved
		}
	}
	return ""
}

func (r *RemoteDocker) MetricInfo(metric string) MetricInfo {
	return MetricInfo{Unit: ""}
}

func (r *RemoteDocker) MessageContext() string {
	return "docker host - " + r.Host
}

type Container struct {
	Command string
	Created int
	Id      string
	Image   string
	Names   []string
	Ports   []PortConfig
	Status  string
}

type PortConfig struct {
	IP          string
	PrivatePort int
	PublicPort  int
	Type        string
}

type ContainerStats struct {
	Read    string `json:"read"`
	Network struct {
		RxDropped int `json:"rx_dropped"`
		RxBytes   int `json:"rx_bytes"`
		RxErrors  int `json:"rx_errors"`
		TxPackets int `json:"tx_packets"`
		TxDropped int `json:"tx_dropped"`
		RxPackets int `json:"rx_packets"`
		TxErrors  int `json:"tx_errors"`
		TxBytes   int `json:"tx_bytes"`
	} `json:"network"`
	MemoryStats struct {
		Stats struct {
			TotalRss int `json:"total_rss"`
			// TODO: add additional mem stats
		} `json:"stats"`
		MaxUsage int `json:"max_usage"`
		Usage    int `json:"usage"`
		Failcnt  int `json:"failcnt"`
		Limit    int `json:"limit"`
	} `json:"memory_stats"`
	CpuStats struct {
		CpuUsage struct {
			PercpuUsage       []int `json:"percpu_usage"`
			UsageInUsermode   int   `json:"usage_in_usermode"`
			TotalUsage        int   `json:"total_usage"`
			UsageInKernelmode int   `json:"usage_in_kernelmode"`
		} `json:"cpu_usage"`
		SystemCpuUsage int `json:"system_cpu_usage"`
	} `json:"cpu_stats"`
}
<commit_msg>Update metric names<commit_after>package checks

import (
	"bytes"
	"encoding/json"
	"errors"
	"log"
	"net"
	"os"
	"strings"

	"github.com/jonog/redalert/utils"

	"golang.org/x/crypto/ssh"
	"golang.org/x/crypto/ssh/agent"
)

func init() {
	Register("remote-docker", NewDockerRemoteDocker)
}

type RemoteDocker struct {
	User string
	Host string
	Tool string
	log  *log.Logger
}

var NewDockerRemoteDocker = func(config Config, logger *log.Logger) (Checker, error) {

	tool := utils.StringDefault(config.Tool, "nc")
	if !utils.FindStringInArray(tool, []string{"nc", "socat"}) {
		return nil, errors.New("checks: unknown tool in remote docker config")
	}

	return Checker(&RemoteDocker{
		User: config.User,
		Host: config.Host,
		Tool: tool,
		log:  logger,
	}), nil
}

func runCommand(client *ssh.Client, cmd string) (string, error) {
	session, err := client.NewSession()
	if err != nil {
		return "", nil
	}
	defer session.Close()
	var b bytes.Buffer
	session.Stdout = &b
	err = session.Run(cmd)
	if err != nil {
		return "", nil
	}
	output := b.String()
	return output, nil
}

func parseAndUnmarshal(raw string, data interface{}) error {

	httpRawSplit := strings.Split(raw, "\n\r\n")
	if len(httpRawSplit) < 2 {
		return errors.New("invalid format")
	}

	jsonStr := httpRawSplit[1]
	return json.Unmarshal([]byte(jsonStr), data)
}

func (r *RemoteDocker) dockerAPISocketAccess() string {
	if r.Tool == "nc" {
		return "nc -U /var/run/docker.sock"
	}
	if r.Tool == "socat" {
		return "socat - UNIX-CONNECT:/var/run/docker.sock"
	}
	return ""
}

func (r *RemoteDocker) dockerAPIStreamSocketAccess() string {
	if r.Tool == "nc" {
		return "nc -U /var/run/docker.sock"
	}
	if r.Tool == "socat" {
		return "socat -t 2 - UNIX-CONNECT:/var/run/docker.sock"
	}
	return ""
}

func (r *RemoteDocker) Check() (Metrics, error) {

	output := Metrics(make(map[string]*float64))

	// TODO:
	// add SSH auth options involving password / key

	sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK"))
	if err != nil {
		return output, nil
	}
	auth := ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)
	defer sshAgent.Close()

	client, err := ssh.Dial("tcp", r.Host+":"+"22", &ssh.ClientConfig{
		User: r.User,
		Auth: []ssh.AuthMethod{auth},
	})
	if err != nil {
		return output, nil
	}

	// TODO:
	// give user choice of nc -U or socat

	sshOutput, err := runCommand(client, `echo -e "GET /containers/json HTTP/1.0\r\n" | `+r.dockerAPISocketAccess())
	if err != nil {
		return output, nil
	}

	if len(sshOutput) == 0 {
		r.log.Println("ERROR: cannot get list of containers from docker remote API")
		return output, nil
	}

	var containers []Container
	err = parseAndUnmarshal(sshOutput, &containers)
	if err != nil {
		return output, nil

	}

	for _, c := range containers {

		cmd := `(timeout 3 <<<'GET /containers/` + c.Id + `/stats HTTP/1.0'$'\r'$'\n' ` + r.dockerAPIStreamSocketAccess() + ` | cat) | tail -2`

		sshOutput, err := runCommand(client, cmd)
		if err != nil {
			r.log.Println("ERROR: unable to successfully ssh to obtain container stats", err)
			continue
		}

		if len(sshOutput) == 0 {
			r.log.Println("ERROR: cannot get container stats from docker remote API")
			continue
		}

		readings := strings.Split(sshOutput, "\n")
		if len(readings) < 2 {
			r.log.Println("ERROR: two readings were not obtained from docker remote API")
			continue
		}

		var containerStats1 ContainerStats
		err = json.Unmarshal([]byte(readings[0]), &containerStats1)
		if err != nil {
			r.log.Println("ERROR: unmarshalling container stats json (1st reading)", err)
			continue
		}
		var containerStats2 ContainerStats
		err = json.Unmarshal([]byte(readings[1]), &containerStats2)
		if err != nil {
			r.log.Println("ERROR: unmarshalling container stats json (2nd reading)", err)
			continue
		}

		containerName, err := getContainerName(c.Names)
		if err != nil {
			r.log.Println("ERROR: establishing container name", err)
			continue
		}

		// TODO: collect all the metrics
		containerMemory := float64(containerStats2.MemoryStats.Usage / 1000000.0)
		output[containerName+".memory"] = &containerMemory

		cpuUsageDelta := float64(containerStats2.CpuStats.CpuUsage.TotalUsage) - float64(containerStats1.CpuStats.CpuUsage.TotalUsage)
		systemCpuUsageDelta := float64(containerStats2.CpuStats.SystemCpuUsage) - float64(containerStats1.CpuStats.SystemCpuUsage)
		cpuUsagePercent := cpuUsageDelta * 100 / systemCpuUsageDelta

		output[containerName+".cpu"] = &cpuUsagePercent

	}

	containerCount := float64(len(containers))
	output["container_count"] = &containerCount

	return output, nil
}

func getContainerName(names []string) string {

	// remove prefix '/'
	for _, name := range names {
		namePrefixRemoved := name[1:]

		// find container without '/' within name
		if len(strings.Split(namePrefixRemoved, "/")) == 1 {
			return namePrefixRemoved
		}
	}
	return ""
}

func (r *RemoteDocker) MetricInfo(metric string) MetricInfo {
	return MetricInfo{Unit: ""}
}

func (r *RemoteDocker) MessageContext() string {
	return "docker host - " + r.Host
}

type Container struct {
	Command string
	Created int
	Id      string
	Image   string
	Names   []string
	Ports   []PortConfig
	Status  string
}

type PortConfig struct {
	IP          string
	PrivatePort int
	PublicPort  int
	Type        string
}

type ContainerStats struct {
	Read    string `json:"read"`
	Network struct {
		RxDropped int `json:"rx_dropped"`
		RxBytes   int `json:"rx_bytes"`
		RxErrors  int `json:"rx_errors"`
		TxPackets int `json:"tx_packets"`
		TxDropped int `json:"tx_dropped"`
		RxPackets int `json:"rx_packets"`
		TxErrors  int `json:"tx_errors"`
		TxBytes   int `json:"tx_bytes"`
	} `json:"network"`
	MemoryStats struct {
		Stats struct {
			TotalRss int `json:"total_rss"`
			// TODO: add additional mem stats
		} `json:"stats"`
		MaxUsage int `json:"max_usage"`
		Usage    int `json:"usage"`
		Failcnt  int `json:"failcnt"`
		Limit    int `json:"limit"`
	} `json:"memory_stats"`
	CpuStats struct {
		CpuUsage struct {
			PercpuUsage       []int `json:"percpu_usage"`
			UsageInUsermode   int   `json:"usage_in_usermode"`
			TotalUsage        int   `json:"total_usage"`
			UsageInKernelmode int   `json:"usage_in_kernelmode"`
		} `json:"cpu_usage"`
		SystemCpuUsage int `json:"system_cpu_usage"`
	} `json:"cpu_stats"`
}
<|endoftext|>


<commit_before>package server

import (
	"encoding/json"
	"log"
	"time"

	"github.com/andreandradecosta/rpimonitor/models"
	"github.com/garyburd/redigo/redis"
)

type Monitor struct {
	Interval  time.Duration
	RedisPool *redis.Pool
}

func (m *Monitor) Start() {
	ticker := time.NewTicker(m.Interval)
	for {
		m.tick()
		<-ticker.C
	}
}

func (m *Monitor) tick() {
	conn := m.RedisPool.Get()
	defer conn.Close()
	conn.Send("MULTI")
	s := models.NewSample()
	conn.Send("SET", "updated", s.Timestamp)
	sample := makeJSON(s)
	conn.Send("SET", "snapshot", sample)
	status := makeJSON(models.NewStatus())
	conn.Send("SET", "status", status)
	_, err := conn.Do("EXEC")
	if err != nil {
		log.Println(err)
	}
}

func makeJSON(data interface{}) []byte {
	json, err := json.Marshal(data)
	if err != nil {
		log.Println(err)
		return nil
	}
	return json
}
<commit_msg>Just to know where is the error.<commit_after>package server

import (
	"encoding/json"
	"log"
	"time"

	"github.com/andreandradecosta/rpimonitor/models"
	"github.com/garyburd/redigo/redis"
)

type Monitor struct {
	Interval  time.Duration
	RedisPool *redis.Pool
}

func (m *Monitor) Start() {
	ticker := time.NewTicker(m.Interval)
	for {
		m.tick()
		<-ticker.C
	}
}

func (m *Monitor) tick() {
	conn := m.RedisPool.Get()
	defer conn.Close()
	conn.Send("MULTI")
	s := models.NewSample()
	conn.Send("SET", "updated", s.Timestamp)
	sample := makeJSON(s)
	conn.Send("SET", "snapshot", sample)
	status := makeJSON(models.NewStatus())
	conn.Send("SET", "status", status)
	_, err := conn.Do("EXEC")
	if err != nil {
		log.Println("tick:", err)
	}
}

func makeJSON(data interface{}) []byte {
	json, err := json.Marshal(data)
	if err != nil {
		log.Println("makeJSON:", err)
		return nil
	}
	return json
}
<|endoftext|>


<commit_before>// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package migrations

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strconv"

	base "code.gitea.io/gitea/modules/migration"

	"gopkg.in/yaml.v2"
)

// RepositoryRestorer implements an Downloader from the local directory
type RepositoryRestorer struct {
	base.NullDownloader
	ctx       context.Context
	baseDir   string
	repoOwner string
	repoName  string
}

// NewRepositoryRestorer creates a repository restorer which could restore repository from a dumped folder
func NewRepositoryRestorer(ctx context.Context, baseDir, owner, repoName string) (*RepositoryRestorer, error) {
	baseDir, err := filepath.Abs(baseDir)
	if err != nil {
		return nil, err
	}
	return &RepositoryRestorer{
		ctx:       ctx,
		baseDir:   baseDir,
		repoOwner: owner,
		repoName:  repoName,
	}, nil
}

func (r *RepositoryRestorer) commentDir() string {
	return filepath.Join(r.baseDir, "comments")
}

func (r *RepositoryRestorer) reviewDir() string {
	return filepath.Join(r.baseDir, "reviews")
}

// SetContext set context
func (r *RepositoryRestorer) SetContext(ctx context.Context) {
	r.ctx = ctx
}

func (r *RepositoryRestorer) getRepoOptions() (map[string]string, error) {
	p := filepath.Join(r.baseDir, "repo.yml")
	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, err
	}

	opts := make(map[string]string)
	err = yaml.Unmarshal(bs, &opts)
	if err != nil {
		return nil, err
	}
	return opts, nil
}

// GetRepoInfo returns a repository information
func (r *RepositoryRestorer) GetRepoInfo() (*base.Repository, error) {
	opts, err := r.getRepoOptions()
	if err != nil {
		return nil, err
	}

	isPrivate, _ := strconv.ParseBool(opts["is_private"])

	return &base.Repository{
		Owner:         r.repoOwner,
		Name:          r.repoName,
		IsPrivate:     isPrivate,
		Description:   opts["description"],
		OriginalURL:   opts["original_url"],
		CloneURL:      filepath.Join(r.baseDir, "git"),
		DefaultBranch: opts["default_branch"],
	}, nil
}

// GetTopics return github topics
func (r *RepositoryRestorer) GetTopics() ([]string, error) {
	p := filepath.Join(r.baseDir, "topic.yml")

	topics := struct {
		Topics []string `yaml:"topics"`
	}{}

	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, err
	}

	err = yaml.Unmarshal(bs, &topics)
	if err != nil {
		return nil, err
	}
	return topics.Topics, nil
}

// GetMilestones returns milestones
func (r *RepositoryRestorer) GetMilestones() ([]*base.Milestone, error) {
	milestones := make([]*base.Milestone, 0, 10)
	p := filepath.Join(r.baseDir, "milestone.yml")
	_, err := os.Stat(p)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}

	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, err
	}

	err = yaml.Unmarshal(bs, &milestones)
	if err != nil {
		return nil, err
	}
	return milestones, nil
}

// GetReleases returns releases
func (r *RepositoryRestorer) GetReleases() ([]*base.Release, error) {
	releases := make([]*base.Release, 0, 10)
	p := filepath.Join(r.baseDir, "release.yml")
	_, err := os.Stat(p)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}

	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, err
	}

	err = yaml.Unmarshal(bs, &releases)
	if err != nil {
		return nil, err
	}
	for _, rel := range releases {
		for _, asset := range rel.Assets {
			if asset.DownloadURL != nil {
				*asset.DownloadURL = "file://" + filepath.Join(r.baseDir, *asset.DownloadURL)
			}
		}
	}
	return releases, nil
}

// GetLabels returns labels
func (r *RepositoryRestorer) GetLabels() ([]*base.Label, error) {
	labels := make([]*base.Label, 0, 10)
	p := filepath.Join(r.baseDir, "label.yml")
	_, err := os.Stat(p)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}

	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, err
	}

	err = yaml.Unmarshal(bs, &labels)
	if err != nil {
		return nil, err
	}
	return labels, nil
}

// GetIssues returns issues according start and limit
func (r *RepositoryRestorer) GetIssues(page, perPage int) ([]*base.Issue, bool, error) {
	issues := make([]*base.Issue, 0, 10)
	p := filepath.Join(r.baseDir, "issue.yml")
	_, err := os.Stat(p)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, true, nil
		}
		return nil, false, err
	}

	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, false, err
	}

	err = yaml.Unmarshal(bs, &issues)
	if err != nil {
		return nil, false, err
	}
	for _, issue := range issues {
		issue.Context = base.BasicIssueContext(issue.Number)
	}
	return issues, true, nil
}

// GetComments returns comments according issueNumber
func (r *RepositoryRestorer) GetComments(opts base.GetCommentOptions) ([]*base.Comment, bool, error) {
	comments := make([]*base.Comment, 0, 10)
	p := filepath.Join(r.commentDir(), fmt.Sprintf("%d.yml", opts.Context.ForeignID()))
	_, err := os.Stat(p)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, false, nil
		}
		return nil, false, err
	}

	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, false, err
	}

	err = yaml.Unmarshal(bs, &comments)
	if err != nil {
		return nil, false, err
	}
	return comments, false, nil
}

// GetPullRequests returns pull requests according page and perPage
func (r *RepositoryRestorer) GetPullRequests(page, perPage int) ([]*base.PullRequest, bool, error) {
	pulls := make([]*base.PullRequest, 0, 10)
	p := filepath.Join(r.baseDir, "pull_request.yml")
	_, err := os.Stat(p)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, true, nil
		}
		return nil, false, err
	}

	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, false, err
	}

	err = yaml.Unmarshal(bs, &pulls)
	if err != nil {
		return nil, false, err
	}
	for _, pr := range pulls {
		pr.PatchURL = "file://" + filepath.Join(r.baseDir, pr.PatchURL)
		pr.Context = base.BasicIssueContext(pr.Number)
	}
	return pulls, true, nil
}

// GetReviews returns pull requests review
func (r *RepositoryRestorer) GetReviews(context base.IssueContext) ([]*base.Review, error) {
	reviews := make([]*base.Review, 0, 10)
	p := filepath.Join(r.reviewDir(), fmt.Sprintf("%d.yml", context.ForeignID()))
	_, err := os.Stat(p)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}

	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, err
	}

	err = yaml.Unmarshal(bs, &reviews)
	if err != nil {
		return nil, err
	}
	return reviews, nil
}
<commit_msg>Fix restore without topic failure (#18387)<commit_after>// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package migrations

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strconv"

	base "code.gitea.io/gitea/modules/migration"

	"gopkg.in/yaml.v2"
)

// RepositoryRestorer implements an Downloader from the local directory
type RepositoryRestorer struct {
	base.NullDownloader
	ctx       context.Context
	baseDir   string
	repoOwner string
	repoName  string
}

// NewRepositoryRestorer creates a repository restorer which could restore repository from a dumped folder
func NewRepositoryRestorer(ctx context.Context, baseDir, owner, repoName string) (*RepositoryRestorer, error) {
	baseDir, err := filepath.Abs(baseDir)
	if err != nil {
		return nil, err
	}
	return &RepositoryRestorer{
		ctx:       ctx,
		baseDir:   baseDir,
		repoOwner: owner,
		repoName:  repoName,
	}, nil
}

func (r *RepositoryRestorer) commentDir() string {
	return filepath.Join(r.baseDir, "comments")
}

func (r *RepositoryRestorer) reviewDir() string {
	return filepath.Join(r.baseDir, "reviews")
}

// SetContext set context
func (r *RepositoryRestorer) SetContext(ctx context.Context) {
	r.ctx = ctx
}

func (r *RepositoryRestorer) getRepoOptions() (map[string]string, error) {
	p := filepath.Join(r.baseDir, "repo.yml")
	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, err
	}

	opts := make(map[string]string)
	err = yaml.Unmarshal(bs, &opts)
	if err != nil {
		return nil, err
	}
	return opts, nil
}

// GetRepoInfo returns a repository information
func (r *RepositoryRestorer) GetRepoInfo() (*base.Repository, error) {
	opts, err := r.getRepoOptions()
	if err != nil {
		return nil, err
	}

	isPrivate, _ := strconv.ParseBool(opts["is_private"])

	return &base.Repository{
		Owner:         r.repoOwner,
		Name:          r.repoName,
		IsPrivate:     isPrivate,
		Description:   opts["description"],
		OriginalURL:   opts["original_url"],
		CloneURL:      filepath.Join(r.baseDir, "git"),
		DefaultBranch: opts["default_branch"],
	}, nil
}

// GetTopics return github topics
func (r *RepositoryRestorer) GetTopics() ([]string, error) {
	p := filepath.Join(r.baseDir, "topic.yml")

	topics := struct {
		Topics []string `yaml:"topics"`
	}{}

	bs, err := os.ReadFile(p)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}

	err = yaml.Unmarshal(bs, &topics)
	if err != nil {
		return nil, err
	}
	return topics.Topics, nil
}

// GetMilestones returns milestones
func (r *RepositoryRestorer) GetMilestones() ([]*base.Milestone, error) {
	milestones := make([]*base.Milestone, 0, 10)
	p := filepath.Join(r.baseDir, "milestone.yml")
	_, err := os.Stat(p)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}

	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, err
	}

	err = yaml.Unmarshal(bs, &milestones)
	if err != nil {
		return nil, err
	}
	return milestones, nil
}

// GetReleases returns releases
func (r *RepositoryRestorer) GetReleases() ([]*base.Release, error) {
	releases := make([]*base.Release, 0, 10)
	p := filepath.Join(r.baseDir, "release.yml")
	_, err := os.Stat(p)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}

	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, err
	}

	err = yaml.Unmarshal(bs, &releases)
	if err != nil {
		return nil, err
	}
	for _, rel := range releases {
		for _, asset := range rel.Assets {
			if asset.DownloadURL != nil {
				*asset.DownloadURL = "file://" + filepath.Join(r.baseDir, *asset.DownloadURL)
			}
		}
	}
	return releases, nil
}

// GetLabels returns labels
func (r *RepositoryRestorer) GetLabels() ([]*base.Label, error) {
	labels := make([]*base.Label, 0, 10)
	p := filepath.Join(r.baseDir, "label.yml")
	_, err := os.Stat(p)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}

	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, err
	}

	err = yaml.Unmarshal(bs, &labels)
	if err != nil {
		return nil, err
	}
	return labels, nil
}

// GetIssues returns issues according start and limit
func (r *RepositoryRestorer) GetIssues(page, perPage int) ([]*base.Issue, bool, error) {
	issues := make([]*base.Issue, 0, 10)
	p := filepath.Join(r.baseDir, "issue.yml")
	_, err := os.Stat(p)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, true, nil
		}
		return nil, false, err
	}

	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, false, err
	}

	err = yaml.Unmarshal(bs, &issues)
	if err != nil {
		return nil, false, err
	}
	for _, issue := range issues {
		issue.Context = base.BasicIssueContext(issue.Number)
	}
	return issues, true, nil
}

// GetComments returns comments according issueNumber
func (r *RepositoryRestorer) GetComments(opts base.GetCommentOptions) ([]*base.Comment, bool, error) {
	comments := make([]*base.Comment, 0, 10)
	p := filepath.Join(r.commentDir(), fmt.Sprintf("%d.yml", opts.Context.ForeignID()))
	_, err := os.Stat(p)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, false, nil
		}
		return nil, false, err
	}

	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, false, err
	}

	err = yaml.Unmarshal(bs, &comments)
	if err != nil {
		return nil, false, err
	}
	return comments, false, nil
}

// GetPullRequests returns pull requests according page and perPage
func (r *RepositoryRestorer) GetPullRequests(page, perPage int) ([]*base.PullRequest, bool, error) {
	pulls := make([]*base.PullRequest, 0, 10)
	p := filepath.Join(r.baseDir, "pull_request.yml")
	_, err := os.Stat(p)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, true, nil
		}
		return nil, false, err
	}

	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, false, err
	}

	err = yaml.Unmarshal(bs, &pulls)
	if err != nil {
		return nil, false, err
	}
	for _, pr := range pulls {
		pr.PatchURL = "file://" + filepath.Join(r.baseDir, pr.PatchURL)
		pr.Context = base.BasicIssueContext(pr.Number)
	}
	return pulls, true, nil
}

// GetReviews returns pull requests review
func (r *RepositoryRestorer) GetReviews(context base.IssueContext) ([]*base.Review, error) {
	reviews := make([]*base.Review, 0, 10)
	p := filepath.Join(r.reviewDir(), fmt.Sprintf("%d.yml", context.ForeignID()))
	_, err := os.Stat(p)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}

	bs, err := os.ReadFile(p)
	if err != nil {
		return nil, err
	}

	err = yaml.Unmarshal(bs, &reviews)
	if err != nil {
		return nil, err
	}
	return reviews, nil
}
<|endoftext|>


<commit_before>/* Copyright (C) 2013 CompleteDB LLC.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with PubSubSQL.  If not, see <http://www.gnu.org/licenses/>.
 */

package pubsubsql

type requestType uint8

const (
	requestTypeError requestType = iota // error request indicates scan or parse error.
	requestTypeCmd                      // cmd requests help, status etc.
	requestTypeSql                      // sql actins insert, update etc.
)

// request
type request interface {
	getRequestType() requestType
	getTableName() string
}

// errorRequest is an error request.
type errorRequest struct {
	request
	err string
}

// Returns type of a request.
func (act errorRequest) getRequestType() requestType {
	return requestTypeError
}

// sqlRequest is a generic sql request.
type sqlRequest struct {
	request
	table string
}

func (act sqlRequest) getRequestType() requestType {
	return requestTypeSql
}

func (act sqlRequest) getTableName() string {
	return act.table
}

// cmdRequest is a generic command request.
type cmdRequest struct {
	request
}

func (act cmdRequest) getRequestType() requestType {
	return requestTypeCmd
}

// columnValue is a pair of column and value
type columnValue struct {
	col string
	val string
}

// Temporarely stub for sqlFilter type that will be more capble in future versions.
type sqlFilter struct {
	columnValue
}

// Adds col = val to sqlFilter.
func (f *sqlFilter) addFilter(col string, val string) {
	f.col = col
	f.val = val
}

// sqlInsertRequest is a request for sql insert statement.
type sqlInsertRequest struct {
	sqlRequest
	colVals []*columnValue
}

// Adds column to columnValue slice.
func (a *sqlInsertRequest) addColumn(col string) {
	a.colVals = append(a.colVals, &columnValue{col: col})
}

// Adds column and value to columnValue slice for insert request.
func (a *sqlInsertRequest) addColVal(col string, val string) {
	a.colVals = append(a.colVals, &columnValue{col: col, val: val})
}

// Set value at a particular index of columnValue slice.
func (a *sqlInsertRequest) setValueAt(idx int, val string) {
	a.colVals[idx].val = val
}

// sqlSelectRequest is a request for sql select statement.
type sqlSelectRequest struct {
	sqlRequest
	filter sqlFilter
}

// sqlUpdateRequest is a request for sql update statement.
type sqlUpdateRequest struct {
	sqlRequest
	colVals []*columnValue
	filter  sqlFilter
}

// Adds column and value to columnValue slice for udpate request.
func (a *sqlUpdateRequest) addColVal(col string, val string) {
	a.colVals = append(a.colVals, &columnValue{col: col, val: val})
}

// sqlDeleteRequest is a request for sql delete statement.
type sqlDeleteRequest struct {
	sqlRequest
	filter sqlFilter
}

// sqlKeyRequest is a request for sql key statement.
// Key defines unique index.
type sqlKeyRequest struct {
	sqlRequest
	column string
}

// sqlTagRequest is a request for sql tag statement.
// Tag defines non-unique index.
type sqlTagRequest struct {
	sqlRequest
	column string
}

// sqlSubscribeRequest is a request for sql subscribe statement.
type sqlSubscribeRequest struct {
	sqlRequest
	filter sqlFilter
	sender *responseSender
}

// sqlUnsubscribeRequest is a request for sql unsubscribe statement.
type sqlUnsubscribeRequest struct {
	sqlRequest
	connectionId uint64
	filter       sqlFilter
}
<commit_msg>request refactor<commit_after>/* Copyright (C) 2013 CompleteDB LLC.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with PubSubSQL.  If not, see <http://www.gnu.org/licenses/>.
 */

package pubsubsql

type requestType uint8

const (
	requestTypeError requestType = iota // error request indicates scan or parse error.
	requestTypeCmd                      // cmd requests help, status etc.
	requestTypeSql                      // sql actins insert, update etc.
)

// request
type request interface {
	getRequestType() requestType
	getTableName() string
}

// errorRequest is an error request.
type errorRequest struct {
	request
	err string
}

// Returns type of a request.
func (act errorRequest) getRequestType() requestType {
	return requestTypeError
}

// sqlRequest is a generic sql request.
type sqlRequest struct {
	request
	table string
}

func (act sqlRequest) getRequestType() requestType {
	return requestTypeSql
}

func (act sqlRequest) getTableName() string {
	return act.table
}

// cmdRequest is a generic command request.
type cmdRequest struct {
	request
}

func (act cmdRequest) getRequestType() requestType {
	return requestTypeCmd
}

// columnValue is a pair of column and value
type columnValue struct {
	col string
	val string
}

// Temporarely stub for sqlFilter type that will be more capble in future versions.
type sqlFilter struct {
	columnValue
}

// Adds col = val to sqlFilter.
func (this *sqlFilter) addFilter(col string, val string) {
	this.col = col
	this.val = val
}

// sqlInsertRequest is a request for sql insert statement.
type sqlInsertRequest struct {
	sqlRequest
	colVals []*columnValue
}

// Adds column to columnValue slice.
func (this *sqlInsertRequest) addColumn(col string) {
	this.colVals = append(this.colVals, &columnValue{col: col})
}

// Adds column and value to columnValue slice for insert request.
func (this *sqlInsertRequest) addColVal(col string, val string) {
	this.colVals = append(this.colVals, &columnValue{col: col, val: val})
}

// Set value at a particular index of columnValue slice.
func (this *sqlInsertRequest) setValueAt(idx int, val string) {
	this.colVals[idx].val = val
}

// sqlSelectRequest is a request for sql select statement.
type sqlSelectRequest struct {
	sqlRequest
	filter sqlFilter
}

// sqlUpdateRequest is a request for sql update statement.
type sqlUpdateRequest struct {
	sqlRequest
	colVals []*columnValue
	filter  sqlFilter
}

// Adds column and value to columnValue slice for udpate request.
func (this *sqlUpdateRequest) addColVal(col string, val string) {
	this.colVals = append(this.colVals, &columnValue{col: col, val: val})
}

// sqlDeleteRequest is a request for sql delete statement.
type sqlDeleteRequest struct {
	sqlRequest
	filter sqlFilter
}

// sqlKeyRequest is a request for sql key statement.
// Key defines unique index.
type sqlKeyRequest struct {
	sqlRequest
	column string
}

// sqlTagRequest is a request for sql tag statement.
// Tag defines non-unique index.
type sqlTagRequest struct {
	sqlRequest
	column string
}

// sqlSubscribeRequest is a request for sql subscribe statement.
type sqlSubscribeRequest struct {
	sqlRequest
	filter sqlFilter
	sender *responseSender
}

// sqlUnsubscribeRequest is a request for sql unsubscribe statement.
type sqlUnsubscribeRequest struct {
	sqlRequest
	connectionId uint64
	filter       sqlFilter
}
<|endoftext|>


<commit_before>package server

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"

	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/stringid"
	"github.com/kubernetes-incubator/ocid/oci"
	"github.com/kubernetes-incubator/ocid/utils"
	"github.com/opencontainers/runtime-tools/generate"
	"golang.org/x/net/context"
	pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
)

type sandbox struct {
	id         string
	name       string
	logDir     string
	labels     map[string]string
	containers oci.Store
}

const (
	podInfraRootfs      = "/var/lib/ocid/graph/vfs/pause"
	podDefaultNamespace = "default"
)

func (s *sandbox) addContainer(c *oci.Container) {
	s.containers.Add(c.Name(), c)
}

func (s *sandbox) getContainer(name string) *oci.Container {
	return s.containers.Get(name)
}

func (s *sandbox) removeContainer(c *oci.Container) {
	s.containers.Delete(c.Name())
}

func (s *Server) generatePodIDandName(name, namespace string) (string, string, error) {
	var (
		err error
		id  = stringid.GenerateNonCryptoID()
	)
	if namespace == "" {
		namespace = podDefaultNamespace
	}
	if name, err = s.reservePodName(id, namespace+"-"+name); err != nil {
		return "", "", err
	}
	return id, name, err
}

// CreatePodSandbox creates a pod-level sandbox.
// The definition of PodSandbox is at https://k8s.io/kubernetes/pull/25899
func (s *Server) CreatePodSandbox(ctx context.Context, req *pb.CreatePodSandboxRequest) (*pb.CreatePodSandboxResponse, error) {
	// process req.Name
	name := req.GetConfig().GetMetadata().GetName()
	if name == "" {
		return nil, fmt.Errorf("PodSandboxConfig.Name should not be empty")
	}

	namespace := req.GetConfig().GetMetadata().GetNamespace()

	var err error
	id, name, err := s.generatePodIDandName(name, namespace)
	if err != nil {
		return nil, err
	}
	podSandboxDir := filepath.Join(s.sandboxDir, id)
	if _, err = os.Stat(podSandboxDir); err == nil {
		return nil, fmt.Errorf("pod sandbox (%s) already exists", podSandboxDir)
	}

	if err = os.MkdirAll(podSandboxDir, 0755); err != nil {
		return nil, err
	}

	defer func() {
		if err != nil {
			if err2 := os.RemoveAll(podSandboxDir); err2 != nil {
				logrus.Warnf("couldn't cleanup podSandboxDir %s: %v", podSandboxDir, err2)
			}
		}
	}()

	// creates a spec Generator with the default spec.
	g := generate.New()

	// setup defaults for the pod sandbox
	g.SetRootPath(filepath.Join(podInfraRootfs, "rootfs"))
	g.SetRootReadonly(true)
	g.SetProcessArgs([]string{"/pause"})

	// process req.Hostname
	hostname := req.GetConfig().GetHostname()
	if hostname != "" {
		g.SetHostname(hostname)
	}

	// process req.LogDirectory
	logDir := req.GetConfig().GetLogDirectory()
	if logDir == "" {
		logDir = fmt.Sprintf("/var/log/ocid/pods/%s", id)
	}

	dnsServers := req.GetConfig().GetDnsOptions().GetServers()
	dnsSearches := req.GetConfig().GetDnsOptions().GetSearches()
	resolvPath := fmt.Sprintf("%s/resolv.conf", podSandboxDir)
	err = parseDNSOptions(dnsServers, dnsSearches, resolvPath)
	if err != nil {
		err1 := removeFile(resolvPath)
		if err1 != nil {
			err = err1
			return nil, fmt.Errorf("%v; failed to remove %s: %v", err, resolvPath, err1)
		}
		return nil, err
	}

	g.AddBindMount(resolvPath, "/etc/resolv.conf", "ro")

	labels := req.GetConfig().GetLabels()
	labelsJSON, err := json.Marshal(labels)
	if err != nil {
		return nil, err
	}
	g.AddAnnotation("ocid/labels", string(labelsJSON))
	g.AddAnnotation("ocid/log_path", logDir)
	g.AddAnnotation("ocid/name", name)
	containerName := name + "-infra"
	g.AddAnnotation("ocid/container_name", containerName)
	s.addSandbox(&sandbox{
		id:         id,
		name:       name,
		logDir:     logDir,
		labels:     labels,
		containers: oci.NewMemoryStore(),
	})

	annotations := req.GetConfig().GetAnnotations()
	for k, v := range annotations {
		g.AddAnnotation(k, v)
	}

	cgroupParent := req.GetConfig().GetLinux().GetCgroupParent()
	if cgroupParent != "" {
		g.SetLinuxCgroupsPath(cgroupParent)
	}

	// set up namespaces
	if req.GetConfig().GetLinux().GetNamespaceOptions().GetHostNetwork() {
		err = g.RemoveLinuxNamespace("network")
		if err != nil {
			return nil, err
		}
	}

	if req.GetConfig().GetLinux().GetNamespaceOptions().GetHostPid() {
		err = g.RemoveLinuxNamespace("pid")
		if err != nil {
			return nil, err
		}
	}

	if req.GetConfig().GetLinux().GetNamespaceOptions().GetHostIpc() {
		err = g.RemoveLinuxNamespace("ipc")
		if err != nil {
			return nil, err
		}
	}

	err = g.SaveToFile(filepath.Join(podSandboxDir, "config.json"))
	if err != nil {
		return nil, err
	}

	if _, err = os.Stat(podInfraRootfs); err != nil {
		if os.IsNotExist(err) {
			// TODO: Replace by rootfs creation API when it is ready
			if err := utils.CreateFakeRootfs(podInfraRootfs, "docker://kubernetes/pause"); err != nil {
				return nil, err
			}
		} else {
			return nil, err
		}
	}

	container, err := oci.NewContainer(containerName, podSandboxDir, podSandboxDir, labels, id, false)
	if err != nil {
		return nil, err
	}

	if err = s.runtime.CreateContainer(container); err != nil {
		return nil, err
	}

	if err = s.runtime.UpdateStatus(container); err != nil {
		return nil, err
	}

	// Setup the network
	podNamespace := ""
	netnsPath, err := container.NetNsPath()
	if err != nil {
		return nil, err
	}
	if err = s.netPlugin.SetUpPod(netnsPath, podNamespace, id, containerName); err != nil {
		return nil, fmt.Errorf("failed to create network for container %s in sandbox %s: %v", containerName, id, err)
	}

	if err = s.runtime.StartContainer(container); err != nil {
		return nil, err
	}

	s.addContainer(container)

	if err = s.podIDIndex.Add(id); err != nil {
		return nil, err
	}

	if err = s.runtime.UpdateStatus(container); err != nil {
		return nil, err
	}

	return &pb.CreatePodSandboxResponse{PodSandboxId: &id}, nil
}

// StopPodSandbox stops the sandbox. If there are any running containers in the
// sandbox, they should be force terminated.
func (s *Server) StopPodSandbox(ctx context.Context, req *pb.StopPodSandboxRequest) (*pb.StopPodSandboxResponse, error) {
	sbID := req.PodSandboxId
	if *sbID == "" {
		return nil, fmt.Errorf("PodSandboxId should not be empty")
	}
	sb := s.getSandbox(*sbID)
	if sb == nil {
		return nil, fmt.Errorf("specified sandbox not found: %s", *sbID)
	}

	podInfraContainer := sb.name + "-infra"
	for _, c := range sb.containers.List() {
		if podInfraContainer == c.Name() {
			podNamespace := ""
			netnsPath, err := c.NetNsPath()
			if err != nil {
				return nil, err
			}
			if err := s.netPlugin.TearDownPod(netnsPath, podNamespace, *sbID, podInfraContainer); err != nil {
				return nil, fmt.Errorf("failed to destroy network for container %s in sandbox %s: %v", c.Name(), *sbID, err)
			}
		}
		cStatus := s.runtime.ContainerStatus(c)
		if cStatus.Status != "stopped" {
			if err := s.runtime.StopContainer(c); err != nil {
				return nil, fmt.Errorf("failed to stop container %s in sandbox %s: %v", c.Name(), *sbID, err)
			}
		}
	}

	return &pb.StopPodSandboxResponse{}, nil
}

// RemovePodSandbox deletes the sandbox. If there are any running containers in the
// sandbox, they should be force deleted.
func (s *Server) RemovePodSandbox(ctx context.Context, req *pb.RemovePodSandboxRequest) (*pb.RemovePodSandboxResponse, error) {
	sbName := req.PodSandboxId
	if *sbName == "" {
		return nil, fmt.Errorf("PodSandboxId should not be empty")
	}
	sb := s.getSandbox(*sbName)
	if sb == nil {
		return nil, fmt.Errorf("specified sandbox not found: %s", *sbName)
	}

	podInfraContainer := *sbName + "-infra"

	// Delete all the containers in the sandbox
	for _, c := range sb.containers.List() {
		if err := s.runtime.DeleteContainer(c); err != nil {
			return nil, fmt.Errorf("failed to delete container %s in sandbox %s: %v", c.Name(), *sbName, err)
		}
		if podInfraContainer == c.Name() {
			continue
		}
		containerDir := filepath.Join(s.runtime.ContainerDir(), c.Name())
		if err := os.RemoveAll(containerDir); err != nil {
			return nil, fmt.Errorf("failed to remove container %s directory: %v", c.Name(), err)
		}
	}

	// Remove the files related to the sandbox
	podSandboxDir := filepath.Join(s.sandboxDir, *sbName)
	if err := os.RemoveAll(podSandboxDir); err != nil {
		return nil, fmt.Errorf("failed to remove sandbox %s directory: %v", *sbName, err)
	}

	return &pb.RemovePodSandboxResponse{}, nil
}

// PodSandboxStatus returns the Status of the PodSandbox.
func (s *Server) PodSandboxStatus(ctx context.Context, req *pb.PodSandboxStatusRequest) (*pb.PodSandboxStatusResponse, error) {
	sbName := req.PodSandboxId
	if *sbName == "" {
		return nil, fmt.Errorf("PodSandboxId should not be empty")
	}
	sb := s.getSandbox(*sbName)
	if sb == nil {
		return nil, fmt.Errorf("specified sandbox not found: %s", *sbName)
	}

	podInfraContainerName := *sbName + "-infra"
	podInfraContainer := sb.getContainer(podInfraContainerName)

	cState := s.runtime.ContainerStatus(podInfraContainer)
	created := cState.Created.Unix()

	netNsPath, err := podInfraContainer.NetNsPath()
	if err != nil {
		return nil, err
	}
	podNamespace := ""
	ip, err := s.netPlugin.GetContainerNetworkStatus(netNsPath, podNamespace, *sbName, podInfraContainerName)
	if err != nil {
		// ignore the error on network status
		ip = ""
	}

	return &pb.PodSandboxStatusResponse{
		Status: &pb.PodSandboxStatus{
			Id:        sbName,
			CreatedAt: int64Ptr(created),
			Linux: &pb.LinuxPodSandboxStatus{
				Namespaces: &pb.Namespace{
					Network: sPtr(netNsPath),
				},
			},
			Network: &pb.PodSandboxNetworkStatus{Ip: &ip},
		},
	}, nil
}

// ListPodSandbox returns a list of SandBox.
func (s *Server) ListPodSandbox(context.Context, *pb.ListPodSandboxRequest) (*pb.ListPodSandboxResponse, error) {
	return nil, nil
}
<commit_msg>Fixup remove sandbox logic<commit_after>package server

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"

	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/stringid"
	"github.com/kubernetes-incubator/ocid/oci"
	"github.com/kubernetes-incubator/ocid/utils"
	"github.com/opencontainers/runtime-tools/generate"
	"golang.org/x/net/context"
	pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
)

type sandbox struct {
	id         string
	name       string
	logDir     string
	labels     map[string]string
	containers oci.Store
}

const (
	podInfraRootfs      = "/var/lib/ocid/graph/vfs/pause"
	podDefaultNamespace = "default"
)

func (s *sandbox) addContainer(c *oci.Container) {
	s.containers.Add(c.Name(), c)
}

func (s *sandbox) getContainer(name string) *oci.Container {
	return s.containers.Get(name)
}

func (s *sandbox) removeContainer(c *oci.Container) {
	s.containers.Delete(c.Name())
}

func (s *Server) generatePodIDandName(name, namespace string) (string, string, error) {
	var (
		err error
		id  = stringid.GenerateNonCryptoID()
	)
	if namespace == "" {
		namespace = podDefaultNamespace
	}
	if name, err = s.reservePodName(id, namespace+"-"+name); err != nil {
		return "", "", err
	}
	return id, name, err
}

// CreatePodSandbox creates a pod-level sandbox.
// The definition of PodSandbox is at https://k8s.io/kubernetes/pull/25899
func (s *Server) CreatePodSandbox(ctx context.Context, req *pb.CreatePodSandboxRequest) (*pb.CreatePodSandboxResponse, error) {
	// process req.Name
	name := req.GetConfig().GetMetadata().GetName()
	if name == "" {
		return nil, fmt.Errorf("PodSandboxConfig.Name should not be empty")
	}

	namespace := req.GetConfig().GetMetadata().GetNamespace()

	var err error
	id, name, err := s.generatePodIDandName(name, namespace)
	if err != nil {
		return nil, err
	}
	podSandboxDir := filepath.Join(s.sandboxDir, id)
	if _, err = os.Stat(podSandboxDir); err == nil {
		return nil, fmt.Errorf("pod sandbox (%s) already exists", podSandboxDir)
	}

	if err = os.MkdirAll(podSandboxDir, 0755); err != nil {
		return nil, err
	}

	defer func() {
		if err != nil {
			if err2 := os.RemoveAll(podSandboxDir); err2 != nil {
				logrus.Warnf("couldn't cleanup podSandboxDir %s: %v", podSandboxDir, err2)
			}
		}
	}()

	// creates a spec Generator with the default spec.
	g := generate.New()

	// setup defaults for the pod sandbox
	g.SetRootPath(filepath.Join(podInfraRootfs, "rootfs"))
	g.SetRootReadonly(true)
	g.SetProcessArgs([]string{"/pause"})

	// process req.Hostname
	hostname := req.GetConfig().GetHostname()
	if hostname != "" {
		g.SetHostname(hostname)
	}

	// process req.LogDirectory
	logDir := req.GetConfig().GetLogDirectory()
	if logDir == "" {
		logDir = fmt.Sprintf("/var/log/ocid/pods/%s", id)
	}

	dnsServers := req.GetConfig().GetDnsOptions().GetServers()
	dnsSearches := req.GetConfig().GetDnsOptions().GetSearches()
	resolvPath := fmt.Sprintf("%s/resolv.conf", podSandboxDir)
	err = parseDNSOptions(dnsServers, dnsSearches, resolvPath)
	if err != nil {
		err1 := removeFile(resolvPath)
		if err1 != nil {
			err = err1
			return nil, fmt.Errorf("%v; failed to remove %s: %v", err, resolvPath, err1)
		}
		return nil, err
	}

	g.AddBindMount(resolvPath, "/etc/resolv.conf", "ro")

	labels := req.GetConfig().GetLabels()
	labelsJSON, err := json.Marshal(labels)
	if err != nil {
		return nil, err
	}
	g.AddAnnotation("ocid/labels", string(labelsJSON))
	g.AddAnnotation("ocid/log_path", logDir)
	g.AddAnnotation("ocid/name", name)
	containerName := name + "-infra"
	g.AddAnnotation("ocid/container_name", containerName)
	s.addSandbox(&sandbox{
		id:         id,
		name:       name,
		logDir:     logDir,
		labels:     labels,
		containers: oci.NewMemoryStore(),
	})

	annotations := req.GetConfig().GetAnnotations()
	for k, v := range annotations {
		g.AddAnnotation(k, v)
	}

	cgroupParent := req.GetConfig().GetLinux().GetCgroupParent()
	if cgroupParent != "" {
		g.SetLinuxCgroupsPath(cgroupParent)
	}

	// set up namespaces
	if req.GetConfig().GetLinux().GetNamespaceOptions().GetHostNetwork() {
		err = g.RemoveLinuxNamespace("network")
		if err != nil {
			return nil, err
		}
	}

	if req.GetConfig().GetLinux().GetNamespaceOptions().GetHostPid() {
		err = g.RemoveLinuxNamespace("pid")
		if err != nil {
			return nil, err
		}
	}

	if req.GetConfig().GetLinux().GetNamespaceOptions().GetHostIpc() {
		err = g.RemoveLinuxNamespace("ipc")
		if err != nil {
			return nil, err
		}
	}

	err = g.SaveToFile(filepath.Join(podSandboxDir, "config.json"))
	if err != nil {
		return nil, err
	}

	if _, err = os.Stat(podInfraRootfs); err != nil {
		if os.IsNotExist(err) {
			// TODO: Replace by rootfs creation API when it is ready
			if err := utils.CreateFakeRootfs(podInfraRootfs, "docker://kubernetes/pause"); err != nil {
				return nil, err
			}
		} else {
			return nil, err
		}
	}

	container, err := oci.NewContainer(containerName, podSandboxDir, podSandboxDir, labels, id, false)
	if err != nil {
		return nil, err
	}

	if err = s.runtime.CreateContainer(container); err != nil {
		return nil, err
	}

	if err = s.runtime.UpdateStatus(container); err != nil {
		return nil, err
	}

	// Setup the network
	podNamespace := ""
	netnsPath, err := container.NetNsPath()
	if err != nil {
		return nil, err
	}
	if err = s.netPlugin.SetUpPod(netnsPath, podNamespace, id, containerName); err != nil {
		return nil, fmt.Errorf("failed to create network for container %s in sandbox %s: %v", containerName, id, err)
	}

	if err = s.runtime.StartContainer(container); err != nil {
		return nil, err
	}

	s.addContainer(container)

	if err = s.podIDIndex.Add(id); err != nil {
		return nil, err
	}

	if err = s.runtime.UpdateStatus(container); err != nil {
		return nil, err
	}

	return &pb.CreatePodSandboxResponse{PodSandboxId: &id}, nil
}

// StopPodSandbox stops the sandbox. If there are any running containers in the
// sandbox, they should be force terminated.
func (s *Server) StopPodSandbox(ctx context.Context, req *pb.StopPodSandboxRequest) (*pb.StopPodSandboxResponse, error) {
	sbID := req.PodSandboxId
	if *sbID == "" {
		return nil, fmt.Errorf("PodSandboxId should not be empty")
	}
	sb := s.getSandbox(*sbID)
	if sb == nil {
		return nil, fmt.Errorf("specified sandbox not found: %s", *sbID)
	}

	podInfraContainer := sb.name + "-infra"
	for _, c := range sb.containers.List() {
		if podInfraContainer == c.Name() {
			podNamespace := ""
			netnsPath, err := c.NetNsPath()
			if err != nil {
				return nil, err
			}
			if err := s.netPlugin.TearDownPod(netnsPath, podNamespace, *sbID, podInfraContainer); err != nil {
				return nil, fmt.Errorf("failed to destroy network for container %s in sandbox %s: %v", c.Name(), *sbID, err)
			}
		}
		cStatus := s.runtime.ContainerStatus(c)
		if cStatus.Status != "stopped" {
			if err := s.runtime.StopContainer(c); err != nil {
				return nil, fmt.Errorf("failed to stop container %s in sandbox %s: %v", c.Name(), *sbID, err)
			}
		}
	}

	return &pb.StopPodSandboxResponse{}, nil
}

// RemovePodSandbox deletes the sandbox. If there are any running containers in the
// sandbox, they should be force deleted.
func (s *Server) RemovePodSandbox(ctx context.Context, req *pb.RemovePodSandboxRequest) (*pb.RemovePodSandboxResponse, error) {
	sbID := req.PodSandboxId
	if *sbID == "" {
		return nil, fmt.Errorf("PodSandboxId should not be empty")
	}
	sb := s.getSandbox(*sbID)
	if sb == nil {
		return nil, fmt.Errorf("specified sandbox not found: %s", *sbID)
	}

	podInfraContainer := sb.name + "-infra"

	// Delete all the containers in the sandbox
	for _, c := range sb.containers.List() {
		if err := s.runtime.DeleteContainer(c); err != nil {
			return nil, fmt.Errorf("failed to delete container %s in sandbox %s: %v", c.Name(), *sbID, err)
		}
		if podInfraContainer == c.Name() {
			continue
		}
		containerDir := filepath.Join(s.runtime.ContainerDir(), c.Name())
		if err := os.RemoveAll(containerDir); err != nil {
			return nil, fmt.Errorf("failed to remove container %s directory: %v", c.Name(), err)
		}
	}

	// Remove the files related to the sandbox
	podSandboxDir := filepath.Join(s.sandboxDir, *sbID)
	if err := os.RemoveAll(podSandboxDir); err != nil {
		return nil, fmt.Errorf("failed to remove sandbox %s directory: %v", *sbID, err)
	}

	return &pb.RemovePodSandboxResponse{}, nil
}

// PodSandboxStatus returns the Status of the PodSandbox.
func (s *Server) PodSandboxStatus(ctx context.Context, req *pb.PodSandboxStatusRequest) (*pb.PodSandboxStatusResponse, error) {
	sbName := req.PodSandboxId
	if *sbName == "" {
		return nil, fmt.Errorf("PodSandboxId should not be empty")
	}
	sb := s.getSandbox(*sbName)
	if sb == nil {
		return nil, fmt.Errorf("specified sandbox not found: %s", *sbName)
	}

	podInfraContainerName := *sbName + "-infra"
	podInfraContainer := sb.getContainer(podInfraContainerName)

	cState := s.runtime.ContainerStatus(podInfraContainer)
	created := cState.Created.Unix()

	netNsPath, err := podInfraContainer.NetNsPath()
	if err != nil {
		return nil, err
	}
	podNamespace := ""
	ip, err := s.netPlugin.GetContainerNetworkStatus(netNsPath, podNamespace, *sbName, podInfraContainerName)
	if err != nil {
		// ignore the error on network status
		ip = ""
	}

	return &pb.PodSandboxStatusResponse{
		Status: &pb.PodSandboxStatus{
			Id:        sbName,
			CreatedAt: int64Ptr(created),
			Linux: &pb.LinuxPodSandboxStatus{
				Namespaces: &pb.Namespace{
					Network: sPtr(netNsPath),
				},
			},
			Network: &pb.PodSandboxNetworkStatus{Ip: &ip},
		},
	}, nil
}

// ListPodSandbox returns a list of SandBox.
func (s *Server) ListPodSandbox(context.Context, *pb.ListPodSandboxRequest) (*pb.ListPodSandboxResponse, error) {
	return nil, nil
}
<|endoftext|>


<commit_before>package service

import (
	"fmt"
	"net/http"
	"os"

	"github.com/spf13/cobra"

	"github.com/runabove/sail/internal"
)

func deleteCmd() *cobra.Command {

	cmd := &cobra.Command{
		Use:     "delete",
		Short:   "Delete a docker service: sail service delete [<applicationName>/]<serviceId>",
		Run:     cmdServiceDelete,
		Aliases: []string{"del", "rm", "remove"},
	}
	return cmd
}

func cmdServiceDelete(cmd *cobra.Command, args []string) {
	usage := "Invalid usage. sail service delete [<applicationName>/]<serviceId>"
	if len(args) != 1 {
		fmt.Fprintln(os.Stderr, usage)
		return
	}

	// Split namespace and service
	host, app, service, _, err := internal.ParseResourceName(args[0])
	internal.Check(err)

	if !internal.CheckHostConsistent(host) {
		fmt.Fprintf(os.Stderr, "Error: Invalid Host %s for endpoint %s\n", host, internal.Host)
		os.Exit(1)
	}

	serviceDelete(app, service)
}

func serviceDelete(namespace string, name string) {
	path := fmt.Sprintf("/applications/%s/services/%s", namespace, name)
	data := internal.ReqWant("DELETE", http.StatusOK, path, nil)
	// TODO Check for json error here
	internal.FormatOutputDef(data)
}
<commit_msg>feat: expose delete --force<commit_after>package service

import (
	"fmt"
	"net/http"
	"os"

	"github.com/spf13/cobra"

	"github.com/runabove/sail/internal"
)

var deleteForce bool

func deleteCmd() *cobra.Command {

	cmd := &cobra.Command{
		Use:     "delete",
		Short:   "Delete a docker service: sail service delete [<applicationName>/]<serviceId> [--force]",
		Run:     cmdServiceDelete,
		Aliases: []string{"del", "rm", "remove"},
	}

	cmd.Flags().BoolVarP(&deleteForce, "force", "", false, "danger zone: delete service even if it breaks links")

	return cmd
}

func cmdServiceDelete(cmd *cobra.Command, args []string) {
	usage := "Invalid usage. sail service delete [<applicationName>/]<serviceId>"
	if len(args) != 1 {
		fmt.Fprintln(os.Stderr, usage)
		return
	}

	// Split namespace and service
	host, app, service, _, err := internal.ParseResourceName(args[0])
	internal.Check(err)

	if !internal.CheckHostConsistent(host) {
		fmt.Fprintf(os.Stderr, "Error: Invalid Host %s for endpoint %s\n", host, internal.Host)
		os.Exit(1)
	}

	serviceDelete(app, service)
}

func serviceDelete(namespace string, name string) {
	path := fmt.Sprintf("/applications/%s/services/%s?force=%t", namespace, name, deleteForce)
	data := internal.ReqWant("DELETE", http.StatusOK, path, nil)
	// TODO Check for json error here
	internal.FormatOutputDef(data)
}
<|endoftext|>