Skip to content

Commit

Permalink
Merge pull request #67 from scality/improvement/COSI-35-update-loggin…
Browse files Browse the repository at this point in the history
…g-mechanism

COSI-35: Improve Logging Clarity and Accuracy for Object Storage and IAM Operations
  • Loading branch information
anurag4DSB authored Dec 18, 2024
2 parents add30eb + 535757d commit 52e13ca
Show file tree
Hide file tree
Showing 13 changed files with 225 additions and 174 deletions.
4 changes: 4 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ component_management:
name: 🔧 Util Package
paths:
- pkg/util/**
- component_id: constants-package
name: 🔖 Constants Package
paths:
- pkg/constants/**

flag_management:
default_rules: # the rules that will be followed for any flag added, generally
Expand Down
12 changes: 9 additions & 3 deletions helm/scality-cosi-driver/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@ image:

replicaCount: 1


# Log levels define the verbosity of logs for various parts of the system.
# Use these levels to control the detail included in the logs:
# 1 - General configuration, routine logs
# 2 - Steady-state operations, HTTP requests, system state changes (default)
# 3 - Extended changes, additional system details
# 4 - Debug-level logs, tricky logic areas
# 5 - Trace-level logs, context for troubleshooting
logLevels:
driver: "5"
sidecar: "5"
driver: "2"
sidecar: "2"


namespace: scality-object-storage
Expand Down
7 changes: 7 additions & 0 deletions kustomize/overlays/debug/scality-cosi-driver.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
# Log levels define the verbosity of logs for various parts of the system.
# Use these levels to control the detail included in the logs:
# 1 - General configuration, routine logs
# 2 - Steady-state operations, HTTP requests, system state changes (default)
# 3 - Extended changes, additional system details
# 4 - Debug-level logs, tricky logic areas
# 5 - Trace-level logs, context for troubleshooting
COSI_DRIVER_LOG_LEVEL=5
OBJECTSTORAGE_PROVISIONER_SIDECAR_LOG_LEVEL=5
7 changes: 7 additions & 0 deletions kustomize/overlays/dev/scality-cosi-driver.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
# Log levels define the verbosity of logs for various parts of the system.
# Use these levels to control the detail included in the logs:
# 1 - General configuration, routine logs
# 2 - Steady-state operations, HTTP requests, system state changes (default)
# 3 - Extended changes, additional system details
# 4 - Debug-level logs, tricky logic areas
# 5 - Trace-level logs, context for troubleshooting
COSI_DRIVER_LOG_LEVEL=5
OBJECTSTORAGE_PROVISIONER_SIDECAR_LOG_LEVEL=5
11 changes: 9 additions & 2 deletions kustomize/overlays/production/scality-cosi-driver.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
COSI_DRIVER_LOG_LEVEL=5
OBJECTSTORAGE_PROVISIONER_SIDECAR_LOG_LEVEL=5
# Log levels define the verbosity of logs for various parts of the system.
# Use these levels to control the detail included in the logs:
# 1 - General configuration, routine logs
# 2 - Steady-state operations, HTTP requests, system state changes (default)
# 3 - Extended changes, additional system details
# 4 - Debug-level logs, tricky logic areas
# 5 - Trace-level logs, context for troubleshooting
COSI_DRIVER_LOG_LEVEL=2
OBJECTSTORAGE_PROVISIONER_SIDECAR_LOG_LEVEL=2
59 changes: 24 additions & 35 deletions pkg/clients/iam/iam_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/aws/aws-sdk-go-v2/service/iam"
"github.com/aws/aws-sdk-go-v2/service/iam/types"
"github.com/aws/smithy-go/logging"
c "github.com/scality/cosi-driver/pkg/constants"
"github.com/scality/cosi-driver/pkg/util"
"k8s.io/klog/v2"
)
Expand Down Expand Up @@ -48,6 +49,7 @@ var InitIAMClient = func(params util.StorageClientParameters) (*IAMClient, error
}

if strings.HasPrefix(params.IAMEndpoint, "https://") {
klog.V(c.LvlDebug).InfoS("Configuring TLS transport for IAM client", "IAMEndpoint", params.IAMEndpoint)
httpClient.Transport = util.ConfigureTLSTransport(params.TLSCert)
}

Expand All @@ -60,7 +62,7 @@ var InitIAMClient = func(params util.StorageClientParameters) (*IAMClient, error
config.WithLogger(logger),
)
if err != nil {
return nil, fmt.Errorf("failed to load AWS config: %w", err)
return nil, err
}

iamClient := iam.NewFromConfig(awsCfg, func(o *iam.Options) {
Expand All @@ -79,12 +81,7 @@ func (client *IAMClient) CreateUser(ctx context.Context, userName string) error
}

_, err := client.IAMService.CreateUser(ctx, input)
if err != nil {
return fmt.Errorf("failed to create IAM user %s: %w", userName, err)
}

klog.InfoS("IAM user creation succeeded", "user", userName)
return nil
return err
}

// AttachS3WildcardInlinePolicy attaches an inline policy to an IAM user for a specific bucket.
Expand All @@ -110,12 +107,7 @@ func (client *IAMClient) AttachS3WildcardInlinePolicy(ctx context.Context, userN
}

_, err := client.IAMService.PutUserPolicy(ctx, input)
if err != nil {
return fmt.Errorf("failed to attach inline policy to IAM user %s: %w", userName, err)
}

klog.InfoS("Inline policy attachment succeeded", "user", userName, "policyName", bucketName)
return nil
return err
}

// CreateAccessKey generates access keys for an IAM user.
Expand All @@ -125,12 +117,7 @@ func (client *IAMClient) CreateAccessKey(ctx context.Context, userName string) (
}

output, err := client.IAMService.CreateAccessKey(ctx, input)
if err != nil {
return nil, fmt.Errorf("failed to create access key for IAM user %s: %w", userName, err)
}

klog.InfoS("Access key creation succeeded", "user", userName)
return output, nil
return output, err
}

// CreateBucketAccess is a helper that combines user creation, policy attachment, and access key generation.
Expand All @@ -139,16 +126,19 @@ func (client *IAMClient) CreateBucketAccess(ctx context.Context, userName, bucke
if err != nil {
return nil, err
}
klog.V(c.LvlInfo).InfoS("Successfully created IAM user", "userName", userName)

err = client.AttachS3WildcardInlinePolicy(ctx, userName, bucketName)
if err != nil {
return nil, err
}
klog.V(c.LvlInfo).InfoS("Successfully attached inline policy", "userName", userName, "policyName", bucketName)

accessKeyOutput, err := client.CreateAccessKey(ctx, userName)
if err != nil {
return nil, err
}
klog.V(c.LvlInfo).InfoS("Successfully created access key", "userName", userName)

return accessKeyOutput, nil
}
Expand All @@ -159,32 +149,31 @@ func (client *IAMClient) RevokeBucketAccess(ctx context.Context, userName, bucke
if err != nil {
return err
}
klog.V(c.LvlInfo).InfoS("Verified IAM user exists", "userName", userName)

err = client.DeleteInlinePolicy(ctx, userName, bucketName)
if err != nil {
return err
}
klog.V(c.LvlInfo).InfoS("Deleted inline policy if it existed", "userName", userName, "policyName", bucketName)

err = client.DeleteAllAccessKeys(ctx, userName)
if err != nil {
return err
}
klog.V(c.LvlInfo).InfoS("Deleted all access keys if any existed", "userName", userName)

err = client.DeleteUser(ctx, userName)
if err != nil {
return err
}

klog.InfoS("Successfully revoked bucket access", "user", userName, "bucket", bucketName)
klog.V(c.LvlInfo).InfoS("Deleted IAM user", "userName", userName)
return nil
}

func (client *IAMClient) EnsureUserExists(ctx context.Context, userName string) error {
_, err := client.IAMService.GetUser(ctx, &iam.GetUserInput{UserName: &userName})
if err != nil {
return fmt.Errorf("failed to get IAM user %s: %w", userName, err)
}
return nil
return err
}

func (client *IAMClient) DeleteInlinePolicy(ctx context.Context, userName, bucketName string) error {
Expand All @@ -195,36 +184,37 @@ func (client *IAMClient) DeleteInlinePolicy(ctx context.Context, userName, bucke
if err != nil {
var noSuchEntityErr *types.NoSuchEntityException
if errors.As(err, &noSuchEntityErr) {
klog.V(3).InfoS("Inline policy does not exist, skipping deletion", "user", userName, "policyName", bucketName)
klog.V(c.LvlDebug).InfoS("Inline policy does not exist, skipping deletion", "user", userName, "policyName", bucketName)
return nil
}
return fmt.Errorf("failed to delete inline policy %s for user %s: %w", bucketName, userName, err)
return err
}
klog.InfoS("Successfully deleted inline policy", "user", userName, "policyName", bucketName)
klog.V(c.LvlDebug).InfoS("Successfully deleted inline policy", "userName", userName, "policyName", bucketName)
return nil
}

func (client *IAMClient) DeleteAllAccessKeys(ctx context.Context, userName string) error {
listKeysOutput, err := client.IAMService.ListAccessKeys(ctx, &iam.ListAccessKeysInput{UserName: &userName})
if err != nil {
return fmt.Errorf("failed to list access keys for IAM user %s: %w", userName, err)
return err
}
var noSuchEntityErr *types.NoSuchEntityException
for _, key := range listKeysOutput.AccessKeyMetadata {
klog.V(c.LvlTrace).InfoS("Deleting access key", "userName", userName, "accessKeyId", *key.AccessKeyId)
_, err := client.IAMService.DeleteAccessKey(ctx, &iam.DeleteAccessKeyInput{
UserName: &userName,
AccessKeyId: key.AccessKeyId,
})
if err != nil {
if errors.As(err, &noSuchEntityErr) {
klog.V(5).InfoS("Access key does not exist, skipping deletion", "user", userName, "accessKeyId", *key.AccessKeyId)
klog.V(c.LvlTrace).InfoS("Access key does not exist, skipping deletion", "userName", userName, "accessKeyId", *key.AccessKeyId)
continue
}
return fmt.Errorf("failed to delete access key %s for IAM user %s: %w", *key.AccessKeyId, userName, err)
return err
}
klog.V(5).InfoS("Successfully deleted access key", "user", userName, "accessKeyId", *key.AccessKeyId)
klog.V(c.LvlTrace).InfoS("Successfully deleted access key", "userName", userName, "accessKeyId", *key.AccessKeyId)
}
klog.InfoS("Successfully deleted all access keys", "user", userName)
klog.V(c.LvlDebug).InfoS("Successfully deleted all access keys", "userName", userName)
return nil
}

Expand All @@ -236,8 +226,7 @@ func (client *IAMClient) DeleteUser(ctx context.Context, userName string) error
klog.InfoS("IAM user does not exist, skipping deletion", "user", userName)
return nil // User doesn't exist, nothing to delete
}
return fmt.Errorf("failed to delete IAM user %s: %w", userName, err)
return err
}
klog.InfoS("Successfully deleted IAM user", "user", userName)
return nil
}
5 changes: 0 additions & 5 deletions pkg/clients/iam/iam_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ var _ = Describe("IAMClient", func() {

err := client.CreateUser(ctx, "test-user")
Expect(err).NotTo(BeNil())
Expect(err.Error()).To(ContainSubstring("failed to create IAM user test-user"))
Expect(err.Error()).To(ContainSubstring("simulated CreateUser failure"))
})

Expand Down Expand Up @@ -101,7 +100,6 @@ var _ = Describe("IAMClient", func() {

err := client.AttachS3WildcardInlinePolicy(ctx, "test-user", "test-bucket")
Expect(err).NotTo(BeNil())
Expect(err.Error()).To(ContainSubstring("failed to attach inline policy to IAM user test-user"))
Expect(err.Error()).To(ContainSubstring("simulated PutUserPolicy failure"))
})

Expand Down Expand Up @@ -136,7 +134,6 @@ var _ = Describe("IAMClient", func() {
output, err := client.CreateAccessKey(ctx, "test-user")
Expect(err).NotTo(BeNil())
Expect(output).To(BeNil())
Expect(err.Error()).To(ContainSubstring("failed to create access key for IAM user test-user"))
Expect(err.Error()).To(ContainSubstring("simulated CreateAccessKey failure"))
})
})
Expand Down Expand Up @@ -246,7 +243,6 @@ var _ = Describe("IAMClient", func() {

client, err := iamclient.InitIAMClient(params)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("failed to load AWS config: mock LoadAWSConfig failure"))
Expect(client).To(BeNil())
})

Expand Down Expand Up @@ -299,7 +295,6 @@ var _ = Describe("IAMClient", func() {

err := client.RevokeBucketAccess(ctx, "non-existent-user", "test-bucket")
Expect(err).NotTo(BeNil())
Expect(err.Error()).To(ContainSubstring("failed to get IAM user non-existent-user"))
Expect(errors.As(err, &noSuchEntityError)).To(BeTrue())
})

Expand Down
11 changes: 2 additions & 9 deletions pkg/clients/s3/s3_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package s3client

import (
"context"
"fmt"
"net/http"
"os"
"strings"
Expand All @@ -14,7 +13,6 @@ import (
"github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/aws/smithy-go/logging"
"github.com/scality/cosi-driver/pkg/util"
"k8s.io/klog/v2"
)

type S3API interface {
Expand Down Expand Up @@ -53,7 +51,7 @@ var InitS3Client = func(params util.StorageClientParameters) (*S3Client, error)
config.WithLogger(logger),
)
if err != nil {
return nil, fmt.Errorf("failed to load AWS config: %w", err)
return nil, err
}

s3Client := s3.NewFromConfig(awsCfg, func(o *s3.Options) {
Expand All @@ -79,12 +77,7 @@ func (client *S3Client) CreateBucket(ctx context.Context, bucketName string, par
}

_, err := client.S3Service.CreateBucket(ctx, input)
if err != nil {
return err
}

klog.InfoS("Bucket creation operation succeeded", "name", bucketName, "region", params.Region)
return nil
return err
}

func (client *S3Client) DeleteBucket(ctx context.Context, bucketName string) error {
Expand Down
1 change: 0 additions & 1 deletion pkg/clients/s3/s3_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ var _ = Describe("S3Client", func() {

client, err := s3client.InitS3Client(params)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("failed to load AWS config: mock config loading error"))
Expect(client).To(BeNil())
})

Expand Down
12 changes: 12 additions & 0 deletions pkg/constants/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package constants

// Log level constants for structured logging, starting from 1
// 0 is default if no level is provided
// Guidelines: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/logging.md#what-method-to-use
const (
LvlDefault = iota + 1 // 1 - General configuration, routine logs
LvlInfo // 2 - Steady-state operations, HTTP requests, system state changes
LvlEvent // 3 - Extended changes, additional system details
LvlDebug // 4 - Debug-level logs, tricky logic areas
LvlTrace // 5 - Trace-level logs, detailed troubleshooting context
)
26 changes: 26 additions & 0 deletions pkg/constants/constants_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package constants_test

import (
"testing"

. "github.com/onsi/ginkgo/v2" // Ginkgo for test descriptions
. "github.com/onsi/gomega" // Gomega for assertions
"github.com/scality/cosi-driver/pkg/constants" // Import the constants package
)

func TestConstants(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Constants Suite")
}

var _ = Describe("Constants", func() {
Context("Log level constants", func() {
It("should have the correct values for log levels", func() {
Expect(constants.LvlDefault).To(Equal(1), "LvlDefault should start at 1")
Expect(constants.LvlInfo).To(Equal(2), "LvlInfo should have the value 2")
Expect(constants.LvlEvent).To(Equal(3), "LvlEvent should have the value 3")
Expect(constants.LvlDebug).To(Equal(4), "LvlDebug should have the value 4")
Expect(constants.LvlTrace).To(Equal(5), "LvlTrace should have the value 5")
})
})
})
Loading

0 comments on commit 52e13ca

Please sign in to comment.