Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EBS volume metrics collector daemon #3766

Merged
merged 7 commits into from
Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
26 changes: 26 additions & 0 deletions ecs-agent/daemonimages/csidriver/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
CSI_DRIVER_VERSION?=v1.0.0
GO111MODULE=on
GOPATH=$(shell go env GOPATH)
BUILD_DATE=$(shell date -u -Iseconds)
amogh09 marked this conversation as resolved.
Show resolved Hide resolved

SOURCEDIR=./
CSI_DRIVER_SOURCES=$(shell find $(SOURCEDIR) -name '*.go')

OS?=linux
ARCH?=amd64

# Build binary for linux only
amogh09 marked this conversation as resolved.
Show resolved Hide resolved
.PHONY: bin/csi-driver
bin/csi-driver: $(CSI_DRIVER_SOURCES)
amogh09 marked this conversation as resolved.
Show resolved Hide resolved
CGO_ENABLED=0 GOOS=$(OS) GOARCH=$(ARCH) go build -ldflags "\
-X \"github.com/aws/amazon-ecs-agent/ecs-agent/daemon_images/csi-driver/version.version=$(CSI_DRIVER_VERSION)\" \
amogh09 marked this conversation as resolved.
Show resolved Hide resolved
-X \"github.com/aws/amazon-ecs-agent/ecs-agent/daemon_images/csi-driver/version.buildDate=$(BUILD_DATE)\"" \
-o ./bin/csi-driver ./

.PHONY: test
test:
go test -v -race -tags unit -timeout=60s ./...

.PHONY: clean
clean:
rm -rf bin/
100 changes: 100 additions & 0 deletions ecs-agent/daemonimages/csidriver/driver/driver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 driver

import (
"context"
"net"

"github.com/container-storage-interface/spec/lib/go/csi"
"google.golang.org/grpc"
"k8s.io/klog/v2"

"github.com/aws/amazon-ecs-agent/ecs-agent/daemonimages/csidriver/util"
"github.com/aws/amazon-ecs-agent/ecs-agent/daemonimages/csidriver/version"
)

type Driver struct {
amogh09 marked this conversation as resolved.
Show resolved Hide resolved
nodeService

srv *grpc.Server
options *DriverOptions
}

type DriverOptions struct {
endpoint string
}

func NewDriver(options ...func(*DriverOptions)) (*Driver, error) {
driverInfo := version.GetVersionInfo()
klog.InfoS("Driver Information",
"Driver", "csi-driver",
"Version", driverInfo.Version,
)
klog.V(4).InfoS("Additional driver information",
xxx0624 marked this conversation as resolved.
Show resolved Hide resolved
"BuildDate", driverInfo.BuildDate,
"RuntimeGoVersion", driverInfo.GoVersion,
"RuntimePlatform", driverInfo.Platform,
)

driverOptions := DriverOptions{}
for _, option := range options {
option(&driverOptions)
}

driver := Driver{
nodeService: newNodeService(),
options: &driverOptions,
}
return &driver, nil
}

func (d *Driver) Run() error {
scheme, addr, err := util.ParseEndpoint(d.options.endpoint)
if err != nil {
return err
}

listener, err := net.Listen(scheme, addr)
if err != nil {
return err
}

logErr := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
resp, err := handler(ctx, req)
if err != nil {
klog.ErrorS(err, "GRPC error")
}
return resp, err
}
opts := []grpc.ServerOption{
grpc.UnaryInterceptor(logErr),
}
d.srv = grpc.NewServer(opts...)
csi.RegisterNodeServer(d.srv, d)

klog.V(4).InfoS("Listening for connections", "address", listener.Addr())
return d.srv.Serve(listener)
}

func (d *Driver) Stop() {
klog.InfoS("Stopping the driver")
d.srv.Stop()
}

func WithEndpoint(endpoint string) func(*DriverOptions) {
return func(o *DriverOptions) {
o.endpoint = endpoint
}
}
32 changes: 32 additions & 0 deletions ecs-agent/daemonimages/csidriver/driver/driver_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//go:build unit
// +build unit

// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 driver

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestWithEndpoint(t *testing.T) {
value := "endpoint"
options := &DriverOptions{}

WithEndpoint(value)(options)

assert.Equal(t, value, options.endpoint)
}
31 changes: 31 additions & 0 deletions ecs-agent/daemonimages/csidriver/driver/mount.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 driver

