-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(CLI): add connectors describe (#2082)
* fixes * move common print utils * utilize utility functions * describe a connector * fix lint * Update cmd/conduit/root/pipelines/describe.go Co-authored-by: Lovro Mažgon <lovro.mazgon@gmail.com> * Update cmd/conduit/root/connectors/describe.go Co-authored-by: Lovro Mažgon <lovro.mazgon@gmail.com> * Update cmd/conduit/internal/print_utils.go Co-authored-by: Lovro Mažgon <lovro.mazgon@gmail.com> * display processors on pipelines desc and sort * add some tests * lint --------- Co-authored-by: Lovro Mažgon <lovro.mazgon@gmail.com>
- Loading branch information
1 parent
37457e2
commit ac8fff0
Showing
12 changed files
with
415 additions
and
95 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,72 @@ | ||
// Copyright © 2025 Meroxa, Inc. | ||
// | ||
// 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 internal | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
apiv1 "github.com/conduitio/conduit/proto/api/v1" | ||
"google.golang.org/protobuf/types/known/timestamppb" | ||
) | ||
|
||
// Indentation returns a string with the number of spaces equal to the level | ||
func Indentation(level int) string { | ||
return strings.Repeat(" ", level) | ||
} | ||
|
||
// PrintStatusFromProtoString returns a human-readable status from a proto status | ||
func PrintStatusFromProtoString(protoStatus string) string { | ||
return PrettyProtoEnum("STATUS_", protoStatus) | ||
} | ||
|
||
// PrettyProtoEnum returns a human-readable string from a proto enum | ||
func PrettyProtoEnum(prefix, protoEnum string) string { | ||
return strings.ToLower( | ||
strings.TrimPrefix(protoEnum, prefix), | ||
) | ||
} | ||
|
||
// PrintTime returns a human-readable time from a timestamp | ||
func PrintTime(ts *timestamppb.Timestamp) string { | ||
return ts.AsTime().Format("2006-01-02T15:04:05Z") | ||
} | ||
|
||
// DisplayProcessors prints the processors in a human-readable format | ||
func DisplayProcessors(processors []*apiv1.Processor, indent int) { | ||
if len(processors) == 0 { | ||
return | ||
} | ||
|
||
fmt.Printf("%sProcessors:\n", Indentation(indent)) | ||
|
||
for _, p := range processors { | ||
fmt.Printf("%s- ID: %s\n", Indentation(indent+1), p.Id) | ||
fmt.Printf("%sPlugin: %s\n", Indentation(indent+2), p.Plugin) | ||
|
||
if p.Condition != "" { | ||
fmt.Printf("%sCondition: %s\n", Indentation(indent+2), p.Condition) | ||
} | ||
|
||
fmt.Printf("%sConfig:\n", Indentation(indent+2)) | ||
for name, value := range p.Config.Settings { | ||
fmt.Printf("%s%s: %s\n", Indentation(indent+3), name, value) | ||
} | ||
fmt.Printf("%sWorkers: %d\n", Indentation(indent+3), p.Config.Workers) | ||
|
||
fmt.Printf("%sCreated At: %s\n", Indentation(indent+2), PrintTime(p.CreatedAt)) | ||
fmt.Printf("%sUpdated At: %s\n", Indentation(indent+2), PrintTime(p.UpdatedAt)) | ||
} | ||
} |
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
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
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,133 @@ | ||
// Copyright © 2025 Meroxa, Inc. | ||
// | ||
// 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 connectors | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/conduitio/conduit/cmd/conduit/api" | ||
"github.com/conduitio/conduit/cmd/conduit/cecdysis" | ||
"github.com/conduitio/conduit/cmd/conduit/internal" | ||
"github.com/conduitio/conduit/pkg/foundation/cerrors" | ||
apiv1 "github.com/conduitio/conduit/proto/api/v1" | ||
"github.com/conduitio/ecdysis" | ||
) | ||
|
||
var ( | ||
_ cecdysis.CommandWithExecuteWithClient = (*DescribeCommand)(nil) | ||
_ ecdysis.CommandWithAliases = (*DescribeCommand)(nil) | ||
_ ecdysis.CommandWithDocs = (*DescribeCommand)(nil) | ||
_ ecdysis.CommandWithArgs = (*DescribeCommand)(nil) | ||
) | ||
|
||
type DescribeArgs struct { | ||
ConnectorID string | ||
} | ||
|
||
type DescribeCommand struct { | ||
args DescribeArgs | ||
} | ||
|
||
func (c *DescribeCommand) Usage() string { return "describe" } | ||
|
||
func (c *DescribeCommand) Docs() ecdysis.Docs { | ||
return ecdysis.Docs{ | ||
Short: "Describe an existing connector", | ||
Long: `This command requires Conduit to be already running since it will describe a connector registered | ||
by Conduit. You can list existing connectors with the 'conduit connectors list' command.`, | ||
Example: "conduit connectors describe connector:source\n" + | ||
"conduit connectors desc connector:destination", | ||
} | ||
} | ||
|
||
func (c *DescribeCommand) Aliases() []string { return []string{"desc"} } | ||
|
||
func (c *DescribeCommand) Args(args []string) error { | ||
if len(args) == 0 { | ||
return cerrors.Errorf("requires a connector ID") | ||
} | ||
|
||
if len(args) > 1 { | ||
return cerrors.Errorf("too many arguments") | ||
} | ||
|
||
c.args.ConnectorID = args[0] | ||
return nil | ||
} | ||
|
||
func (c *DescribeCommand) ExecuteWithClient(ctx context.Context, client *api.Client) error { | ||
resp, err := client.ConnectorServiceClient.GetConnector(ctx, &apiv1.GetConnectorRequest{ | ||
Id: c.args.ConnectorID, | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("failed to get connector: %w", err) | ||
} | ||
|
||
var processors []*apiv1.Processor | ||
|
||
for _, processorID := range resp.Connector.ProcessorIds { | ||
processor, err := client.ProcessorServiceClient.GetProcessor(ctx, &apiv1.GetProcessorRequest{ | ||
Id: processorID, | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("failed to get processor: %w", err) | ||
} | ||
processors = append(processors, processor.Processor) | ||
} | ||
|
||
displayConnector(resp.Connector, processors) | ||
|
||
return nil | ||
} | ||
|
||
func displayConnector(connector *apiv1.Connector, processors []*apiv1.Processor) { | ||
if connector == nil { | ||
return | ||
} | ||
|
||
fmt.Printf("ID: %s\n", connector.Id) | ||
|
||
var connectorType string | ||
|
||
switch connector.Type { | ||
case apiv1.Connector_TYPE_SOURCE: | ||
connectorType = "Source" | ||
case apiv1.Connector_TYPE_DESTINATION: | ||
connectorType = "Destination" | ||
case apiv1.Connector_TYPE_UNSPECIFIED: | ||
connectorType = "Unspecified" | ||
default: | ||
connectorType = "Unknown" | ||
} | ||
|
||
fmt.Printf("Type: %s\n", connectorType) | ||
fmt.Printf("Plugin: %s\n", connector.Plugin) | ||
fmt.Printf("Pipeline ID: %s\n", connector.PipelineId) | ||
|
||
displayConnectorConfig(connector.Config) | ||
fmt.Printf("Created At: %s\n", internal.PrintTime(connector.CreatedAt)) | ||
fmt.Printf("Updated At: %s\n", internal.PrintTime(connector.UpdatedAt)) | ||
|
||
internal.DisplayProcessors(processors, 0) | ||
} | ||
|
||
func displayConnectorConfig(cfg *apiv1.Connector_Config) { | ||
fmt.Println("Config:") | ||
|
||
for name, value := range cfg.Settings { | ||
fmt.Printf("%s%s: %s\n", internal.Indentation(1), name, value) | ||
} | ||
} |
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,56 @@ | ||
// Copyright © 2025 Meroxa, Inc. | ||
// | ||
// 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 connectors | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/matryer/is" | ||
) | ||
|
||
func TestDescribeExecutionNoArgs(t *testing.T) { | ||
is := is.New(t) | ||
|
||
c := DescribeCommand{} | ||
err := c.Args([]string{}) | ||
|
||
expected := "requires a connector ID" | ||
|
||
is.True(err != nil) | ||
is.Equal(err.Error(), expected) | ||
} | ||
|
||
func TestDescribeExecutionMultipleArgs(t *testing.T) { | ||
is := is.New(t) | ||
|
||
c := DescribeCommand{} | ||
err := c.Args([]string{"foo", "bar"}) | ||
|
||
expected := "too many arguments" | ||
|
||
is.True(err != nil) | ||
is.Equal(err.Error(), expected) | ||
} | ||
|
||
func TestDescribeExecutionCorrectArgs(t *testing.T) { | ||
is := is.New(t) | ||
connectorID := "my-connector" | ||
|
||
c := DescribeCommand{} | ||
err := c.Args([]string{connectorID}) | ||
|
||
is.NoErr(err) | ||
is.Equal(c.args.ConnectorID, connectorID) | ||
} |
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
Oops, something went wrong.