github.com/segmentio/kafka-go@v0.4.48-0.20240318174348-3f6244eb34fd/createacls.go (about)

     1  package kafka
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/segmentio/kafka-go/protocol/createacls"
    11  )
    12  
    13  // CreateACLsRequest represents a request sent to a kafka broker to add
    14  // new ACLs.
    15  type CreateACLsRequest struct {
    16  	// Address of the kafka broker to send the request to.
    17  	Addr net.Addr
    18  
    19  	// List of ACL to create.
    20  	ACLs []ACLEntry
    21  }
    22  
    23  // CreateACLsResponse represents a response from a kafka broker to an ACL
    24  // creation request.
    25  type CreateACLsResponse struct {
    26  	// The amount of time that the broker throttled the request.
    27  	Throttle time.Duration
    28  
    29  	// List of errors that occurred while attempting to create
    30  	// the ACLs.
    31  	//
    32  	// The errors contain the kafka error code. Programs may use the standard
    33  	// errors.Is function to test the error against kafka error codes.
    34  	Errors []error
    35  }
    36  
    37  type ACLPermissionType int8
    38  
    39  const (
    40  	ACLPermissionTypeUnknown ACLPermissionType = 0
    41  	ACLPermissionTypeAny     ACLPermissionType = 1
    42  	ACLPermissionTypeDeny    ACLPermissionType = 2
    43  	ACLPermissionTypeAllow   ACLPermissionType = 3
    44  )
    45  
    46  func (apt ACLPermissionType) String() string {
    47  	mapping := map[ACLPermissionType]string{
    48  		ACLPermissionTypeUnknown: "Unknown",
    49  		ACLPermissionTypeAny:     "Any",
    50  		ACLPermissionTypeDeny:    "Deny",
    51  		ACLPermissionTypeAllow:   "Allow",
    52  	}
    53  	s, ok := mapping[apt]
    54  	if !ok {
    55  		s = mapping[ACLPermissionTypeUnknown]
    56  	}
    57  	return s
    58  }
    59  
    60  // MarshalText transforms an ACLPermissionType into its string representation.
    61  func (apt ACLPermissionType) MarshalText() ([]byte, error) {
    62  	return []byte(apt.String()), nil
    63  }
    64  
    65  // UnmarshalText takes a string representation of the resource type and converts it to an ACLPermissionType.
    66  func (apt *ACLPermissionType) UnmarshalText(text []byte) error {
    67  	normalized := strings.ToLower(string(text))
    68  	mapping := map[string]ACLPermissionType{
    69  		"unknown": ACLPermissionTypeUnknown,
    70  		"any":     ACLPermissionTypeAny,
    71  		"deny":    ACLPermissionTypeDeny,
    72  		"allow":   ACLPermissionTypeAllow,
    73  	}
    74  	parsed, ok := mapping[normalized]
    75  	if !ok {
    76  		*apt = ACLPermissionTypeUnknown
    77  		return fmt.Errorf("cannot parse %s as an ACLPermissionType", normalized)
    78  	}
    79  	*apt = parsed
    80  	return nil
    81  }
    82  
    83  type ACLOperationType int8
    84  
    85  const (
    86  	ACLOperationTypeUnknown         ACLOperationType = 0
    87  	ACLOperationTypeAny             ACLOperationType = 1
    88  	ACLOperationTypeAll             ACLOperationType = 2
    89  	ACLOperationTypeRead            ACLOperationType = 3
    90  	ACLOperationTypeWrite           ACLOperationType = 4
    91  	ACLOperationTypeCreate          ACLOperationType = 5
    92  	ACLOperationTypeDelete          ACLOperationType = 6
    93  	ACLOperationTypeAlter           ACLOperationType = 7
    94  	ACLOperationTypeDescribe        ACLOperationType = 8
    95  	ACLOperationTypeClusterAction   ACLOperationType = 9
    96  	ACLOperationTypeDescribeConfigs ACLOperationType = 10
    97  	ACLOperationTypeAlterConfigs    ACLOperationType = 11
    98  	ACLOperationTypeIdempotentWrite ACLOperationType = 12
    99  )
   100  
   101  func (aot ACLOperationType) String() string {
   102  	mapping := map[ACLOperationType]string{
   103  		ACLOperationTypeUnknown:         "Unknown",
   104  		ACLOperationTypeAny:             "Any",
   105  		ACLOperationTypeAll:             "All",
   106  		ACLOperationTypeRead:            "Read",
   107  		ACLOperationTypeWrite:           "Write",
   108  		ACLOperationTypeCreate:          "Create",
   109  		ACLOperationTypeDelete:          "Delete",
   110  		ACLOperationTypeAlter:           "Alter",
   111  		ACLOperationTypeDescribe:        "Describe",
   112  		ACLOperationTypeClusterAction:   "ClusterAction",
   113  		ACLOperationTypeDescribeConfigs: "DescribeConfigs",
   114  		ACLOperationTypeAlterConfigs:    "AlterConfigs",
   115  		ACLOperationTypeIdempotentWrite: "IdempotentWrite",
   116  	}
   117  	s, ok := mapping[aot]
   118  	if !ok {
   119  		s = mapping[ACLOperationTypeUnknown]
   120  	}
   121  	return s
   122  }
   123  
   124  // MarshalText transforms an ACLOperationType into its string representation.
   125  func (aot ACLOperationType) MarshalText() ([]byte, error) {
   126  	return []byte(aot.String()), nil
   127  }
   128  
   129  // UnmarshalText takes a string representation of the resource type and converts it to an ACLPermissionType.
   130  func (aot *ACLOperationType) UnmarshalText(text []byte) error {
   131  	normalized := strings.ToLower(string(text))
   132  	mapping := map[string]ACLOperationType{
   133  		"unknown":         ACLOperationTypeUnknown,
   134  		"any":             ACLOperationTypeAny,
   135  		"all":             ACLOperationTypeAll,
   136  		"read":            ACLOperationTypeRead,
   137  		"write":           ACLOperationTypeWrite,
   138  		"create":          ACLOperationTypeCreate,
   139  		"delete":          ACLOperationTypeDelete,
   140  		"alter":           ACLOperationTypeAlter,
   141  		"describe":        ACLOperationTypeDescribe,
   142  		"clusteraction":   ACLOperationTypeClusterAction,
   143  		"describeconfigs": ACLOperationTypeDescribeConfigs,
   144  		"alterconfigs":    ACLOperationTypeAlterConfigs,
   145  		"idempotentwrite": ACLOperationTypeIdempotentWrite,
   146  	}
   147  	parsed, ok := mapping[normalized]
   148  	if !ok {
   149  		*aot = ACLOperationTypeUnknown
   150  		return fmt.Errorf("cannot parse %s as an ACLOperationType", normalized)
   151  	}
   152  	*aot = parsed
   153  	return nil
   154  
   155  }
   156  
   157  type ACLEntry struct {
   158  	ResourceType        ResourceType
   159  	ResourceName        string
   160  	ResourcePatternType PatternType
   161  	Principal           string
   162  	Host                string
   163  	Operation           ACLOperationType
   164  	PermissionType      ACLPermissionType
   165  }
   166  
   167  // CreateACLs sends ACLs creation request to a kafka broker and returns the
   168  // response.
   169  func (c *Client) CreateACLs(ctx context.Context, req *CreateACLsRequest) (*CreateACLsResponse, error) {
   170  	acls := make([]createacls.RequestACLs, 0, len(req.ACLs))
   171  
   172  	for _, acl := range req.ACLs {
   173  		acls = append(acls, createacls.RequestACLs{
   174  			ResourceType:        int8(acl.ResourceType),
   175  			ResourceName:        acl.ResourceName,
   176  			ResourcePatternType: int8(acl.ResourcePatternType),
   177  			Principal:           acl.Principal,
   178  			Host:                acl.Host,
   179  			Operation:           int8(acl.Operation),
   180  			PermissionType:      int8(acl.PermissionType),
   181  		})
   182  	}
   183  
   184  	m, err := c.roundTrip(ctx, req.Addr, &createacls.Request{
   185  		Creations: acls,
   186  	})
   187  	if err != nil {
   188  		return nil, fmt.Errorf("kafka.(*Client).CreateACLs: %w", err)
   189  	}
   190  
   191  	res := m.(*createacls.Response)
   192  	ret := &CreateACLsResponse{
   193  		Throttle: makeDuration(res.ThrottleTimeMs),
   194  		Errors:   make([]error, 0, len(res.Results)),
   195  	}
   196  
   197  	for _, t := range res.Results {
   198  		ret.Errors = append(ret.Errors, makeError(t.ErrorCode, t.ErrorMessage))
   199  	}
   200  
   201  	return ret, nil
   202  }