Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions internal/kube/site/site.go
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,7 @@ func (s *Site) CheckConnector(name string, connector *skupperv2alpha1.Connector)
return s.updateConnectorConfiguredStatus(connector, stderrors.New("No active site in namespace"))
}
var tlsErr error
var specErr error
if connector != nil {
tlsErr = s.missingTlsCredentialsErr(connector.Spec.TlsCredentials)
if tlsErr != nil {
Expand All @@ -1067,6 +1068,9 @@ func (s *Site) CheckConnector(name string, connector *skupperv2alpha1.Connector)
slog.String("secret", connector.Spec.TlsCredentials),
)
}
if connector.Spec.Host == "" && connector.Spec.Selector == "" {
specErr = stderrors.New("Connector must define either spec.host or spec.selector")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest including "non-empty" as a qualifier here: Connector must define a non-empty spec.host or spec.selector. If anyone ever sees this message, they have already defined one of these fields.

As I'm sure you noticed when testing, the kubernetes API refuses an invalid Connector that does not satisfy a oneOf required selector or host.

$ cat << EOF | kubectl apply -f -
apiVersion: skupper.io/v2alpha1
kind: Connector
metadata:
  name: invalid
spec:
  port: 8888
  routingKey: test

EOF

The Connector "invalid" is invalid:
* <nil>: Invalid value: "": "spec" must validate one and only one schema (oneOf). Found none valid
* spec.selector: Required value

$ cat << EOF | kubectl apply -f -
apiVersion: skupper.io/v2alpha1
kind: Connector
metadata:
  name: invalid
spec:
  port: 8888
  routingKey: test
  host: ""
  selector: ""
EOF
The Connector "invalid" is invalid: <nil>: Invalid value: "": "spec" must validate one and only one schema (oneOf). Found 2 valid alternatives

To "trick" it you need to provide either host or selector with an empty string (really was a miss on our api spec side.) Because of how our go types were set up, we end up missing that distinction and can't easily plainly say "Invalid value for host|selector. Must not be empty".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see thanks for letting me know, I'll implement that change later today👍.

}
}
update := s.bindings.UpdateConnector(name, connector)
if connector == nil {
Expand All @@ -1076,13 +1080,13 @@ func (s *Site) CheckConnector(name string, connector *skupperv2alpha1.Connector)
return nil
}
if update == nil {
if tlsErr != nil {
return s.updateConnectorConfiguredStatus(connector, tlsErr)
if err := stderrors.Join(tlsErr, specErr); err != nil {
return s.updateConnectorConfiguredStatus(connector, err)
}
return nil
}
routerErr := s.updateRouterConfig(update)
return s.updateConnectorConfiguredStatus(connector, stderrors.Join(tlsErr, routerErr))
return s.updateConnectorConfiguredStatus(connector, stderrors.Join(tlsErr, specErr, routerErr))
}

func (s *Site) updateListenerStatus(listener *skupperv2alpha1.Listener, err error) error {
Expand Down
47 changes: 43 additions & 4 deletions internal/kube/site/site_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,8 @@ func TestSite_CheckConnector(t *testing.T) {
wantErr bool
want string
wantConnectors uint
wantConfigured bool
wantErrMessage string
k8sObjects []runtime.Object
skupperObjects []runtime.Object
skupperErrorMessage string
Expand Down Expand Up @@ -823,6 +825,38 @@ func TestSite_CheckConnector(t *testing.T) {
want: "initialized",
wantErr: false,
wantConnectors: 1,
wantConfigured: true,
},
{
name: "connector missing host and selector",
args: args{
name: "connector1",
connector: &skupperv2alpha1.Connector{
ObjectMeta: metav1.ObjectMeta{
Name: "connector1",
Namespace: "test",
UID: "8a96ffdf-403b-4e4a-83a8-97d3d459adb6",
},
Spec: skupperv2alpha1.ConnectorSpec{
RoutingKey: "backend",
Port: 8080,
Type: "tcp",
},
},
},
skupperObjects: []runtime.Object{
&skupperv2alpha1.Connector{
ObjectMeta: metav1.ObjectMeta{
Name: "connector1",
Namespace: "test",
},
},
},
want: "initialized",
wantErr: false,
wantConnectors: 1,
wantConfigured: false,
wantErrMessage: "Connector must define either spec.host or spec.selector",
},
}
for _, tt := range tests {
Expand All @@ -844,19 +878,24 @@ func TestSite_CheckConnector(t *testing.T) {
connector := s.bindings.bindings.GetConnector(tt.args.name)
if tt.wantConnectors != 0 {
connectorConfigured := false
var configuredMessage string
if connector == nil {
t.Errorf("Site.Checkconnector() expected connector doesn't exist")
} else {
if connector.Spec.Port != tt.args.connector.Spec.Port {
t.Errorf("Site.Checkconnector() expected connector doesn't have correct values")
}
for _, condition := range connector.Status.Conditions {
if condition.Type == "Configured" && condition.Status == "True" {
connectorConfigured = true
if condition.Type == "Configured" {
connectorConfigured = condition.Status == "True"
configuredMessage = condition.Message
}
}
if connectorConfigured == false {
t.Errorf("Site.CheckConnector() link not in expected configured state")
if connectorConfigured != tt.wantConfigured {
t.Errorf("Site.CheckConnector() connector configured = %v, want %v", connectorConfigured, tt.wantConfigured)
}
if tt.wantErrMessage != "" && configuredMessage != tt.wantErrMessage {
t.Errorf("Site.CheckConnector() configured message = %q, want %q", configuredMessage, tt.wantErrMessage)
}
}
} else if connector != nil {
Expand Down
Loading