-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#3 added reosurce type of a resource which an ACL can be applied to
- Loading branch information
Krishnakant C
authored and
Krishnakant C
committed
Sep 10, 2024
1 parent
b3b7f6f
commit b00fe84
Showing
2 changed files
with
238 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// Copyright 2024 Atomstate Technologies Private Limited | ||
// | ||
// 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 resource | ||
|
||
import ( | ||
"errors" | ||
"strings" | ||
) | ||
|
||
// ResourceType represents a type of resource which an ACL can be applied to. | ||
type ResourceType byte | ||
|
||
const ( | ||
// UNRECOGNIZED represents any ResourceType which this client cannot understand. | ||
UNRECOGNIZED ResourceType = iota | ||
|
||
// ALL_RESOURCES matches any ResourceType. | ||
ALL_RESOURCES | ||
|
||
// TOPIC represents a Kafka topic. | ||
TOPIC | ||
|
||
// GROUP represents a consumer group. | ||
GROUP | ||
|
||
// CLUSTER represents the cluster as a whole. | ||
CLUSTER | ||
|
||
// TRANSACTIONAL_ID represents a transactional ID. | ||
TRANSACTIONAL_ID | ||
|
||
// DELEGATION_TOKEN represents a token ID. | ||
DELEGATION_TOKEN | ||
|
||
// USER represents a user principal. | ||
USER | ||
|
||
resourceTypeCount // Keep this at the end for the number of resource types | ||
) | ||
|
||
// resourceTypeNames maps ResourceType values to their string representations. | ||
var resourceTypeNames = [resourceTypeCount]string{ | ||
"UNRECOGNIZED", | ||
"ALL_RESOURCES", | ||
"TOPIC", | ||
"GROUP", | ||
"CLUSTER", | ||
"TRANSACTIONAL_ID", | ||
"DELEGATION_TOKEN", | ||
"USER", | ||
} | ||
|
||
// FromString parses the given string as an ACL resource type. | ||
// | ||
// Example usage: | ||
// | ||
// resType, err := FromString("topic") | ||
// if err != nil { | ||
// fmt.Println(err) | ||
// } else { | ||
// fmt.Printf("Parsed ResourceType: %d\n", resType) | ||
// } | ||
// | ||
// This will output: | ||
// | ||
// Parsed ResourceType: 2 | ||
func FromString(str string) (ResourceType, error) { | ||
if str == "" { | ||
return UNRECOGNIZED, errors.New("input string is empty") | ||
} | ||
|
||
// Normalize the input string to upper case for comparison | ||
str = strings.ToUpper(str) | ||
|
||
for i := range resourceTypeNames { | ||
if resourceTypeNames[i] == str { | ||
return ResourceType(i), nil | ||
} | ||
} | ||
return UNRECOGNIZED, errors.New("unknown resource type") | ||
} | ||
|
||
// FromCode returns the ResourceType with the provided code or UNRECOGNIZED if one cannot be found. | ||
// | ||
// Example usage: | ||
// | ||
// code := byte(3) | ||
// resTypeFromCode := FromCode(code) | ||
// fmt.Printf("ResourceType from code %d: %d\n", code, resTypeFromCode) | ||
// | ||
// This will output: | ||
// | ||
// ResourceType from code 3: 3 | ||
func FromCode(code byte) ResourceType { | ||
if code < byte(resourceTypeCount) { | ||
return ResourceType(code) | ||
} | ||
return UNRECOGNIZED | ||
} | ||
|
||
// Code returns the code of this resource type. | ||
func (r ResourceType) Code() byte { | ||
return byte(r) | ||
} | ||
|
||
// IsUnrecognized returns whether this resource type is UNRECOGNIZED. | ||
func (r ResourceType) IsUnrecognized() bool { | ||
return r == UNRECOGNIZED | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// Copyright 2024 Atomstate Technologies Private Limited | ||
// | ||
// 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 resource | ||
|
||
import "testing" | ||
|
||
// Unit tests | ||
func TestFromString(t *testing.T) { | ||
tests := []struct { | ||
input string | ||
expected ResourceType | ||
hasError bool | ||
}{ | ||
{"UNRECOGNIZED", UNRECOGNIZED, false}, | ||
{"ALL_RESOURCES", ALL_RESOURCES, false}, | ||
{"TOPIC", TOPIC, false}, | ||
{"GROUP", GROUP, false}, | ||
{"CLUSTER", CLUSTER, false}, | ||
{"TRANSACTIONAL_ID", TRANSACTIONAL_ID, false}, | ||
{"DELEGATION_TOKEN", DELEGATION_TOKEN, false}, | ||
{"USER", USER, false}, | ||
{"", UNRECOGNIZED, true}, // empty string, expect error | ||
{"INVALID_TYPE", UNRECOGNIZED, true}, // invalid type, expect error | ||
} | ||
|
||
for _, test := range tests { | ||
result, err := FromString(test.input) | ||
if (err != nil) != test.hasError { | ||
t.Errorf("FromString(%q) error = %v, wantError %v", test.input, err, test.hasError) | ||
} | ||
if result != test.expected { | ||
t.Errorf("FromString(%q) = %v, want %v", test.input, result, test.expected) | ||
} | ||
} | ||
} | ||
|
||
func TestFromCode(t *testing.T) { | ||
tests := []struct { | ||
code byte | ||
expected ResourceType | ||
}{ | ||
{0, UNRECOGNIZED}, | ||
{1, ALL_RESOURCES}, | ||
{2, TOPIC}, | ||
{3, GROUP}, | ||
{4, CLUSTER}, | ||
{5, TRANSACTIONAL_ID}, | ||
{6, DELEGATION_TOKEN}, | ||
{7, USER}, | ||
{8, UNRECOGNIZED}, // out of bounds | ||
} | ||
|
||
for _, test := range tests { | ||
result := FromCode(test.code) | ||
if result != test.expected { | ||
t.Errorf("FromCode(%d) = %v, want %v", test.code, result, test.expected) | ||
} | ||
} | ||
} | ||
|
||
func TestRTCode(t *testing.T) { | ||
tests := []struct { | ||
resourceType ResourceType | ||
expectedCode byte | ||
}{ | ||
{UNRECOGNIZED, 0}, | ||
{ALL_RESOURCES, 1}, | ||
{TOPIC, 2}, | ||
{GROUP, 3}, | ||
{CLUSTER, 4}, | ||
{TRANSACTIONAL_ID, 5}, | ||
{DELEGATION_TOKEN, 6}, | ||
{USER, 7}, | ||
} | ||
|
||
for _, test := range tests { | ||
result := test.resourceType.Code() | ||
if result != test.expectedCode { | ||
t.Errorf("Code() for %v = %d, want %d", test.resourceType, result, test.expectedCode) | ||
} | ||
} | ||
} | ||
|
||
func TestIsUnrecognized(t *testing.T) { | ||
tests := []struct { | ||
resourceType ResourceType | ||
expected bool | ||
}{ | ||
{UNRECOGNIZED, true}, | ||
{ALL_RESOURCES, false}, | ||
{TOPIC, false}, | ||
{GROUP, false}, | ||
{CLUSTER, false}, | ||
{TRANSACTIONAL_ID, false}, | ||
{DELEGATION_TOKEN, false}, | ||
{USER, false}, | ||
} | ||
|
||
for _, test := range tests { | ||
result := test.resourceType.IsUnrecognized() | ||
if result != test.expected { | ||
t.Errorf("IsUnrecognized() for %v = %v, want %v", test.resourceType, result, test.expected) | ||
} | ||
} | ||
} |