// Mounter is the interface implemented by NodeMounter.
amogh09 marked this conversation as resolved.
Show resolved Hide resolved
type Mounter interface {
PathExists(path string) (bool, error)
}

// NodeMounter implements Mounter.
type NodeMounter struct {
}

func (nm NodeMounter) PathExists(path string) (bool, error) {
return false, nil
amogh09 marked this conversation as resolved.
Show resolved Hide resolved
}

func newNodeMounter() (Mounter, error) {
return NodeMounter{}, nil
}
33 changes: 33 additions & 0 deletions ecs-agent/daemonimages/csidriver/driver/node.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 driver

import (
"github.com/container-storage-interface/spec/lib/go/csi"
)

// nodeService represents the node service of CSI driver
type nodeService struct {
mounter Mounter
csi.UnimplementedNodeServer
amogh09 marked this conversation as resolved.
Show resolved Hide resolved
}

func newNodeService() nodeService {
nodeMounter, err := newNodeMounter()
if err != nil {
panic(err)
}

return nodeService{mounter: nodeMounter}
}
47 changes: 47 additions & 0 deletions ecs-agent/daemonimages/csidriver/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 main

import (
"flag"

"k8s.io/klog/v2"

"github.com/aws/amazon-ecs-agent/ecs-agent/daemonimages/csidriver/driver"
)

func main() {
fs := flag.NewFlagSet("csi-driver", flag.ExitOnError)
klog.InitFlags(fs)
srvOptions, err := GetServerOptions(fs)
if err != nil {
klog.ErrorS(err, "Failed to get the server options")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}

klog.V(4).InfoS("Server Options are provided", "ServerOptions", srvOptions)

drv, err := driver.NewDriver(
driver.WithEndpoint(srvOptions.Endpoint),
)
if err != nil {
klog.ErrorS(err, "Failed to create driver")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}

if err := drv.Run(); err != nil {
klog.ErrorS(err, "Failed to run driver")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}
}
43 changes: 43 additions & 0 deletions ecs-agent/daemonimages/csidriver/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 main

import (
"errors"
"flag"
"os"
)

const EmptyCSIEndpoint = ""
amogh09 marked this conversation as resolved.
Show resolved Hide resolved

type ServerOptions struct {
// Endpoint is the endpoint that the driver server should listen on.
Endpoint string
}

func GetServerOptions(fs *flag.FlagSet) (*ServerOptions, error) {
serverOptions := &ServerOptions{}
fs.StringVar(&serverOptions.Endpoint, "endpoint", EmptyCSIEndpoint, "Endpoint for the CSI driver server")

args := os.Args[1:]
if err := fs.Parse(args); err != nil {
return nil, err
}

if serverOptions.Endpoint == EmptyCSIEndpoint {
return nil, errors.New("no endpoint is provided")
}

return serverOptions, nil
}
66 changes: 66 additions & 0 deletions ecs-agent/daemonimages/csidriver/options_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//go:build unit
// +build unit

// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
// http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 main

import (
"flag"
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func TestGetServerOptions(t *testing.T) {
testFunc := func(t *testing.T, additionalArgs []string) (*ServerOptions, error) {
flagSet := flag.NewFlagSet("test-flagset", flag.ContinueOnError)

args := append([]string{
"/bin/csi-driver",
}, additionalArgs...)
oldArgs := os.Args
defer func() { os.Args = oldArgs }()
amogh09 marked this conversation as resolved.
Show resolved Hide resolved
os.Args = args

options, err := GetServerOptions(flagSet)
return options, err
}

testCases := []struct {
name string
testFunc func(t *testing.T)
}{
{
name: "Only endpoint is given",
testFunc: func(t *testing.T) {
opts, err := testFunc(t, []string{"--endpoint=foo"})
assert.NoError(t, err)
assert.Equal(t, "foo", opts.Endpoint)
},
},
{
name: "No argument is given",
testFunc: func(t *testing.T) {
_, err := testFunc(t, nil)
assert.NotNil(t, err)
amogh09 marked this conversation as resolved.
Show resolved Hide resolved
},
},
}

for _, tc := range testCases {
t.Run(tc.name, tc.testFunc)
}
}
Loading