-
Notifications
You must be signed in to change notification settings - Fork 152
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Functionality to call ingress operations after discovering APIVersion (…
…#1138) * Figure out ingress API before calling List/Get operations This commit adds wrapper around the std API's get and list methods so that we can first figure out which api version ingresses are part of, and then can call the respective methods. * Add another method `IngressPath` in `IngressMgr` interface Apart from getting/listting and creating the ingress resources we would also need to get the ingress path of provided ingress resource. Since that would depend on which APIVersion the ingress resource is from, its better we have that method as part of this interface. * Add comments, make consts * Address review comments * Address review comment, change order of var init * Address review comments * Make ingress name format const Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
- Loading branch information
1 parent
5fab1bb
commit 551d676
Showing
5 changed files
with
361 additions
and
1 deletion.
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
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,88 @@ | ||
// Copyright 2019 The Kanister Authors. | ||
// | ||
// 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 ingress | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/pkg/errors" | ||
extensionsv1beta1 "k8s.io/api/extensions/v1beta1" | ||
apierrors "k8s.io/apimachinery/pkg/api/errors" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/client-go/kubernetes" | ||
) | ||
|
||
// ExtensionsV1beta1 implements ingress.Manager interface | ||
type ExtensionsV1beta1 struct { | ||
kubeCli kubernetes.Interface | ||
} | ||
|
||
func NewExtensionsV1beta1(cli kubernetes.Interface) *ExtensionsV1beta1 { | ||
return &ExtensionsV1beta1{ | ||
kubeCli: cli, | ||
} | ||
} | ||
|
||
// List can be used to list all the ingress resources from `ns` namespace | ||
func (i *ExtensionsV1beta1) List(ctx context.Context, ns string) (runtime.Object, error) { | ||
return i.kubeCli.ExtensionsV1beta1().Ingresses(ns).List(ctx, metav1.ListOptions{}) | ||
} | ||
|
||
// Get can be used to to get ingress resource with name `name` in `ns` namespace | ||
func (i *ExtensionsV1beta1) Get(ctx context.Context, ns, name string) (runtime.Object, error) { | ||
return i.kubeCli.ExtensionsV1beta1().Ingresses(ns).Get(ctx, name, metav1.GetOptions{}) | ||
} | ||
|
||
// IngressPath can be used to get the backend path that is specified in the | ||
// ingress resource in `ns` namespace and name `releaseName-ingress` | ||
func (i *ExtensionsV1beta1) IngressPath(ctx context.Context, ns, releaseName string) (string, error) { | ||
obj, err := i.Get(ctx, ns, fmt.Sprintf(ingressNameFormat, releaseName, ingressNameSuffix)) | ||
if apierrors.IsNotFound(err) { | ||
// Try the release name if the ingress does not exist. | ||
// This is possible if the user setup OIDC using the localhost IP | ||
// and has port forwarding turned on to access K10. | ||
return releaseName, nil | ||
} | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
ingress := obj.(*extensionsv1beta1.Ingress) | ||
if len(ingress.Spec.Rules) == 0 { | ||
return "", errors.Wrapf(err, "No ingress rules were found") | ||
} | ||
ingressHTTPRule := ingress.Spec.Rules[0].IngressRuleValue.HTTP | ||
if ingressHTTPRule == nil { | ||
return "", errors.Wrapf(err, "A HTTP ingress rule value is missing") | ||
} | ||
ingressPaths := ingressHTTPRule.Paths | ||
if len(ingressPaths) == 0 { | ||
return "", errors.Wrapf(err, "Failed to find HTTP paths in the ingress") | ||
} | ||
ingressPath := "" | ||
for _, path := range ingressPaths { | ||
if path.Backend.ServiceName == gatewaySvcName { | ||
ingressPath = path.Path | ||
break | ||
} | ||
} | ||
if ingressPath == "" { | ||
return "", errors.Wrapf(err, "No path was set for K10's gateway service") | ||
} | ||
|
||
return ingressPath, nil | ||
} |
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,88 @@ | ||
// Copyright 2019 The Kanister Authors. | ||
// | ||
// 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 ingress | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/pkg/errors" | ||
netv1beta1 "k8s.io/api/networking/v1beta1" | ||
apierrors "k8s.io/apimachinery/pkg/api/errors" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/client-go/kubernetes" | ||
) | ||
|
||
// NetworkingV1beta1 implements ingress.Manager interface | ||
type NetworkingV1beta1 struct { | ||
kubeCli kubernetes.Interface | ||
} | ||
|
||
func NewNetworkingV1beta1(cli kubernetes.Interface) *NetworkingV1beta1 { | ||
return &NetworkingV1beta1{ | ||
kubeCli: cli, | ||
} | ||
} | ||
|
||
// List can be used to list all the ingress resources from `ns` namespace | ||
func (i *NetworkingV1beta1) List(ctx context.Context, ns string) (runtime.Object, error) { | ||
return i.kubeCli.NetworkingV1beta1().Ingresses(ns).List(ctx, metav1.ListOptions{}) | ||
} | ||
|
||
// Get can be used to to get ingress resource with name `name` in `ns` namespace | ||
func (i *NetworkingV1beta1) Get(ctx context.Context, ns, name string) (runtime.Object, error) { | ||
return i.kubeCli.NetworkingV1beta1().Ingresses(ns).Get(ctx, name, metav1.GetOptions{}) | ||
} | ||
|
||
// IngressPath can be used to get the backend path that is specified in the | ||
// ingress resource in `ns` namespace and name `releaseName-ingress` | ||
func (i *NetworkingV1beta1) IngressPath(ctx context.Context, ns, releaseName string) (string, error) { | ||
obj, err := i.Get(ctx, ns, fmt.Sprintf(ingressNameFormat, releaseName, ingressNameSuffix)) | ||
if apierrors.IsNotFound(err) { | ||
// Try the release name if the ingress does not exist. | ||
// This is possible if the user setup OIDC using the localhost IP | ||
// and has port forwarding turned on to access K10. | ||
return releaseName, nil | ||
} | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
ingress := obj.(*netv1beta1.Ingress) | ||
if len(ingress.Spec.Rules) == 0 { | ||
return "", errors.Wrapf(err, "No ingress rules were found") | ||
} | ||
ingressHTTPRule := ingress.Spec.Rules[0].IngressRuleValue.HTTP | ||
if ingressHTTPRule == nil { | ||
return "", errors.Wrapf(err, "A HTTP ingress rule value is missing") | ||
} | ||
ingressPaths := ingressHTTPRule.Paths | ||
if len(ingressPaths) == 0 { | ||
return "", errors.Wrapf(err, "Failed to find HTTP paths in the ingress") | ||
} | ||
ingressPath := "" | ||
for _, path := range ingressPaths { | ||
if path.Backend.ServiceName == gatewaySvcName { | ||
ingressPath = path.Path | ||
break | ||
} | ||
} | ||
if ingressPath == "" { | ||
return "", errors.Wrapf(err, "No path was set for K10's gateway service") | ||
} | ||
|
||
return ingressPath, nil | ||
} |
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,88 @@ | ||
// Copyright 2019 The Kanister Authors. | ||
// | ||
// 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 ingress | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/pkg/errors" | ||
netv1 "k8s.io/api/networking/v1" | ||
apierrors "k8s.io/apimachinery/pkg/api/errors" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/client-go/kubernetes" | ||
) | ||
|
||
// NetworkingV1 implements ingress.Manager interface | ||
type NetworkingV1 struct { | ||
kubeCli kubernetes.Interface | ||
} | ||
|
||
func NewNetworkingV1(cli kubernetes.Interface) *NetworkingV1 { | ||
return &NetworkingV1{ | ||
kubeCli: cli, | ||
} | ||
} | ||
|
||
// List can be used to list all the ingress resources from `ns` namespace | ||
func (i *NetworkingV1) List(ctx context.Context, ns string) (runtime.Object, error) { | ||
return i.kubeCli.NetworkingV1().Ingresses(ns).List(ctx, metav1.ListOptions{}) | ||
} | ||
|
||
// Get can be used to to get ingress resource with name `name` in `ns` namespace | ||
func (i *NetworkingV1) Get(ctx context.Context, ns, name string) (runtime.Object, error) { | ||
return i.kubeCli.NetworkingV1().Ingresses(ns).Get(ctx, name, metav1.GetOptions{}) | ||
} | ||
|
||
// IngressPath can be used to get the backend path that is specified in the | ||
// ingress resource in `ns` namespace and name `releaseName-ingress` | ||
func (i *NetworkingV1) IngressPath(ctx context.Context, ns, releaseName string) (string, error) { | ||
obj, err := i.Get(ctx, ns, fmt.Sprintf(ingressNameFormat, releaseName, ingressNameSuffix)) | ||
if apierrors.IsNotFound(err) { | ||
// Try the release name if the ingress does not exist. | ||
// This is possible if the user setup OIDC using the localhost IP | ||
// and has port forwarding turned on to access K10. | ||
return releaseName, nil | ||
} | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
ingress := obj.(*netv1.Ingress) | ||
if len(ingress.Spec.Rules) == 0 { | ||
return "", errors.Wrapf(err, "No ingress rules were found") | ||
} | ||
ingressHTTPRule := ingress.Spec.Rules[0].IngressRuleValue.HTTP | ||
if ingressHTTPRule == nil { | ||
return "", errors.Wrapf(err, "A HTTP ingress rule value is missing") | ||
} | ||
ingressPaths := ingressHTTPRule.Paths | ||
if len(ingressPaths) == 0 { | ||
return "", errors.Wrapf(err, "Failed to find HTTP paths in the ingress") | ||
} | ||
ingressPath := "" | ||
for _, path := range ingressPaths { | ||
if path.Backend.Service.Name == gatewaySvcName { | ||
ingressPath = path.Path | ||
break | ||
} | ||
} | ||
if ingressPath == "" { | ||
return "", errors.Wrapf(err, "No path was set for K10's gateway service") | ||
} | ||
|
||
return ingressPath, nil | ||
} |
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,76 @@ | ||
// Copyright 2019 The Kanister Authors. | ||
// | ||
// 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 ingress | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/pkg/errors" | ||
extensionsv1beta1 "k8s.io/api/extensions/v1beta1" | ||
netv1 "k8s.io/api/networking/v1" | ||
netv1beta1 "k8s.io/api/networking/v1beta1" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/client-go/kubernetes" | ||
|
||
"github.com/kanisterio/kanister/pkg/kube" | ||
) | ||
|
||
const ( | ||
ingressRes = "ingresses" | ||
gatewaySvcName = "gateway" | ||
ingressNameSuffix = "ingress" | ||
ingressNameFormat = "%s-%s" | ||
) | ||
|
||
// Manager is an abstraction over the behaviour of the ingress resources that | ||
// depends on the APIVersion of the ingress resource | ||
type Manager interface { | ||
// List can be used to list all the ingress resources from `ns` namespace | ||
List(ctx context.Context, ns string) (runtime.Object, error) | ||
// Get can be used to to get ingress resource with name `name` in `ns` namespace | ||
Get(ctx context.Context, ns, name string) (runtime.Object, error) | ||
// IngressPath can be used to get the backend path that is specified in the | ||
// ingress resource in `ns` namespace and name `releaseName-ingress` | ||
IngressPath(ctx context.Context, ns, releaseName string) (string, error) | ||
} | ||
|
||
// NewManager can be used to get the Manager based on the APIVersion of the ingress resources on the cluster | ||
// so that, respecitve methods from that APIVersion can be called | ||
func NewManager(ctx context.Context, kubeCli kubernetes.Interface) (Manager, error) { | ||
exists, err := kube.IsResAvailableInGroupVersion(ctx, kubeCli.Discovery(), netv1.GroupName, netv1.SchemeGroupVersion.Version, ingressRes) | ||
if err != nil { | ||
return nil, errors.Errorf("Failed to call discovery APIs: %v", err) | ||
} | ||
if exists { | ||
return NewNetworkingV1(kubeCli), nil | ||
} | ||
|
||
exists, err = kube.IsResAvailableInGroupVersion(ctx, kubeCli.Discovery(), extensionsv1beta1.GroupName, extensionsv1beta1.SchemeGroupVersion.Version, ingressRes) | ||
if err != nil { | ||
return nil, errors.Errorf("Failed to call discovery APIs: %v", err) | ||
} | ||
if exists { | ||
return NewExtensionsV1beta1(kubeCli), nil | ||
} | ||
|
||
exists, err = kube.IsResAvailableInGroupVersion(ctx, kubeCli.Discovery(), netv1beta1.GroupName, netv1beta1.SchemeGroupVersion.Version, ingressRes) | ||
if err != nil { | ||
return nil, errors.Errorf("Failed to call discovery APIs: %v", err) | ||
} | ||
if exists { | ||
return NewNetworkingV1beta1(kubeCli), nil | ||
} | ||
return nil, errors.New("Ingress resources are not available") | ||
} |