Sync the certificate from che-git-self-signed-cert to user namespaces (#1222)
feat: Sync the git tls certificate configuration in a format digestable by DWO. Other slightly related changes: * Make sure the version content annotations survive across multiple conversions between v1 and v2alpha1. * Add DWO watch labels so that our stuff is picked up. * irifrance/gini has moved to go-air/ginipull/1249/head
parent
777f2687bf
commit
0e72bb2ca8
|
|
@ -300,7 +300,7 @@
|
||||||
| [github.com/golangplus/bytes@45c989fe545070ef7c9003cf1998bb195c61731a](https://github.com/golangplus/bytes.git) | BSD-3-Clause | [clearlydefined](https://clearlydefined.io/definitions/git/github/golangplus/bytes/45c989fe545070ef7c9003cf1998bb195c61731a) |
|
| [github.com/golangplus/bytes@45c989fe545070ef7c9003cf1998bb195c61731a](https://github.com/golangplus/bytes.git) | BSD-3-Clause | [clearlydefined](https://clearlydefined.io/definitions/git/github/golangplus/bytes/45c989fe545070ef7c9003cf1998bb195c61731a) |
|
||||||
| [github.com/grpc-ecosystem/grpc-health-probe@v0.3.2](https://github.com/grpc-ecosystem/grpc-health-probe.git) | Apache-2.0 | [clearlydefined](https://clearlydefined.io/definitions/git/github/grpc-ecosystem/grpc-health-probe/71ebd03865797e785bdc7ae6fababe548b75188e) |
|
| [github.com/grpc-ecosystem/grpc-health-probe@v0.3.2](https://github.com/grpc-ecosystem/grpc-health-probe.git) | Apache-2.0 | [clearlydefined](https://clearlydefined.io/definitions/git/github/grpc-ecosystem/grpc-health-probe/71ebd03865797e785bdc7ae6fababe548b75188e) |
|
||||||
| [github.com/hokaccha/go-prettyjson@108c894c2c0e4a3236172e3698c14f1e3199548d](https://github.com/hokaccha/go-prettyjson.git) | MIT | [clearlydefined](https://clearlydefined.io/definitions/git/github/hokaccha/go-prettyjson/108c894c2c0e4a3236172e3698c14f1e3199548d) |
|
| [github.com/hokaccha/go-prettyjson@108c894c2c0e4a3236172e3698c14f1e3199548d](https://github.com/hokaccha/go-prettyjson.git) | MIT | [clearlydefined](https://clearlydefined.io/definitions/git/github/hokaccha/go-prettyjson/108c894c2c0e4a3236172e3698c14f1e3199548d) |
|
||||||
| [github.com/irifrance/gini@v1.0.1](https://github.com/irifrance/gini.git) | MIT | [clearlydefined](https://clearlydefined.io/definitions/git/github/irifrance/gini/ab553a98575687dd98cf73371b2fc398f41d10fc) |
|
| [github.com/go-air/gini@v1.0.1](https://github.com/go-air/gini.git) | MIT | [clearlydefined](https://clearlydefined.io/definitions/git/github/go-air/gini/ab553a98575687dd98cf73371b2fc398f41d10fc) |
|
||||||
| [github.com/itchyny/astgen-go@cf3ea398f64584ef328f8fa3e0281536dbaffa4b](https://github.com/itchyny/astgen-go.git) | MIT | [clearlydefined](https://clearlydefined.io/definitions/git/github/itchyny/astgen-go/cf3ea398f64584ef328f8fa3e0281536dbaffa4b) |
|
| [github.com/itchyny/astgen-go@cf3ea398f64584ef328f8fa3e0281536dbaffa4b](https://github.com/itchyny/astgen-go.git) | MIT | [clearlydefined](https://clearlydefined.io/definitions/git/github/itchyny/astgen-go/cf3ea398f64584ef328f8fa3e0281536dbaffa4b) |
|
||||||
| [github.com/itchyny/gojq@v0.11.0](https://github.com/itchyny/gojq.git) | MIT | [clearlydefined](https://clearlydefined.io/definitions/git/github/itchyny/gojq/d33449f4c07af896f91db06c7b64052c92ebe42b) |
|
| [github.com/itchyny/gojq@v0.11.0](https://github.com/itchyny/gojq.git) | MIT | [clearlydefined](https://clearlydefined.io/definitions/git/github/itchyny/gojq/d33449f4c07af896f91db06c7b64052c92ebe42b) |
|
||||||
| [github.com/jackc/pgmock@13a1b77aafa2641ad31b655a18e8c3605ef55e2d](https://github.com/jackc/pgmock.git) | MIT | [clearlydefined](https://clearlydefined.io/definitions/git/github/jackc/pgmock/13a1b77aafa2641ad31b655a18e8c3605ef55e2d) |
|
| [github.com/jackc/pgmock@13a1b77aafa2641ad31b655a18e8c3605ef55e2d](https://github.com/jackc/pgmock.git) | MIT | [clearlydefined](https://clearlydefined.io/definitions/git/github/jackc/pgmock/13a1b77aafa2641ad31b655a18e8c3605ef55e2d) |
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ func V1ToV2alpha1(v1 *v1.CheCluster, v2 *v2alpha1.CheCluster) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v2.ObjectMeta = v1.ObjectMeta
|
v2.ObjectMeta = *v1.ObjectMeta.DeepCopy()
|
||||||
v2.Spec = v2Spec
|
v2.Spec = v2Spec
|
||||||
|
|
||||||
v1Spec, err := yaml.Marshal(v1.Spec)
|
v1Spec, err := yaml.Marshal(v1.Spec)
|
||||||
|
|
@ -89,7 +89,7 @@ func V2alpha1ToV1(v2 *v2alpha1.CheCluster, v1Obj *v1.CheCluster) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v1Obj.ObjectMeta = v2.ObjectMeta
|
v1Obj.ObjectMeta = *v2.ObjectMeta.DeepCopy()
|
||||||
v1Obj.Spec = v1Spec
|
v1Obj.Spec = v1Spec
|
||||||
v1Obj.Status = v1.CheClusterStatus{}
|
v1Obj.Status = v1.CheClusterStatus{}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/che-incubator/kubernetes-image-puller-operator/api/v1alpha1"
|
"github.com/che-incubator/kubernetes-image-puller-operator/api/v1alpha1"
|
||||||
v1 "github.com/eclipse-che/che-operator/api/v1"
|
v1 "github.com/eclipse-che/che-operator/api/v1"
|
||||||
"github.com/eclipse-che/che-operator/api/v2alpha1"
|
"github.com/eclipse-che/che-operator/api/v2alpha1"
|
||||||
|
|
@ -691,17 +693,13 @@ func TestFullCircleV1(t *testing.T) {
|
||||||
convertedV1 := v1.CheCluster{}
|
convertedV1 := v1.CheCluster{}
|
||||||
V2alpha1ToV1(&v2Obj, &convertedV1)
|
V2alpha1ToV1(&v2Obj, &convertedV1)
|
||||||
|
|
||||||
if !reflect.DeepEqual(&v1Obj, &convertedV1) {
|
assert.Empty(t, convertedV1.Annotations[v1StorageAnnotation])
|
||||||
t.Errorf("V1 not equal to itself after the conversion through v2alpha1: %v", cmp.Diff(&v1Obj, &convertedV1))
|
assert.NotEmpty(t, convertedV1.Annotations[v2alpha1StorageAnnotation])
|
||||||
}
|
|
||||||
|
|
||||||
if convertedV1.Annotations[v1StorageAnnotation] != "" {
|
// remove v2 content annotation on the convertedV1 so that it doesn't interfere with the equality.
|
||||||
t.Errorf("The v1 storage annotations should not be present on the v1 object")
|
delete(convertedV1.Annotations, v2alpha1StorageAnnotation)
|
||||||
}
|
|
||||||
|
|
||||||
if convertedV1.Annotations[v2alpha1StorageAnnotation] == "" {
|
assert.Equal(t, &v1Obj, &convertedV1)
|
||||||
t.Errorf("The v2alpha1 storage annotation should be present on the v1 object")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFullCircleV2(t *testing.T) {
|
func TestFullCircleV2(t *testing.T) {
|
||||||
|
|
@ -744,17 +742,13 @@ func TestFullCircleV2(t *testing.T) {
|
||||||
convertedV2 := v2alpha1.CheCluster{}
|
convertedV2 := v2alpha1.CheCluster{}
|
||||||
V1ToV2alpha1(&v1Obj, &convertedV2)
|
V1ToV2alpha1(&v1Obj, &convertedV2)
|
||||||
|
|
||||||
if !reflect.DeepEqual(&v2Obj, &convertedV2) {
|
assert.Empty(t, convertedV2.Annotations[v2alpha1StorageAnnotation])
|
||||||
t.Errorf("V2alpha1 not equal to itself after the conversion through v1: %v", cmp.Diff(&v2Obj, &convertedV2))
|
assert.NotEmpty(t, convertedV2.Annotations[v1StorageAnnotation])
|
||||||
}
|
|
||||||
|
|
||||||
if convertedV2.Annotations[v2alpha1StorageAnnotation] != "" {
|
// remove v1 content annotation on the convertedV1 so that it doesn't interfere with the equality.
|
||||||
t.Errorf("The v2alpha1 storage annotations should not be present on the v2alpha1 object")
|
delete(convertedV2.Annotations, v1StorageAnnotation)
|
||||||
}
|
|
||||||
|
|
||||||
if convertedV2.Annotations[v1StorageAnnotation] == "" {
|
assert.Equal(t, &v2Obj, &convertedV2)
|
||||||
t.Errorf("The v1 storage annotation should be present on the v2alpha1 object")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func onFakeOpenShift(f func()) {
|
func onFakeOpenShift(f func()) {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"k8s.io/utils/pointer"
|
||||||
|
|
||||||
"github.com/eclipse-che/che-operator/pkg/util"
|
"github.com/eclipse-che/che-operator/pkg/util"
|
||||||
|
|
||||||
"github.com/eclipse-che/che-operator/pkg/deploy/gateway"
|
"github.com/eclipse-che/che-operator/pkg/deploy/gateway"
|
||||||
|
|
@ -672,7 +674,7 @@ func determineEndpointScheme(e dw.Endpoint) string {
|
||||||
scheme = string(e.Protocol)
|
scheme = string(e.Protocol)
|
||||||
}
|
}
|
||||||
|
|
||||||
upgradeToSecure := e.Secure
|
upgradeToSecure := pointer.BoolPtrDerefOr(e.Secure, false)
|
||||||
|
|
||||||
// gateway is always on HTTPS, so if the endpoint is served through the gateway, we need to use the TLS'd variant.
|
// gateway is always on HTTPS, so if the endpoint is served through the gateway, we need to use the TLS'd variant.
|
||||||
if e.Attributes.GetString(urlRewriteSupportedEndpointAttributeName, nil) == "true" {
|
if e.Attributes.GetString(urlRewriteSupportedEndpointAttributeName, nil) == "true" {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/utils/pointer"
|
||||||
|
|
||||||
"github.com/eclipse-che/che-operator/pkg/util"
|
"github.com/eclipse-che/che-operator/pkg/util"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
@ -145,7 +147,7 @@ func subdomainDevWorkspaceRouting() *dwo.DevWorkspaceRouting {
|
||||||
Exposure: dw.PublicEndpointExposure,
|
Exposure: dw.PublicEndpointExposure,
|
||||||
Protocol: "http",
|
Protocol: "http",
|
||||||
Path: "/2.js",
|
Path: "/2.js",
|
||||||
Secure: true,
|
Secure: pointer.BoolPtr(true),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "e3",
|
Name: "e3",
|
||||||
|
|
@ -186,7 +188,7 @@ func relocatableDevWorkspaceRouting() *dwo.DevWorkspaceRouting {
|
||||||
Exposure: dw.PublicEndpointExposure,
|
Exposure: dw.PublicEndpointExposure,
|
||||||
Protocol: "http",
|
Protocol: "http",
|
||||||
Path: "/2.js",
|
Path: "/2.js",
|
||||||
Secure: true,
|
Secure: pointer.BoolPtr(true),
|
||||||
Attributes: attributes.Attributes{
|
Attributes: attributes.Attributes{
|
||||||
urlRewriteSupportedEndpointAttributeName: apiext.JSON{Raw: []byte("\"true\"")},
|
urlRewriteSupportedEndpointAttributeName: apiext.JSON{Raw: []byte("\"true\"")},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ func (r *CheUserNamespaceReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||||
For(obj).
|
For(obj).
|
||||||
Watches(&source.Kind{Type: &corev1.Secret{}}, r.watchRulesForSecrets(ctx)).
|
Watches(&source.Kind{Type: &corev1.Secret{}}, r.watchRulesForSecrets(ctx)).
|
||||||
Watches(&source.Kind{Type: &corev1.ConfigMap{}}, r.watchRulesForConfigMaps(ctx)).
|
Watches(&source.Kind{Type: &corev1.ConfigMap{}}, r.watchRulesForConfigMaps(ctx)).
|
||||||
Watches(&source.Kind{Type: &v1.CheCluster{}}, r.triggerAllNamespaces(ctx))
|
Watches(&source.Kind{Type: &v1.CheCluster{}}, r.triggerAllNamespaces())
|
||||||
|
|
||||||
return bld.Complete(r)
|
return bld.Complete(r)
|
||||||
}
|
}
|
||||||
|
|
@ -155,7 +155,7 @@ func (r *CheUserNamespaceReconciler) isInManagedNamespace(ctx context.Context, o
|
||||||
return err == nil && info != nil && info.OwnerUid != ""
|
return err == nil && info != nil && info.OwnerUid != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *CheUserNamespaceReconciler) triggerAllNamespaces(ctx context.Context) handler.EventHandler {
|
func (r *CheUserNamespaceReconciler) triggerAllNamespaces() handler.EventHandler {
|
||||||
return handler.EnqueueRequestsFromMapFunc(
|
return handler.EnqueueRequestsFromMapFunc(
|
||||||
handler.MapFunc(func(obj client.Object) []reconcile.Request {
|
handler.MapFunc(func(obj client.Object) []reconcile.Request {
|
||||||
nss := r.namespaceCache.GetAllKnownNamespaces()
|
nss := r.namespaceCache.GetAllKnownNamespaces()
|
||||||
|
|
@ -228,6 +228,11 @@ func (r *CheUserNamespaceReconciler) Reconcile(ctx context.Context, req ctrl.Req
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = r.reconcileGitTlsCertificate(ctx, req.Name, checluster, deployContext); err != nil {
|
||||||
|
logrus.Errorf("Failed to reconcile Che git TLS certificate into namespace '%s': %v", req.Name, err)
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
return ctrl.Result{}, nil
|
return ctrl.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -286,7 +291,8 @@ func (r *CheUserNamespaceReconciler) reconcileSelfSignedCert(ctx context.Context
|
||||||
Name: targetCertName,
|
Name: targetCertName,
|
||||||
Namespace: targetNs,
|
Namespace: targetNs,
|
||||||
Labels: defaults.AddStandardLabelsForComponent(checluster, userSettingsComponentLabelValue, map[string]string{
|
Labels: defaults.AddStandardLabelsForComponent(checluster, userSettingsComponentLabelValue, map[string]string{
|
||||||
constants.DevWorkspaceMountLabel: "true",
|
constants.DevWorkspaceMountLabel: "true",
|
||||||
|
constants.DevWorkspaceWatchSecretLabel: "true",
|
||||||
}),
|
}),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
constants.DevWorkspaceMountAsAnnotation: "file",
|
constants.DevWorkspaceMountAsAnnotation: "file",
|
||||||
|
|
@ -330,7 +336,8 @@ func (r *CheUserNamespaceReconciler) reconcileTrustedCerts(ctx context.Context,
|
||||||
Name: targetConfigMapName,
|
Name: targetConfigMapName,
|
||||||
Namespace: targetNs,
|
Namespace: targetNs,
|
||||||
Labels: defaults.AddStandardLabelsForComponent(checluster, userSettingsComponentLabelValue, map[string]string{
|
Labels: defaults.AddStandardLabelsForComponent(checluster, userSettingsComponentLabelValue, map[string]string{
|
||||||
constants.DevWorkspaceMountLabel: "true",
|
constants.DevWorkspaceMountLabel: "true",
|
||||||
|
constants.DevWorkspaceWatchConfigMapLabel: "true",
|
||||||
}),
|
}),
|
||||||
Annotations: addToFirst(sourceMap.Annotations, map[string]string{
|
Annotations: addToFirst(sourceMap.Annotations, map[string]string{
|
||||||
constants.DevWorkspaceMountAsAnnotation: "file",
|
constants.DevWorkspaceMountAsAnnotation: "file",
|
||||||
|
|
@ -397,7 +404,8 @@ func (r *CheUserNamespaceReconciler) reconcileProxySettings(ctx context.Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
requiredLabels := defaults.AddStandardLabelsForComponent(checluster, userSettingsComponentLabelValue, map[string]string{
|
requiredLabels := defaults.AddStandardLabelsForComponent(checluster, userSettingsComponentLabelValue, map[string]string{
|
||||||
constants.DevWorkspaceMountLabel: "true",
|
constants.DevWorkspaceMountLabel: "true",
|
||||||
|
constants.DevWorkspaceWatchConfigMapLabel: "true",
|
||||||
})
|
})
|
||||||
requiredAnnos := map[string]string{
|
requiredAnnos := map[string]string{
|
||||||
constants.DevWorkspaceMountAsAnnotation: "env",
|
constants.DevWorkspaceMountAsAnnotation: "env",
|
||||||
|
|
@ -421,6 +429,50 @@ func (r *CheUserNamespaceReconciler) reconcileProxySettings(ctx context.Context,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *CheUserNamespaceReconciler) reconcileGitTlsCertificate(ctx context.Context, targetNs string, checluster *v2alpha1.CheCluster, deployContext *deploy.DeployContext) error {
|
||||||
|
targetName := prefixedName(checluster, "git-tls-creds")
|
||||||
|
delConfigMap := func() error {
|
||||||
|
_, err := deploy.Delete(deployContext, client.ObjectKey{Name: targetName, Namespace: targetNs}, &corev1.Secret{})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
clusterv1 := org.AsV1(checluster)
|
||||||
|
if !clusterv1.Spec.Server.GitSelfSignedCert {
|
||||||
|
return delConfigMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
gitCert := &corev1.ConfigMap{}
|
||||||
|
|
||||||
|
if err := deployContext.ClusterAPI.Client.Get(ctx, client.ObjectKey{Name: deploy.GitSelfSignedCertsConfigMapName, Namespace: checluster.Namespace}, gitCert); err != nil {
|
||||||
|
if !errors.IsNotFound(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return delConfigMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
target := corev1.ConfigMap{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "ConfigMap",
|
||||||
|
APIVersion: "v1",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: targetName,
|
||||||
|
Namespace: targetNs,
|
||||||
|
Labels: defaults.AddStandardLabelsForComponent(checluster, userSettingsComponentLabelValue, map[string]string{
|
||||||
|
constants.DevWorkspaceGitTLSLabel: "true",
|
||||||
|
constants.DevWorkspaceWatchConfigMapLabel: "true",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
Data: map[string]string{
|
||||||
|
"host": gitCert.Data["githost"],
|
||||||
|
"certificate": gitCert.Data["ca.crt"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := deploy.DoSync(deployContext, &target, deploy.ConfigMapDiffOpts)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func prefixedName(checluster *v2alpha1.CheCluster, name string) string {
|
func prefixedName(checluster *v2alpha1.CheCluster, name string) string {
|
||||||
return checluster.Name + "-" + checluster.Namespace + "-" + name
|
return checluster.Name + "-" + checluster.Namespace + "-" + name
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,8 @@ func setupCheCluster(t *testing.T, ctx context.Context, cl client.Client, scheme
|
||||||
},
|
},
|
||||||
Spec: v1.CheClusterSpec{
|
Spec: v1.CheClusterSpec{
|
||||||
Server: v1.CheClusterSpecServer{
|
Server: v1.CheClusterSpecServer{
|
||||||
CheHost: "che-host",
|
CheHost: "che-host",
|
||||||
|
GitSelfSignedCert: true,
|
||||||
CustomCheProperties: map[string]string{
|
CustomCheProperties: map[string]string{
|
||||||
"CHE_INFRA_OPENSHIFT_ROUTE_HOST_DOMAIN__SUFFIX": "root-domain",
|
"CHE_INFRA_OPENSHIFT_ROUTE_HOST_DOMAIN__SUFFIX": "root-domain",
|
||||||
},
|
},
|
||||||
|
|
@ -106,6 +107,20 @@ func setupCheCluster(t *testing.T, ctx context.Context, cl client.Client, scheme
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gitTlsCredentials := &corev1.ConfigMap{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: deploy.GitSelfSignedCertsConfigMapName,
|
||||||
|
Namespace: cheNamespaceName,
|
||||||
|
},
|
||||||
|
Data: map[string]string{
|
||||||
|
"githost": "the.host.of.git",
|
||||||
|
"ca.crt": "the public certificate of the.host.of.git",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err := cl.Create(ctx, gitTlsCredentials); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
r := devworkspace.New(cl, scheme)
|
r := devworkspace.New(cl, scheme)
|
||||||
// the reconciliation needs to run twice for it to be truly finished - we're setting up finalizers etc...
|
// the reconciliation needs to run twice for it to be truly finished - we're setting up finalizers etc...
|
||||||
if _, err := r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: cheName, Namespace: cheNamespaceName}}); err != nil {
|
if _, err := r.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: cheName, Namespace: cheNamespaceName}}); err != nil {
|
||||||
|
|
@ -301,6 +316,13 @@ func TestCreatesDataInNamespace(t *testing.T) {
|
||||||
assert.Equal(t, 2, len(caCerts.Data), "Expecting exactly 2 data entries in the trusted cert config map")
|
assert.Equal(t, 2, len(caCerts.Data), "Expecting exactly 2 data entries in the trusted cert config map")
|
||||||
assert.Equal(t, "trusted cert 1", string(caCerts.Data["trusted1"]), "Unexpected trusted cert 1 value")
|
assert.Equal(t, "trusted cert 1", string(caCerts.Data["trusted1"]), "Unexpected trusted cert 1 value")
|
||||||
assert.Equal(t, "trusted cert 2", string(caCerts.Data["trusted2"]), "Unexpected trusted cert 2 value")
|
assert.Equal(t, "trusted cert 2", string(caCerts.Data["trusted2"]), "Unexpected trusted cert 2 value")
|
||||||
|
|
||||||
|
gitTlsConfig := corev1.ConfigMap{}
|
||||||
|
assert.NoError(t, cl.Get(ctx, client.ObjectKey{Name: "che-eclipse-che-git-tls-creds", Namespace: namespace.GetName()}, &gitTlsConfig))
|
||||||
|
assert.Equal(t, "true", gitTlsConfig.Labels[constants.DevWorkspaceGitTLSLabel])
|
||||||
|
assert.Equal(t, "true", gitTlsConfig.Labels[constants.DevWorkspaceWatchConfigMapLabel])
|
||||||
|
assert.Equal(t, "the.host.of.git", gitTlsConfig.Data["host"])
|
||||||
|
assert.Equal(t, "the public certificate of the.host.of.git", gitTlsConfig.Data["certificate"])
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("k8s", func(t *testing.T) {
|
t.Run("k8s", func(t *testing.T) {
|
||||||
|
|
|
||||||
6
go.mod
6
go.mod
|
|
@ -7,8 +7,8 @@ require (
|
||||||
github.com/bitly/go-simplejson v0.0.0-00010101000000-000000000000 // indirect
|
github.com/bitly/go-simplejson v0.0.0-00010101000000-000000000000 // indirect
|
||||||
github.com/blang/semver/v4 v4.0.0
|
github.com/blang/semver/v4 v4.0.0
|
||||||
github.com/che-incubator/kubernetes-image-puller-operator v0.0.0-20210929175054-0128446f5af7
|
github.com/che-incubator/kubernetes-image-puller-operator v0.0.0-20210929175054-0128446f5af7
|
||||||
github.com/devfile/api/v2 v2.0.0-20210713124824-03e023e7078b
|
github.com/devfile/api/v2 v2.0.0-20210917193329-089a48011460
|
||||||
github.com/devfile/devworkspace-operator v0.2.1-0.20211005102315-728dff7e987c
|
github.com/devfile/devworkspace-operator v0.2.1-0.20211213140302-4226bdb05e56
|
||||||
github.com/go-logr/logr v0.4.0
|
github.com/go-logr/logr v0.4.0
|
||||||
github.com/golang/mock v1.5.0
|
github.com/golang/mock v1.5.0
|
||||||
github.com/google/go-cmp v0.5.6
|
github.com/google/go-cmp v0.5.6
|
||||||
|
|
@ -212,7 +212,7 @@ replace (
|
||||||
github.com/huandu/xstrings => github.com/huandu/xstrings v1.2.0
|
github.com/huandu/xstrings => github.com/huandu/xstrings v1.2.0
|
||||||
github.com/imdario/mergo => github.com/imdario/mergo v0.3.5
|
github.com/imdario/mergo => github.com/imdario/mergo v0.3.5
|
||||||
github.com/inconshreveable/mousetrap => github.com/inconshreveable/mousetrap v1.0.0
|
github.com/inconshreveable/mousetrap => github.com/inconshreveable/mousetrap v1.0.0
|
||||||
github.com/irifrance/gini => github.com/irifrance/gini v1.0.1
|
github.com/irifrance/gini => github.com/go-air/gini v1.0.1
|
||||||
github.com/itchyny/astgen-go => github.com/itchyny/astgen-go v0.0.0-20200519013840-cf3ea398f645
|
github.com/itchyny/astgen-go => github.com/itchyny/astgen-go v0.0.0-20200519013840-cf3ea398f645
|
||||||
github.com/itchyny/go-flags => github.com/itchyny/go-flags v1.5.0
|
github.com/itchyny/go-flags => github.com/itchyny/go-flags v1.5.0
|
||||||
github.com/itchyny/gojq => github.com/itchyny/gojq v0.11.0
|
github.com/itchyny/gojq => github.com/itchyny/gojq v0.11.0
|
||||||
|
|
|
||||||
10
go.sum
10
go.sum
|
|
@ -115,10 +115,10 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||||
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
|
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
|
||||||
github.com/deislabs/oras v0.8.1/go.mod h1:Mx0rMSbBNaNfY9hjpccEnxkOqJL6KGjtxNHPLC4G4As=
|
github.com/deislabs/oras v0.8.1/go.mod h1:Mx0rMSbBNaNfY9hjpccEnxkOqJL6KGjtxNHPLC4G4As=
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20190204142019-df6d76eb9289/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
|
github.com/denisenkom/go-mssqldb v0.0.0-20190204142019-df6d76eb9289/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
|
||||||
github.com/devfile/api/v2 v2.0.0-20210713124824-03e023e7078b h1:N00ORHA5iamvPKpDFfSAkAczAaCBvK8l0EzAphsgFSI=
|
github.com/devfile/api/v2 v2.0.0-20210917193329-089a48011460 h1:cmd+3poyUwevcWchYdvE02YT1nQU4SJpA5/wrdLrpWE=
|
||||||
github.com/devfile/api/v2 v2.0.0-20210713124824-03e023e7078b/go.mod h1:QNzaIVQnCsYfXed+QZOn1uvEQFzyhvpi/uc3g/b2ws0=
|
github.com/devfile/api/v2 v2.0.0-20210917193329-089a48011460/go.mod h1:kLX/nW93gigOHXK3NLeJL2fSS/sgEe+OHu8bo3aoOi4=
|
||||||
github.com/devfile/devworkspace-operator v0.2.1-0.20211005102315-728dff7e987c h1:ua0f1tLDmxUhKPFHbSIxKE/oWB7GHZNhVRoh3V/NStU=
|
github.com/devfile/devworkspace-operator v0.2.1-0.20211213140302-4226bdb05e56 h1:2BDnr7bPGoAs4vCiW5XIwp4M0L9Mecbvm5N48AuNgoc=
|
||||||
github.com/devfile/devworkspace-operator v0.2.1-0.20211005102315-728dff7e987c/go.mod h1:NJBkFTNuP1vusHXm8yky1hjA1JVtRdrWl49vaQs0eiw=
|
github.com/devfile/devworkspace-operator v0.2.1-0.20211213140302-4226bdb05e56/go.mod h1:XP3lnHXRIItnXEa4YKyk2ZnEthVQQWjcA219FZs2ZpM=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dhui/dktest v0.3.2/go.mod h1:l1/ib23a/CmxAe7yixtrYPc8Iy90Zy2udyaHINM5p58=
|
github.com/dhui/dktest v0.3.2/go.mod h1:l1/ib23a/CmxAe7yixtrYPc8Iy90Zy2udyaHINM5p58=
|
||||||
|
|
@ -166,6 +166,7 @@ github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680 h1:ZktWZesgun21uEDrwW7
|
||||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||||
github.com/globalsign/mgo v0.0.0-20160323214708-72aab81a5dec/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
github.com/globalsign/mgo v0.0.0-20160323214708-72aab81a5dec/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||||
|
github.com/go-air/gini v1.0.1/go.mod h1:swH5OTtiG/X/YrU06r288qZwq6I1agpbuXQOB55xqGU=
|
||||||
github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I=
|
github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I=
|
||||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||||
|
|
@ -274,7 +275,6 @@ github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
|
||||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/irifrance/gini v1.0.1/go.mod h1:swH5OTtiG/X/YrU06r288qZwq6I1agpbuXQOB55xqGU=
|
|
||||||
github.com/itchyny/astgen-go v0.0.0-20200519013840-cf3ea398f645/go.mod h1:296z3W7Xsrp2mlIY88ruDKscuvrkL6zXCNRtaYVshzw=
|
github.com/itchyny/astgen-go v0.0.0-20200519013840-cf3ea398f645/go.mod h1:296z3W7Xsrp2mlIY88ruDKscuvrkL6zXCNRtaYVshzw=
|
||||||
github.com/itchyny/go-flags v1.5.0/go.mod h1:lenkYuCobuxLBAd/HGFE4LRoW8D3B6iXRQfWYJ+MNbA=
|
github.com/itchyny/go-flags v1.5.0/go.mod h1:lenkYuCobuxLBAd/HGFE4LRoW8D3B6iXRQfWYJ+MNbA=
|
||||||
github.com/itchyny/gojq v0.11.0/go.mod h1:my6D2qN2Sm6qa+/5GsPDUZlCWGR+U8Qsa9he76sudv0=
|
github.com/itchyny/gojq v0.11.0/go.mod h1:my6D2qN2Sm6qa+/5GsPDUZlCWGR+U8Qsa9he76sudv0=
|
||||||
|
|
|
||||||
|
|
@ -18,14 +18,15 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// CommandGroupKind describes the kind of command group.
|
// CommandGroupKind describes the kind of command group.
|
||||||
// +kubebuilder:validation:Enum=build;run;test;debug
|
// +kubebuilder:validation:Enum=build;run;test;debug;deploy
|
||||||
type CommandGroupKind string
|
type CommandGroupKind string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
BuildCommandGroupKind CommandGroupKind = "build"
|
BuildCommandGroupKind CommandGroupKind = "build"
|
||||||
RunCommandGroupKind CommandGroupKind = "run"
|
RunCommandGroupKind CommandGroupKind = "run"
|
||||||
TestCommandGroupKind CommandGroupKind = "test"
|
TestCommandGroupKind CommandGroupKind = "test"
|
||||||
DebugCommandGroupKind CommandGroupKind = "debug"
|
DebugCommandGroupKind CommandGroupKind = "debug"
|
||||||
|
DeployCommandGroupKind CommandGroupKind = "deploy"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CommandGroup struct {
|
type CommandGroup struct {
|
||||||
|
|
@ -34,7 +35,7 @@ type CommandGroup struct {
|
||||||
|
|
||||||
// +optional
|
// +optional
|
||||||
// Identifies the default command for a given group kind
|
// Identifies the default command for a given group kind
|
||||||
IsDefault bool `json:"isDefault,omitempty"`
|
IsDefault *bool `json:"isDefault,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BaseCommand struct {
|
type BaseCommand struct {
|
||||||
|
|
@ -144,7 +145,7 @@ type ExecCommand struct {
|
||||||
// If set to `true` the command won't be restarted and it is expected to handle file changes on its own.
|
// If set to `true` the command won't be restarted and it is expected to handle file changes on its own.
|
||||||
//
|
//
|
||||||
// Default value is `false`
|
// Default value is `false`
|
||||||
HotReloadCapable bool `json:"hotReloadCapable,omitempty"`
|
HotReloadCapable *bool `json:"hotReloadCapable,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApplyCommand struct {
|
type ApplyCommand struct {
|
||||||
|
|
@ -163,7 +164,7 @@ type CompositeCommand struct {
|
||||||
|
|
||||||
// Indicates if the sub-commands should be executed concurrently
|
// Indicates if the sub-commands should be executed concurrently
|
||||||
// +optional
|
// +optional
|
||||||
Parallel bool `json:"parallel,omitempty"`
|
Parallel *bool `json:"parallel,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CustomCommand struct {
|
type CustomCommand struct {
|
||||||
|
|
|
||||||
2
vendor/github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2/component_container.go
generated
vendored
2
vendor/github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2/component_container.go
generated
vendored
|
|
@ -69,7 +69,7 @@ type Container struct {
|
||||||
//
|
//
|
||||||
// Default value is `false`
|
// Default value is `false`
|
||||||
// +optional
|
// +optional
|
||||||
DedicatedPod bool `json:"dedicatedPod,omitempty"`
|
DedicatedPod *bool `json:"dedicatedPod,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type EnvVar struct {
|
type EnvVar struct {
|
||||||
|
|
|
||||||
38
vendor/github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2/component_image.go
generated
vendored
Normal file
38
vendor/github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2/component_image.go
generated
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
package v1alpha2
|
||||||
|
|
||||||
|
// ImageType describes the type of image.
|
||||||
|
// Only one of the following image type may be specified.
|
||||||
|
// +kubebuilder:validation:Enum=Dockerfile
|
||||||
|
type ImageType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
DockerfileImageType ImageType = "Dockerfile"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BaseImage struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Component that allows the developer to build a runtime image for outerloop
|
||||||
|
type ImageComponent struct {
|
||||||
|
BaseComponent `json:",inline"`
|
||||||
|
Image `json:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Image struct {
|
||||||
|
// Name of the image for the resulting outerloop build
|
||||||
|
ImageName string `json:"imageName"`
|
||||||
|
ImageUnion `json:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +union
|
||||||
|
type ImageUnion struct {
|
||||||
|
// Type of image
|
||||||
|
//
|
||||||
|
// +unionDiscriminator
|
||||||
|
// +optional
|
||||||
|
ImageType ImageType `json:"imageType,omitempty"`
|
||||||
|
|
||||||
|
// Allows specifying dockerfile type build
|
||||||
|
// +optional
|
||||||
|
Dockerfile *DockerfileImage `json:"dockerfile,omitempty"`
|
||||||
|
}
|
||||||
81
vendor/github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2/component_image_dockerfile.go
generated
vendored
Normal file
81
vendor/github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2/component_image_dockerfile.go
generated
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
package v1alpha2
|
||||||
|
|
||||||
|
// DockerfileSrcType describes the type of
|
||||||
|
// the src for the Dockerfile outerloop build.
|
||||||
|
// Only one of the following location type may be specified.
|
||||||
|
// +kubebuilder:validation:Enum=Uri;DevfileRegistry;Git
|
||||||
|
type DockerfileSrcType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
UriLikeDockerfileSrcType DockerfileSrcType = "Uri"
|
||||||
|
DevfileRegistryLikeDockerfileSrcType DockerfileSrcType = "DevfileRegistry"
|
||||||
|
GitLikeDockerfileSrcType DockerfileSrcType = "Git"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Dockerfile Image type to specify the outerloop build using a Dockerfile
|
||||||
|
type DockerfileImage struct {
|
||||||
|
BaseImage `json:",inline"`
|
||||||
|
DockerfileSrc `json:",inline"`
|
||||||
|
Dockerfile `json:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +union
|
||||||
|
type DockerfileSrc struct {
|
||||||
|
// Type of Dockerfile src
|
||||||
|
// +
|
||||||
|
// +unionDiscriminator
|
||||||
|
// +optional
|
||||||
|
SrcType DockerfileSrcType `json:"srcType,omitempty"`
|
||||||
|
|
||||||
|
// URI Reference of a Dockerfile.
|
||||||
|
// It can be a full URL or a relative URI from the current devfile as the base URI.
|
||||||
|
// +optional
|
||||||
|
Uri string `json:"uri,omitempty"`
|
||||||
|
|
||||||
|
// Dockerfile's Devfile Registry source
|
||||||
|
// +optional
|
||||||
|
DevfileRegistry *DockerfileDevfileRegistrySource `json:"devfileRegistry,omitempty"`
|
||||||
|
|
||||||
|
// Dockerfile's Git source
|
||||||
|
// +optional
|
||||||
|
Git *DockerfileGitProjectSource `json:"git,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Dockerfile struct {
|
||||||
|
// Path of source directory to establish build context. Defaults to ${PROJECT_ROOT} in the container
|
||||||
|
// +optional
|
||||||
|
BuildContext string `json:"buildContext,omitempty"`
|
||||||
|
|
||||||
|
// The arguments to supply to the dockerfile build.
|
||||||
|
// +optional
|
||||||
|
Args []string `json:"args,omitempty" patchStrategy:"replace"`
|
||||||
|
|
||||||
|
// Specify if a privileged builder pod is required.
|
||||||
|
//
|
||||||
|
// Default value is `false`
|
||||||
|
// +optional
|
||||||
|
RootRequired *bool `json:"rootRequired,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DockerfileDevfileRegistrySource struct {
|
||||||
|
// Id in a devfile registry that contains a Dockerfile. The src in the OCI registry
|
||||||
|
// required for the Dockerfile build will be downloaded for building the image.
|
||||||
|
Id string `json:"id"`
|
||||||
|
|
||||||
|
// Devfile Registry URL to pull the Dockerfile from when using the Devfile Registry as Dockerfile src.
|
||||||
|
// To ensure the Dockerfile gets resolved consistently in different environments,
|
||||||
|
// it is recommended to always specify the `devfileRegistryUrl` when `Id` is used.
|
||||||
|
// +optional
|
||||||
|
RegistryUrl string `json:"registryUrl,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DockerfileGitProjectSource struct {
|
||||||
|
// Git src for the Dockerfile build. The src required for the Dockerfile build will need to be
|
||||||
|
// cloned for building the image.
|
||||||
|
GitProjectSource `json:",inline"`
|
||||||
|
|
||||||
|
// Location of the Dockerfile in the Git repository when using git as Dockerfile src.
|
||||||
|
// Defaults to Dockerfile.
|
||||||
|
// +optional
|
||||||
|
FileLocation string `json:"fileLocation,omitempty"`
|
||||||
|
}
|
||||||
2
vendor/github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2/component_volume.go
generated
vendored
2
vendor/github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2/component_volume.go
generated
vendored
|
|
@ -15,5 +15,5 @@ type Volume struct {
|
||||||
// +optional
|
// +optional
|
||||||
// Ephemeral volumes are not stored persistently across restarts. Defaults
|
// Ephemeral volumes are not stored persistently across restarts. Defaults
|
||||||
// to false
|
// to false
|
||||||
Ephemeral bool `json:"ephemeral,omitempty"`
|
Ephemeral *bool `json:"ephemeral,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
// ComponentType describes the type of component.
|
// ComponentType describes the type of component.
|
||||||
// Only one of the following component type may be specified.
|
// Only one of the following component type may be specified.
|
||||||
// +kubebuilder:validation:Enum=Container;Kubernetes;Openshift;Volume;Plugin;Custom
|
// +kubebuilder:validation:Enum=Container;Kubernetes;Openshift;Volume;Image;Plugin;Custom
|
||||||
type ComponentType string
|
type ComponentType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -16,6 +16,7 @@ const (
|
||||||
OpenshiftComponentType ComponentType = "Openshift"
|
OpenshiftComponentType ComponentType = "Openshift"
|
||||||
PluginComponentType ComponentType = "Plugin"
|
PluginComponentType ComponentType = "Plugin"
|
||||||
VolumeComponentType ComponentType = "Volume"
|
VolumeComponentType ComponentType = "Volume"
|
||||||
|
ImageComponentType ComponentType = "Image"
|
||||||
CustomComponentType ComponentType = "Custom"
|
CustomComponentType ComponentType = "Custom"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -72,6 +73,10 @@ type ComponentUnion struct {
|
||||||
// +optional
|
// +optional
|
||||||
Volume *VolumeComponent `json:"volume,omitempty"`
|
Volume *VolumeComponent `json:"volume,omitempty"`
|
||||||
|
|
||||||
|
// Allows specifying the definition of an image for outer loop builds
|
||||||
|
// +optional
|
||||||
|
Image *ImageComponent `json:"image,omitempty"`
|
||||||
|
|
||||||
// Allows importing a plugin.
|
// Allows importing a plugin.
|
||||||
//
|
//
|
||||||
// Plugins are mainly imported devfiles that contribute components, commands
|
// Plugins are mainly imported devfiles that contribute components, commands
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ type DevWorkspaceTemplateSpec struct {
|
||||||
|
|
||||||
// +devfile:overrides:generate
|
// +devfile:overrides:generate
|
||||||
type DevWorkspaceTemplateSpecContent struct {
|
type DevWorkspaceTemplateSpecContent struct {
|
||||||
// Map of key-value variables used for string replacement in the devfile. Values can can be referenced via {{variable-key}}
|
// Map of key-value variables used for string replacement in the devfile. Values can be referenced via {{variable-key}}
|
||||||
// to replace the corresponding value in string fields in the devfile. Replacement cannot be used for
|
// to replace the corresponding value in string fields in the devfile. Replacement cannot be used for
|
||||||
//
|
//
|
||||||
// - schemaVersion, metadata, parent source
|
// - schemaVersion, metadata, parent source
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ type Endpoint struct {
|
||||||
// Describes whether the endpoint should be secured and protected by some
|
// Describes whether the endpoint should be secured and protected by some
|
||||||
// authentication process. This requires a protocol of `https` or `wss`.
|
// authentication process. This requires a protocol of `https` or `wss`.
|
||||||
// +optional
|
// +optional
|
||||||
Secure bool `json:"secure,omitempty"`
|
Secure *bool `json:"secure,omitempty"`
|
||||||
|
|
||||||
// Path of the endpoint URL
|
// Path of the endpoint URL
|
||||||
// +optional
|
// +optional
|
||||||
|
|
|
||||||
2
vendor/github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2/import_reference.go
generated
vendored
2
vendor/github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2/import_reference.go
generated
vendored
|
|
@ -47,7 +47,7 @@ type ImportReference struct {
|
||||||
|
|
||||||
// Registry URL to pull the parent devfile from when using id in the parent reference.
|
// Registry URL to pull the parent devfile from when using id in the parent reference.
|
||||||
// To ensure the parent devfile gets resolved consistently in different environments,
|
// To ensure the parent devfile gets resolved consistently in different environments,
|
||||||
// it is recommended to always specify the `regsitryURL` when `Id` is used.
|
// it is recommended to always specify the `registryUrl` when `id` is used.
|
||||||
// +optional
|
// +optional
|
||||||
RegistryUrl string `json:"registryUrl,omitempty"`
|
RegistryUrl string `json:"registryUrl,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,8 @@ type GitLikeProjectSource struct {
|
||||||
// +optional
|
// +optional
|
||||||
CheckoutFrom *CheckoutFrom `json:"checkoutFrom,omitempty"`
|
CheckoutFrom *CheckoutFrom `json:"checkoutFrom,omitempty"`
|
||||||
|
|
||||||
// The remotes map which should be initialized in the git project. Must have at least one remote configured
|
// The remotes map which should be initialized in the git project.
|
||||||
|
// Projects must have at least one remote configured while StarterProjects & Image Component's Git source can only have at most one remote configured.
|
||||||
Remotes map[string]string `json:"remotes"`
|
Remotes map[string]string `json:"remotes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
980
vendor/github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2/zz_generated.deepcopy.go
generated
vendored
980
vendor/github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2/zz_generated.deepcopy.go
generated
vendored
File diff suppressed because it is too large
Load Diff
|
|
@ -142,7 +142,7 @@ type CommandParentOverride struct {
|
||||||
// +union
|
// +union
|
||||||
type ComponentUnionParentOverride struct {
|
type ComponentUnionParentOverride struct {
|
||||||
|
|
||||||
// +kubebuilder:validation:Enum=Container;Kubernetes;Openshift;Volume;Plugin
|
// +kubebuilder:validation:Enum=Container;Kubernetes;Openshift;Volume;Image;Plugin
|
||||||
// Type of component
|
// Type of component
|
||||||
//
|
//
|
||||||
// +unionDiscriminator
|
// +unionDiscriminator
|
||||||
|
|
@ -172,6 +172,10 @@ type ComponentUnionParentOverride struct {
|
||||||
// +optional
|
// +optional
|
||||||
Volume *VolumeComponentParentOverride `json:"volume,omitempty"`
|
Volume *VolumeComponentParentOverride `json:"volume,omitempty"`
|
||||||
|
|
||||||
|
// Allows specifying the definition of an image for outer loop builds
|
||||||
|
// +optional
|
||||||
|
Image *ImageComponentParentOverride `json:"image,omitempty"`
|
||||||
|
|
||||||
// Allows importing a plugin.
|
// Allows importing a plugin.
|
||||||
//
|
//
|
||||||
// Plugins are mainly imported devfiles that contribute components, commands
|
// Plugins are mainly imported devfiles that contribute components, commands
|
||||||
|
|
@ -262,6 +266,12 @@ type VolumeComponentParentOverride struct {
|
||||||
VolumeParentOverride `json:",inline"`
|
VolumeParentOverride `json:",inline"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Component that allows the developer to build a runtime image for outerloop
|
||||||
|
type ImageComponentParentOverride struct {
|
||||||
|
BaseComponentParentOverride `json:",inline"`
|
||||||
|
ImageParentOverride `json:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
type PluginComponentParentOverride struct {
|
type PluginComponentParentOverride struct {
|
||||||
BaseComponentParentOverride `json:",inline"`
|
BaseComponentParentOverride `json:",inline"`
|
||||||
ImportReferenceParentOverride `json:",inline"`
|
ImportReferenceParentOverride `json:",inline"`
|
||||||
|
|
@ -330,7 +340,7 @@ type ExecCommandParentOverride struct {
|
||||||
// If set to `true` the command won't be restarted and it is expected to handle file changes on its own.
|
// If set to `true` the command won't be restarted and it is expected to handle file changes on its own.
|
||||||
//
|
//
|
||||||
// Default value is `false`
|
// Default value is `false`
|
||||||
HotReloadCapable bool `json:"hotReloadCapable,omitempty"`
|
HotReloadCapable *bool `json:"hotReloadCapable,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApplyCommandParentOverride struct {
|
type ApplyCommandParentOverride struct {
|
||||||
|
|
@ -350,7 +360,7 @@ type CompositeCommandParentOverride struct {
|
||||||
|
|
||||||
// Indicates if the sub-commands should be executed concurrently
|
// Indicates if the sub-commands should be executed concurrently
|
||||||
// +optional
|
// +optional
|
||||||
Parallel bool `json:"parallel,omitempty"`
|
Parallel *bool `json:"parallel,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DevWorkspace component: Anything that will bring additional features / tooling / behaviour / context
|
// DevWorkspace component: Anything that will bring additional features / tooling / behaviour / context
|
||||||
|
|
@ -420,7 +430,7 @@ type ContainerParentOverride struct {
|
||||||
//
|
//
|
||||||
// Default value is `false`
|
// Default value is `false`
|
||||||
// +optional
|
// +optional
|
||||||
DedicatedPod bool `json:"dedicatedPod,omitempty"`
|
DedicatedPod *bool `json:"dedicatedPod,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type EndpointParentOverride struct {
|
type EndpointParentOverride struct {
|
||||||
|
|
@ -471,7 +481,7 @@ type EndpointParentOverride struct {
|
||||||
// Describes whether the endpoint should be secured and protected by some
|
// Describes whether the endpoint should be secured and protected by some
|
||||||
// authentication process. This requires a protocol of `https` or `wss`.
|
// authentication process. This requires a protocol of `https` or `wss`.
|
||||||
// +optional
|
// +optional
|
||||||
Secure bool `json:"secure,omitempty"`
|
Secure *bool `json:"secure,omitempty"`
|
||||||
|
|
||||||
// Path of the endpoint URL
|
// Path of the endpoint URL
|
||||||
// +optional
|
// +optional
|
||||||
|
|
@ -507,7 +517,15 @@ type VolumeParentOverride struct {
|
||||||
// +optional
|
// +optional
|
||||||
// Ephemeral volumes are not stored persistently across restarts. Defaults
|
// Ephemeral volumes are not stored persistently across restarts. Defaults
|
||||||
// to false
|
// to false
|
||||||
Ephemeral bool `json:"ephemeral,omitempty"`
|
Ephemeral *bool `json:"ephemeral,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImageParentOverride struct {
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
// Name of the image for the resulting outerloop build
|
||||||
|
ImageName string `json:"imageName,omitempty"`
|
||||||
|
ImageUnionParentOverride `json:",inline"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ImportReferenceParentOverride struct {
|
type ImportReferenceParentOverride struct {
|
||||||
|
|
@ -515,7 +533,7 @@ type ImportReferenceParentOverride struct {
|
||||||
|
|
||||||
// Registry URL to pull the parent devfile from when using id in the parent reference.
|
// Registry URL to pull the parent devfile from when using id in the parent reference.
|
||||||
// To ensure the parent devfile gets resolved consistently in different environments,
|
// To ensure the parent devfile gets resolved consistently in different environments,
|
||||||
// it is recommended to always specify the `regsitryURL` when `Id` is used.
|
// it is recommended to always specify the `registryUrl` when `id` is used.
|
||||||
// +optional
|
// +optional
|
||||||
RegistryUrl string `json:"registryUrl,omitempty"`
|
RegistryUrl string `json:"registryUrl,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
@ -548,7 +566,8 @@ type GitLikeProjectSourceParentOverride struct {
|
||||||
CheckoutFrom *CheckoutFromParentOverride `json:"checkoutFrom,omitempty"`
|
CheckoutFrom *CheckoutFromParentOverride `json:"checkoutFrom,omitempty"`
|
||||||
|
|
||||||
// +optional
|
// +optional
|
||||||
// The remotes map which should be initialized in the git project. Must have at least one remote configured
|
// The remotes map which should be initialized in the git project.
|
||||||
|
// Projects must have at least one remote configured while StarterProjects & Image Component's Git source can only have at most one remote configured.
|
||||||
Remotes map[string]string `json:"remotes,omitempty"`
|
Remotes map[string]string `json:"remotes,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -615,6 +634,21 @@ type K8sLikeComponentLocationParentOverride struct {
|
||||||
Inlined string `json:"inlined,omitempty"`
|
Inlined string `json:"inlined,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// +union
|
||||||
|
type ImageUnionParentOverride struct {
|
||||||
|
|
||||||
|
// +kubebuilder:validation:Enum=Dockerfile
|
||||||
|
// Type of image
|
||||||
|
//
|
||||||
|
// +unionDiscriminator
|
||||||
|
// +optional
|
||||||
|
ImageType ImageTypeParentOverride `json:"imageType,omitempty"`
|
||||||
|
|
||||||
|
// Allows specifying dockerfile type build
|
||||||
|
// +optional
|
||||||
|
Dockerfile *DockerfileImageParentOverride `json:"dockerfile,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// Location from where the an import reference is retrieved
|
// Location from where the an import reference is retrieved
|
||||||
// +union
|
// +union
|
||||||
type ImportReferenceUnionParentOverride struct {
|
type ImportReferenceUnionParentOverride struct {
|
||||||
|
|
@ -705,6 +739,17 @@ type BaseCommandParentOverride struct {
|
||||||
// Only one of the following component type may be specified.
|
// Only one of the following component type may be specified.
|
||||||
type K8sLikeComponentLocationTypeParentOverride string
|
type K8sLikeComponentLocationTypeParentOverride string
|
||||||
|
|
||||||
|
// ImageType describes the type of image.
|
||||||
|
// Only one of the following image type may be specified.
|
||||||
|
type ImageTypeParentOverride string
|
||||||
|
|
||||||
|
// Dockerfile Image type to specify the outerloop build using a Dockerfile
|
||||||
|
type DockerfileImageParentOverride struct {
|
||||||
|
BaseImageParentOverride `json:",inline"`
|
||||||
|
DockerfileSrcParentOverride `json:",inline"`
|
||||||
|
DockerfileParentOverride `json:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
// ImportReferenceType describes the type of location
|
// ImportReferenceType describes the type of location
|
||||||
// from where the referenced template structure should be retrieved.
|
// from where the referenced template structure should be retrieved.
|
||||||
// Only one of the following parent locations may be specified.
|
// Only one of the following parent locations may be specified.
|
||||||
|
|
@ -721,7 +766,7 @@ type KubernetesCustomResourceImportReferenceParentOverride struct {
|
||||||
// +union
|
// +union
|
||||||
type ComponentUnionPluginOverrideParentOverride struct {
|
type ComponentUnionPluginOverrideParentOverride struct {
|
||||||
|
|
||||||
// +kubebuilder:validation:Enum=Container;Kubernetes;Openshift;Volume
|
// +kubebuilder:validation:Enum=Container;Kubernetes;Openshift;Volume;Image
|
||||||
// Type of component
|
// Type of component
|
||||||
//
|
//
|
||||||
// +unionDiscriminator
|
// +unionDiscriminator
|
||||||
|
|
@ -750,6 +795,10 @@ type ComponentUnionPluginOverrideParentOverride struct {
|
||||||
// shared by several other components
|
// shared by several other components
|
||||||
// +optional
|
// +optional
|
||||||
Volume *VolumeComponentPluginOverrideParentOverride `json:"volume,omitempty"`
|
Volume *VolumeComponentPluginOverrideParentOverride `json:"volume,omitempty"`
|
||||||
|
|
||||||
|
// Allows specifying the definition of an image for outer loop builds
|
||||||
|
// +optional
|
||||||
|
Image *ImageComponentPluginOverrideParentOverride `json:"image,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +union
|
// +union
|
||||||
|
|
@ -793,7 +842,51 @@ type CommandGroupParentOverride struct {
|
||||||
|
|
||||||
// +optional
|
// +optional
|
||||||
// Identifies the default command for a given group kind
|
// Identifies the default command for a given group kind
|
||||||
IsDefault bool `json:"isDefault,omitempty"`
|
IsDefault *bool `json:"isDefault,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseImageParentOverride struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// +union
|
||||||
|
type DockerfileSrcParentOverride struct {
|
||||||
|
|
||||||
|
// +kubebuilder:validation:Enum=Uri;DevfileRegistry;Git
|
||||||
|
// Type of Dockerfile src
|
||||||
|
// +
|
||||||
|
// +unionDiscriminator
|
||||||
|
// +optional
|
||||||
|
SrcType DockerfileSrcTypeParentOverride `json:"srcType,omitempty"`
|
||||||
|
|
||||||
|
// URI Reference of a Dockerfile.
|
||||||
|
// It can be a full URL or a relative URI from the current devfile as the base URI.
|
||||||
|
// +optional
|
||||||
|
Uri string `json:"uri,omitempty"`
|
||||||
|
|
||||||
|
// Dockerfile's Devfile Registry source
|
||||||
|
// +optional
|
||||||
|
DevfileRegistry *DockerfileDevfileRegistrySourceParentOverride `json:"devfileRegistry,omitempty"`
|
||||||
|
|
||||||
|
// Dockerfile's Git source
|
||||||
|
// +optional
|
||||||
|
Git *DockerfileGitProjectSourceParentOverride `json:"git,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DockerfileParentOverride struct {
|
||||||
|
|
||||||
|
// Path of source directory to establish build context. Defaults to ${PROJECT_ROOT} in the container
|
||||||
|
// +optional
|
||||||
|
BuildContext string `json:"buildContext,omitempty"`
|
||||||
|
|
||||||
|
// The arguments to supply to the dockerfile build.
|
||||||
|
// +optional
|
||||||
|
Args []string `json:"args,omitempty" patchStrategy:"replace"`
|
||||||
|
|
||||||
|
// Specify if a privileged builder pod is required.
|
||||||
|
//
|
||||||
|
// Default value is `false`
|
||||||
|
// +optional
|
||||||
|
RootRequired *bool `json:"rootRequired,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ComponentType describes the type of component.
|
// ComponentType describes the type of component.
|
||||||
|
|
@ -823,6 +916,12 @@ type VolumeComponentPluginOverrideParentOverride struct {
|
||||||
VolumePluginOverrideParentOverride `json:",inline"`
|
VolumePluginOverrideParentOverride `json:",inline"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Component that allows the developer to build a runtime image for outerloop
|
||||||
|
type ImageComponentPluginOverrideParentOverride struct {
|
||||||
|
BaseComponentPluginOverrideParentOverride `json:",inline"`
|
||||||
|
ImagePluginOverrideParentOverride `json:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
// CommandType describes the type of command.
|
// CommandType describes the type of command.
|
||||||
// Only one of the following command type may be specified.
|
// Only one of the following command type may be specified.
|
||||||
type CommandTypePluginOverrideParentOverride string
|
type CommandTypePluginOverrideParentOverride string
|
||||||
|
|
@ -867,7 +966,7 @@ type ExecCommandPluginOverrideParentOverride struct {
|
||||||
// If set to `true` the command won't be restarted and it is expected to handle file changes on its own.
|
// If set to `true` the command won't be restarted and it is expected to handle file changes on its own.
|
||||||
//
|
//
|
||||||
// Default value is `false`
|
// Default value is `false`
|
||||||
HotReloadCapable bool `json:"hotReloadCapable,omitempty"`
|
HotReloadCapable *bool `json:"hotReloadCapable,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApplyCommandPluginOverrideParentOverride struct {
|
type ApplyCommandPluginOverrideParentOverride struct {
|
||||||
|
|
@ -887,13 +986,44 @@ type CompositeCommandPluginOverrideParentOverride struct {
|
||||||
|
|
||||||
// Indicates if the sub-commands should be executed concurrently
|
// Indicates if the sub-commands should be executed concurrently
|
||||||
// +optional
|
// +optional
|
||||||
Parallel bool `json:"parallel,omitempty"`
|
Parallel *bool `json:"parallel,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommandGroupKind describes the kind of command group.
|
// CommandGroupKind describes the kind of command group.
|
||||||
// +kubebuilder:validation:Enum=build;run;test;debug
|
// +kubebuilder:validation:Enum=build;run;test;debug;deploy
|
||||||
type CommandGroupKindParentOverride string
|
type CommandGroupKindParentOverride string
|
||||||
|
|
||||||
|
// DockerfileSrcType describes the type of
|
||||||
|
// the src for the Dockerfile outerloop build.
|
||||||
|
// Only one of the following location type may be specified.
|
||||||
|
type DockerfileSrcTypeParentOverride string
|
||||||
|
|
||||||
|
type DockerfileDevfileRegistrySourceParentOverride struct {
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
// Id in a devfile registry that contains a Dockerfile. The src in the OCI registry
|
||||||
|
// required for the Dockerfile build will be downloaded for building the image.
|
||||||
|
Id string `json:"id,omitempty"`
|
||||||
|
|
||||||
|
// Devfile Registry URL to pull the Dockerfile from when using the Devfile Registry as Dockerfile src.
|
||||||
|
// To ensure the Dockerfile gets resolved consistently in different environments,
|
||||||
|
// it is recommended to always specify the `devfileRegistryUrl` when `Id` is used.
|
||||||
|
// +optional
|
||||||
|
RegistryUrl string `json:"registryUrl,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DockerfileGitProjectSourceParentOverride struct {
|
||||||
|
|
||||||
|
// Git src for the Dockerfile build. The src required for the Dockerfile build will need to be
|
||||||
|
// cloned for building the image.
|
||||||
|
GitProjectSourceParentOverride `json:",inline"`
|
||||||
|
|
||||||
|
// Location of the Dockerfile in the Git repository when using git as Dockerfile src.
|
||||||
|
// Defaults to Dockerfile.
|
||||||
|
// +optional
|
||||||
|
FileLocation string `json:"fileLocation,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// DevWorkspace component: Anything that will bring additional features / tooling / behaviour / context
|
// DevWorkspace component: Anything that will bring additional features / tooling / behaviour / context
|
||||||
// to the devworkspace, in order to make working in it easier.
|
// to the devworkspace, in order to make working in it easier.
|
||||||
type BaseComponentPluginOverrideParentOverride struct {
|
type BaseComponentPluginOverrideParentOverride struct {
|
||||||
|
|
@ -962,7 +1092,7 @@ type ContainerPluginOverrideParentOverride struct {
|
||||||
//
|
//
|
||||||
// Default value is `false`
|
// Default value is `false`
|
||||||
// +optional
|
// +optional
|
||||||
DedicatedPod bool `json:"dedicatedPod,omitempty"`
|
DedicatedPod *bool `json:"dedicatedPod,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type EndpointPluginOverrideParentOverride struct {
|
type EndpointPluginOverrideParentOverride struct {
|
||||||
|
|
@ -1013,7 +1143,7 @@ type EndpointPluginOverrideParentOverride struct {
|
||||||
// Describes whether the endpoint should be secured and protected by some
|
// Describes whether the endpoint should be secured and protected by some
|
||||||
// authentication process. This requires a protocol of `https` or `wss`.
|
// authentication process. This requires a protocol of `https` or `wss`.
|
||||||
// +optional
|
// +optional
|
||||||
Secure bool `json:"secure,omitempty"`
|
Secure *bool `json:"secure,omitempty"`
|
||||||
|
|
||||||
// Path of the endpoint URL
|
// Path of the endpoint URL
|
||||||
// +optional
|
// +optional
|
||||||
|
|
@ -1049,7 +1179,15 @@ type VolumePluginOverrideParentOverride struct {
|
||||||
// +optional
|
// +optional
|
||||||
// Ephemeral volumes are not stored persistently across restarts. Defaults
|
// Ephemeral volumes are not stored persistently across restarts. Defaults
|
||||||
// to false
|
// to false
|
||||||
Ephemeral bool `json:"ephemeral,omitempty"`
|
Ephemeral *bool `json:"ephemeral,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImagePluginOverrideParentOverride struct {
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
// Name of the image for the resulting outerloop build
|
||||||
|
ImageName string `json:"imageName,omitempty"`
|
||||||
|
ImageUnionPluginOverrideParentOverride `json:",inline"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LabeledCommandPluginOverrideParentOverride struct {
|
type LabeledCommandPluginOverrideParentOverride struct {
|
||||||
|
|
@ -1113,6 +1251,21 @@ type K8sLikeComponentLocationPluginOverrideParentOverride struct {
|
||||||
Inlined string `json:"inlined,omitempty"`
|
Inlined string `json:"inlined,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// +union
|
||||||
|
type ImageUnionPluginOverrideParentOverride struct {
|
||||||
|
|
||||||
|
// +kubebuilder:validation:Enum=Dockerfile
|
||||||
|
// Type of image
|
||||||
|
//
|
||||||
|
// +unionDiscriminator
|
||||||
|
// +optional
|
||||||
|
ImageType ImageTypePluginOverrideParentOverride `json:"imageType,omitempty"`
|
||||||
|
|
||||||
|
// Allows specifying dockerfile type build
|
||||||
|
// +optional
|
||||||
|
Dockerfile *DockerfileImagePluginOverrideParentOverride `json:"dockerfile,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type BaseCommandPluginOverrideParentOverride struct {
|
type BaseCommandPluginOverrideParentOverride struct {
|
||||||
|
|
||||||
// +optional
|
// +optional
|
||||||
|
|
@ -1125,6 +1278,17 @@ type BaseCommandPluginOverrideParentOverride struct {
|
||||||
// Only one of the following component type may be specified.
|
// Only one of the following component type may be specified.
|
||||||
type K8sLikeComponentLocationTypePluginOverrideParentOverride string
|
type K8sLikeComponentLocationTypePluginOverrideParentOverride string
|
||||||
|
|
||||||
|
// ImageType describes the type of image.
|
||||||
|
// Only one of the following image type may be specified.
|
||||||
|
type ImageTypePluginOverrideParentOverride string
|
||||||
|
|
||||||
|
// Dockerfile Image type to specify the outerloop build using a Dockerfile
|
||||||
|
type DockerfileImagePluginOverrideParentOverride struct {
|
||||||
|
BaseImagePluginOverrideParentOverride `json:",inline"`
|
||||||
|
DockerfileSrcPluginOverrideParentOverride `json:",inline"`
|
||||||
|
DockerfilePluginOverrideParentOverride `json:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
type CommandGroupPluginOverrideParentOverride struct {
|
type CommandGroupPluginOverrideParentOverride struct {
|
||||||
|
|
||||||
// +optional
|
// +optional
|
||||||
|
|
@ -1133,11 +1297,118 @@ type CommandGroupPluginOverrideParentOverride struct {
|
||||||
|
|
||||||
// +optional
|
// +optional
|
||||||
// Identifies the default command for a given group kind
|
// Identifies the default command for a given group kind
|
||||||
IsDefault bool `json:"isDefault,omitempty"`
|
IsDefault *bool `json:"isDefault,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseImagePluginOverrideParentOverride struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// +union
|
||||||
|
type DockerfileSrcPluginOverrideParentOverride struct {
|
||||||
|
|
||||||
|
// +kubebuilder:validation:Enum=Uri;DevfileRegistry;Git
|
||||||
|
// Type of Dockerfile src
|
||||||
|
// +
|
||||||
|
// +unionDiscriminator
|
||||||
|
// +optional
|
||||||
|
SrcType DockerfileSrcTypePluginOverrideParentOverride `json:"srcType,omitempty"`
|
||||||
|
|
||||||
|
// URI Reference of a Dockerfile.
|
||||||
|
// It can be a full URL or a relative URI from the current devfile as the base URI.
|
||||||
|
// +optional
|
||||||
|
Uri string `json:"uri,omitempty"`
|
||||||
|
|
||||||
|
// Dockerfile's Devfile Registry source
|
||||||
|
// +optional
|
||||||
|
DevfileRegistry *DockerfileDevfileRegistrySourcePluginOverrideParentOverride `json:"devfileRegistry,omitempty"`
|
||||||
|
|
||||||
|
// Dockerfile's Git source
|
||||||
|
// +optional
|
||||||
|
Git *DockerfileGitProjectSourcePluginOverrideParentOverride `json:"git,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DockerfilePluginOverrideParentOverride struct {
|
||||||
|
|
||||||
|
// Path of source directory to establish build context. Defaults to ${PROJECT_ROOT} in the container
|
||||||
|
// +optional
|
||||||
|
BuildContext string `json:"buildContext,omitempty"`
|
||||||
|
|
||||||
|
// The arguments to supply to the dockerfile build.
|
||||||
|
// +optional
|
||||||
|
Args []string `json:"args,omitempty" patchStrategy:"replace"`
|
||||||
|
|
||||||
|
// Specify if a privileged builder pod is required.
|
||||||
|
//
|
||||||
|
// Default value is `false`
|
||||||
|
// +optional
|
||||||
|
RootRequired *bool `json:"rootRequired,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommandGroupKind describes the kind of command group.
|
// CommandGroupKind describes the kind of command group.
|
||||||
// +kubebuilder:validation:Enum=build;run;test;debug
|
// +kubebuilder:validation:Enum=build;run;test;debug;deploy
|
||||||
type CommandGroupKindPluginOverrideParentOverride string
|
type CommandGroupKindPluginOverrideParentOverride string
|
||||||
|
|
||||||
|
// DockerfileSrcType describes the type of
|
||||||
|
// the src for the Dockerfile outerloop build.
|
||||||
|
// Only one of the following location type may be specified.
|
||||||
|
type DockerfileSrcTypePluginOverrideParentOverride string
|
||||||
|
|
||||||
|
type DockerfileDevfileRegistrySourcePluginOverrideParentOverride struct {
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
// Id in a devfile registry that contains a Dockerfile. The src in the OCI registry
|
||||||
|
// required for the Dockerfile build will be downloaded for building the image.
|
||||||
|
Id string `json:"id,omitempty"`
|
||||||
|
|
||||||
|
// Devfile Registry URL to pull the Dockerfile from when using the Devfile Registry as Dockerfile src.
|
||||||
|
// To ensure the Dockerfile gets resolved consistently in different environments,
|
||||||
|
// it is recommended to always specify the `devfileRegistryUrl` when `Id` is used.
|
||||||
|
// +optional
|
||||||
|
RegistryUrl string `json:"registryUrl,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DockerfileGitProjectSourcePluginOverrideParentOverride struct {
|
||||||
|
|
||||||
|
// Git src for the Dockerfile build. The src required for the Dockerfile build will need to be
|
||||||
|
// cloned for building the image.
|
||||||
|
GitProjectSourcePluginOverrideParentOverride `json:",inline"`
|
||||||
|
|
||||||
|
// Location of the Dockerfile in the Git repository when using git as Dockerfile src.
|
||||||
|
// Defaults to Dockerfile.
|
||||||
|
// +optional
|
||||||
|
FileLocation string `json:"fileLocation,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GitProjectSourcePluginOverrideParentOverride struct {
|
||||||
|
GitLikeProjectSourcePluginOverrideParentOverride `json:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GitLikeProjectSourcePluginOverrideParentOverride struct {
|
||||||
|
CommonProjectSourcePluginOverrideParentOverride `json:",inline"`
|
||||||
|
|
||||||
|
// Defines from what the project should be checked out. Required if there are more than one remote configured
|
||||||
|
// +optional
|
||||||
|
CheckoutFrom *CheckoutFromPluginOverrideParentOverride `json:"checkoutFrom,omitempty"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
// The remotes map which should be initialized in the git project.
|
||||||
|
// Projects must have at least one remote configured while StarterProjects & Image Component's Git source can only have at most one remote configured.
|
||||||
|
Remotes map[string]string `json:"remotes,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommonProjectSourcePluginOverrideParentOverride struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type CheckoutFromPluginOverrideParentOverride struct {
|
||||||
|
|
||||||
|
// The revision to checkout from. Should be branch name, tag or commit id.
|
||||||
|
// Default branch is used if missing or specified revision is not found.
|
||||||
|
// +optional
|
||||||
|
Revision string `json:"revision,omitempty"`
|
||||||
|
|
||||||
|
// The remote name should be used as init. Required if there are more than one remote configured
|
||||||
|
// +optional
|
||||||
|
Remote string `json:"remote,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
func (overrides ParentOverrides) isOverride() {}
|
func (overrides ParentOverrides) isOverride() {}
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ type CommandPluginOverride struct {
|
||||||
// +union
|
// +union
|
||||||
type ComponentUnionPluginOverride struct {
|
type ComponentUnionPluginOverride struct {
|
||||||
|
|
||||||
// +kubebuilder:validation:Enum=Container;Kubernetes;Openshift;Volume
|
// +kubebuilder:validation:Enum=Container;Kubernetes;Openshift;Volume;Image
|
||||||
// Type of component
|
// Type of component
|
||||||
//
|
//
|
||||||
// +unionDiscriminator
|
// +unionDiscriminator
|
||||||
|
|
@ -94,6 +94,10 @@ type ComponentUnionPluginOverride struct {
|
||||||
// shared by several other components
|
// shared by several other components
|
||||||
// +optional
|
// +optional
|
||||||
Volume *VolumeComponentPluginOverride `json:"volume,omitempty"`
|
Volume *VolumeComponentPluginOverride `json:"volume,omitempty"`
|
||||||
|
|
||||||
|
// Allows specifying the definition of an image for outer loop builds
|
||||||
|
// +optional
|
||||||
|
Image *ImageComponentPluginOverride `json:"image,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +union
|
// +union
|
||||||
|
|
@ -156,6 +160,12 @@ type VolumeComponentPluginOverride struct {
|
||||||
VolumePluginOverride `json:",inline"`
|
VolumePluginOverride `json:",inline"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Component that allows the developer to build a runtime image for outerloop
|
||||||
|
type ImageComponentPluginOverride struct {
|
||||||
|
BaseComponentPluginOverride `json:",inline"`
|
||||||
|
ImagePluginOverride `json:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
// CommandType describes the type of command.
|
// CommandType describes the type of command.
|
||||||
// Only one of the following command type may be specified.
|
// Only one of the following command type may be specified.
|
||||||
type CommandTypePluginOverride string
|
type CommandTypePluginOverride string
|
||||||
|
|
@ -200,7 +210,7 @@ type ExecCommandPluginOverride struct {
|
||||||
// If set to `true` the command won't be restarted and it is expected to handle file changes on its own.
|
// If set to `true` the command won't be restarted and it is expected to handle file changes on its own.
|
||||||
//
|
//
|
||||||
// Default value is `false`
|
// Default value is `false`
|
||||||
HotReloadCapable bool `json:"hotReloadCapable,omitempty"`
|
HotReloadCapable *bool `json:"hotReloadCapable,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApplyCommandPluginOverride struct {
|
type ApplyCommandPluginOverride struct {
|
||||||
|
|
@ -220,7 +230,7 @@ type CompositeCommandPluginOverride struct {
|
||||||
|
|
||||||
// Indicates if the sub-commands should be executed concurrently
|
// Indicates if the sub-commands should be executed concurrently
|
||||||
// +optional
|
// +optional
|
||||||
Parallel bool `json:"parallel,omitempty"`
|
Parallel *bool `json:"parallel,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DevWorkspace component: Anything that will bring additional features / tooling / behaviour / context
|
// DevWorkspace component: Anything that will bring additional features / tooling / behaviour / context
|
||||||
|
|
@ -290,7 +300,7 @@ type ContainerPluginOverride struct {
|
||||||
//
|
//
|
||||||
// Default value is `false`
|
// Default value is `false`
|
||||||
// +optional
|
// +optional
|
||||||
DedicatedPod bool `json:"dedicatedPod,omitempty"`
|
DedicatedPod *bool `json:"dedicatedPod,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type EndpointPluginOverride struct {
|
type EndpointPluginOverride struct {
|
||||||
|
|
@ -341,7 +351,7 @@ type EndpointPluginOverride struct {
|
||||||
// Describes whether the endpoint should be secured and protected by some
|
// Describes whether the endpoint should be secured and protected by some
|
||||||
// authentication process. This requires a protocol of `https` or `wss`.
|
// authentication process. This requires a protocol of `https` or `wss`.
|
||||||
// +optional
|
// +optional
|
||||||
Secure bool `json:"secure,omitempty"`
|
Secure *bool `json:"secure,omitempty"`
|
||||||
|
|
||||||
// Path of the endpoint URL
|
// Path of the endpoint URL
|
||||||
// +optional
|
// +optional
|
||||||
|
|
@ -377,7 +387,15 @@ type VolumePluginOverride struct {
|
||||||
// +optional
|
// +optional
|
||||||
// Ephemeral volumes are not stored persistently across restarts. Defaults
|
// Ephemeral volumes are not stored persistently across restarts. Defaults
|
||||||
// to false
|
// to false
|
||||||
Ephemeral bool `json:"ephemeral,omitempty"`
|
Ephemeral *bool `json:"ephemeral,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImagePluginOverride struct {
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
// Name of the image for the resulting outerloop build
|
||||||
|
ImageName string `json:"imageName,omitempty"`
|
||||||
|
ImageUnionPluginOverride `json:",inline"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LabeledCommandPluginOverride struct {
|
type LabeledCommandPluginOverride struct {
|
||||||
|
|
@ -440,6 +458,21 @@ type K8sLikeComponentLocationPluginOverride struct {
|
||||||
Inlined string `json:"inlined,omitempty"`
|
Inlined string `json:"inlined,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// +union
|
||||||
|
type ImageUnionPluginOverride struct {
|
||||||
|
|
||||||
|
// +kubebuilder:validation:Enum=Dockerfile
|
||||||
|
// Type of image
|
||||||
|
//
|
||||||
|
// +unionDiscriminator
|
||||||
|
// +optional
|
||||||
|
ImageType ImageTypePluginOverride `json:"imageType,omitempty"`
|
||||||
|
|
||||||
|
// Allows specifying dockerfile type build
|
||||||
|
// +optional
|
||||||
|
Dockerfile *DockerfileImagePluginOverride `json:"dockerfile,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type BaseCommandPluginOverride struct {
|
type BaseCommandPluginOverride struct {
|
||||||
|
|
||||||
// +optional
|
// +optional
|
||||||
|
|
@ -452,6 +485,17 @@ type BaseCommandPluginOverride struct {
|
||||||
// Only one of the following component type may be specified.
|
// Only one of the following component type may be specified.
|
||||||
type K8sLikeComponentLocationTypePluginOverride string
|
type K8sLikeComponentLocationTypePluginOverride string
|
||||||
|
|
||||||
|
// ImageType describes the type of image.
|
||||||
|
// Only one of the following image type may be specified.
|
||||||
|
type ImageTypePluginOverride string
|
||||||
|
|
||||||
|
// Dockerfile Image type to specify the outerloop build using a Dockerfile
|
||||||
|
type DockerfileImagePluginOverride struct {
|
||||||
|
BaseImagePluginOverride `json:",inline"`
|
||||||
|
DockerfileSrcPluginOverride `json:",inline"`
|
||||||
|
DockerfilePluginOverride `json:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
type CommandGroupPluginOverride struct {
|
type CommandGroupPluginOverride struct {
|
||||||
|
|
||||||
// +optional
|
// +optional
|
||||||
|
|
@ -460,11 +504,118 @@ type CommandGroupPluginOverride struct {
|
||||||
|
|
||||||
// +optional
|
// +optional
|
||||||
// Identifies the default command for a given group kind
|
// Identifies the default command for a given group kind
|
||||||
IsDefault bool `json:"isDefault,omitempty"`
|
IsDefault *bool `json:"isDefault,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseImagePluginOverride struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// +union
|
||||||
|
type DockerfileSrcPluginOverride struct {
|
||||||
|
|
||||||
|
// +kubebuilder:validation:Enum=Uri;DevfileRegistry;Git
|
||||||
|
// Type of Dockerfile src
|
||||||
|
// +
|
||||||
|
// +unionDiscriminator
|
||||||
|
// +optional
|
||||||
|
SrcType DockerfileSrcTypePluginOverride `json:"srcType,omitempty"`
|
||||||
|
|
||||||
|
// URI Reference of a Dockerfile.
|
||||||
|
// It can be a full URL or a relative URI from the current devfile as the base URI.
|
||||||
|
// +optional
|
||||||
|
Uri string `json:"uri,omitempty"`
|
||||||
|
|
||||||
|
// Dockerfile's Devfile Registry source
|
||||||
|
// +optional
|
||||||
|
DevfileRegistry *DockerfileDevfileRegistrySourcePluginOverride `json:"devfileRegistry,omitempty"`
|
||||||
|
|
||||||
|
// Dockerfile's Git source
|
||||||
|
// +optional
|
||||||
|
Git *DockerfileGitProjectSourcePluginOverride `json:"git,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DockerfilePluginOverride struct {
|
||||||
|
|
||||||
|
// Path of source directory to establish build context. Defaults to ${PROJECT_ROOT} in the container
|
||||||
|
// +optional
|
||||||
|
BuildContext string `json:"buildContext,omitempty"`
|
||||||
|
|
||||||
|
// The arguments to supply to the dockerfile build.
|
||||||
|
// +optional
|
||||||
|
Args []string `json:"args,omitempty" patchStrategy:"replace"`
|
||||||
|
|
||||||
|
// Specify if a privileged builder pod is required.
|
||||||
|
//
|
||||||
|
// Default value is `false`
|
||||||
|
// +optional
|
||||||
|
RootRequired *bool `json:"rootRequired,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommandGroupKind describes the kind of command group.
|
// CommandGroupKind describes the kind of command group.
|
||||||
// +kubebuilder:validation:Enum=build;run;test;debug
|
// +kubebuilder:validation:Enum=build;run;test;debug;deploy
|
||||||
type CommandGroupKindPluginOverride string
|
type CommandGroupKindPluginOverride string
|
||||||
|
|
||||||
|
// DockerfileSrcType describes the type of
|
||||||
|
// the src for the Dockerfile outerloop build.
|
||||||
|
// Only one of the following location type may be specified.
|
||||||
|
type DockerfileSrcTypePluginOverride string
|
||||||
|
|
||||||
|
type DockerfileDevfileRegistrySourcePluginOverride struct {
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
// Id in a devfile registry that contains a Dockerfile. The src in the OCI registry
|
||||||
|
// required for the Dockerfile build will be downloaded for building the image.
|
||||||
|
Id string `json:"id,omitempty"`
|
||||||
|
|
||||||
|
// Devfile Registry URL to pull the Dockerfile from when using the Devfile Registry as Dockerfile src.
|
||||||
|
// To ensure the Dockerfile gets resolved consistently in different environments,
|
||||||
|
// it is recommended to always specify the `devfileRegistryUrl` when `Id` is used.
|
||||||
|
// +optional
|
||||||
|
RegistryUrl string `json:"registryUrl,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DockerfileGitProjectSourcePluginOverride struct {
|
||||||
|
|
||||||
|
// Git src for the Dockerfile build. The src required for the Dockerfile build will need to be
|
||||||
|
// cloned for building the image.
|
||||||
|
GitProjectSourcePluginOverride `json:",inline"`
|
||||||
|
|
||||||
|
// Location of the Dockerfile in the Git repository when using git as Dockerfile src.
|
||||||
|
// Defaults to Dockerfile.
|
||||||
|
// +optional
|
||||||
|
FileLocation string `json:"fileLocation,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GitProjectSourcePluginOverride struct {
|
||||||
|
GitLikeProjectSourcePluginOverride `json:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GitLikeProjectSourcePluginOverride struct {
|
||||||
|
CommonProjectSourcePluginOverride `json:",inline"`
|
||||||
|
|
||||||
|
// Defines from what the project should be checked out. Required if there are more than one remote configured
|
||||||
|
// +optional
|
||||||
|
CheckoutFrom *CheckoutFromPluginOverride `json:"checkoutFrom,omitempty"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
// The remotes map which should be initialized in the git project.
|
||||||
|
// Projects must have at least one remote configured while StarterProjects & Image Component's Git source can only have at most one remote configured.
|
||||||
|
Remotes map[string]string `json:"remotes,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommonProjectSourcePluginOverride struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type CheckoutFromPluginOverride struct {
|
||||||
|
|
||||||
|
// The revision to checkout from. Should be branch name, tag or commit id.
|
||||||
|
// Default branch is used if missing or specified revision is not found.
|
||||||
|
// +optional
|
||||||
|
Revision string `json:"revision,omitempty"`
|
||||||
|
|
||||||
|
// The remote name should be used as init. Required if there are more than one remote configured
|
||||||
|
// +optional
|
||||||
|
Remote string `json:"remote,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
func (overrides PluginOverrides) isOverride() {}
|
func (overrides PluginOverrides) isOverride() {}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,48 @@ type CommandUnionVisitor struct {
|
||||||
Custom func(*CustomCommand) error
|
Custom func(*CustomCommand) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var imageUnion reflect.Type = reflect.TypeOf(ImageUnionVisitor{})
|
||||||
|
|
||||||
|
func (union ImageUnion) Visit(visitor ImageUnionVisitor) error {
|
||||||
|
return visitUnion(union, visitor)
|
||||||
|
}
|
||||||
|
func (union *ImageUnion) discriminator() *string {
|
||||||
|
return (*string)(&union.ImageType)
|
||||||
|
}
|
||||||
|
func (union *ImageUnion) Normalize() error {
|
||||||
|
return normalizeUnion(union, imageUnion)
|
||||||
|
}
|
||||||
|
func (union *ImageUnion) Simplify() {
|
||||||
|
simplifyUnion(union, imageUnion)
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type ImageUnionVisitor struct {
|
||||||
|
Dockerfile func(*DockerfileImage) error
|
||||||
|
}
|
||||||
|
|
||||||
|
var dockerfileSrc reflect.Type = reflect.TypeOf(DockerfileSrcVisitor{})
|
||||||
|
|
||||||
|
func (union DockerfileSrc) Visit(visitor DockerfileSrcVisitor) error {
|
||||||
|
return visitUnion(union, visitor)
|
||||||
|
}
|
||||||
|
func (union *DockerfileSrc) discriminator() *string {
|
||||||
|
return (*string)(&union.SrcType)
|
||||||
|
}
|
||||||
|
func (union *DockerfileSrc) Normalize() error {
|
||||||
|
return normalizeUnion(union, dockerfileSrc)
|
||||||
|
}
|
||||||
|
func (union *DockerfileSrc) Simplify() {
|
||||||
|
simplifyUnion(union, dockerfileSrc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type DockerfileSrcVisitor struct {
|
||||||
|
Uri func(string) error
|
||||||
|
DevfileRegistry func(*DockerfileDevfileRegistrySource) error
|
||||||
|
Git func(*DockerfileGitProjectSource) error
|
||||||
|
}
|
||||||
|
|
||||||
var k8sLikeComponentLocation reflect.Type = reflect.TypeOf(K8sLikeComponentLocationVisitor{})
|
var k8sLikeComponentLocation reflect.Type = reflect.TypeOf(K8sLikeComponentLocationVisitor{})
|
||||||
|
|
||||||
func (union K8sLikeComponentLocation) Visit(visitor K8sLikeComponentLocationVisitor) error {
|
func (union K8sLikeComponentLocation) Visit(visitor K8sLikeComponentLocationVisitor) error {
|
||||||
|
|
@ -69,6 +111,7 @@ type ComponentUnionVisitor struct {
|
||||||
Kubernetes func(*KubernetesComponent) error
|
Kubernetes func(*KubernetesComponent) error
|
||||||
Openshift func(*OpenshiftComponent) error
|
Openshift func(*OpenshiftComponent) error
|
||||||
Volume func(*VolumeComponent) error
|
Volume func(*VolumeComponent) error
|
||||||
|
Image func(*ImageComponent) error
|
||||||
Plugin func(*PluginComponent) error
|
Plugin func(*PluginComponent) error
|
||||||
Custom func(*CustomComponent) error
|
Custom func(*CustomComponent) error
|
||||||
}
|
}
|
||||||
|
|
@ -138,6 +181,7 @@ type ComponentUnionParentOverrideVisitor struct {
|
||||||
Kubernetes func(*KubernetesComponentParentOverride) error
|
Kubernetes func(*KubernetesComponentParentOverride) error
|
||||||
Openshift func(*OpenshiftComponentParentOverride) error
|
Openshift func(*OpenshiftComponentParentOverride) error
|
||||||
Volume func(*VolumeComponentParentOverride) error
|
Volume func(*VolumeComponentParentOverride) error
|
||||||
|
Image func(*ImageComponentParentOverride) error
|
||||||
Plugin func(*PluginComponentParentOverride) error
|
Plugin func(*PluginComponentParentOverride) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,6 +249,26 @@ type K8sLikeComponentLocationParentOverrideVisitor struct {
|
||||||
Inlined func(string) error
|
Inlined func(string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var imageUnionParentOverride reflect.Type = reflect.TypeOf(ImageUnionParentOverrideVisitor{})
|
||||||
|
|
||||||
|
func (union ImageUnionParentOverride) Visit(visitor ImageUnionParentOverrideVisitor) error {
|
||||||
|
return visitUnion(union, visitor)
|
||||||
|
}
|
||||||
|
func (union *ImageUnionParentOverride) discriminator() *string {
|
||||||
|
return (*string)(&union.ImageType)
|
||||||
|
}
|
||||||
|
func (union *ImageUnionParentOverride) Normalize() error {
|
||||||
|
return normalizeUnion(union, imageUnionParentOverride)
|
||||||
|
}
|
||||||
|
func (union *ImageUnionParentOverride) Simplify() {
|
||||||
|
simplifyUnion(union, imageUnionParentOverride)
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type ImageUnionParentOverrideVisitor struct {
|
||||||
|
Dockerfile func(*DockerfileImageParentOverride) error
|
||||||
|
}
|
||||||
|
|
||||||
var importReferenceUnionParentOverride reflect.Type = reflect.TypeOf(ImportReferenceUnionParentOverrideVisitor{})
|
var importReferenceUnionParentOverride reflect.Type = reflect.TypeOf(ImportReferenceUnionParentOverrideVisitor{})
|
||||||
|
|
||||||
func (union ImportReferenceUnionParentOverride) Visit(visitor ImportReferenceUnionParentOverrideVisitor) error {
|
func (union ImportReferenceUnionParentOverride) Visit(visitor ImportReferenceUnionParentOverrideVisitor) error {
|
||||||
|
|
@ -248,6 +312,7 @@ type ComponentUnionPluginOverrideParentOverrideVisitor struct {
|
||||||
Kubernetes func(*KubernetesComponentPluginOverrideParentOverride) error
|
Kubernetes func(*KubernetesComponentPluginOverrideParentOverride) error
|
||||||
Openshift func(*OpenshiftComponentPluginOverrideParentOverride) error
|
Openshift func(*OpenshiftComponentPluginOverrideParentOverride) error
|
||||||
Volume func(*VolumeComponentPluginOverrideParentOverride) error
|
Volume func(*VolumeComponentPluginOverrideParentOverride) error
|
||||||
|
Image func(*ImageComponentPluginOverrideParentOverride) error
|
||||||
}
|
}
|
||||||
|
|
||||||
var commandUnionPluginOverrideParentOverride reflect.Type = reflect.TypeOf(CommandUnionPluginOverrideParentOverrideVisitor{})
|
var commandUnionPluginOverrideParentOverride reflect.Type = reflect.TypeOf(CommandUnionPluginOverrideParentOverrideVisitor{})
|
||||||
|
|
@ -272,6 +337,28 @@ type CommandUnionPluginOverrideParentOverrideVisitor struct {
|
||||||
Composite func(*CompositeCommandPluginOverrideParentOverride) error
|
Composite func(*CompositeCommandPluginOverrideParentOverride) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dockerfileSrcParentOverride reflect.Type = reflect.TypeOf(DockerfileSrcParentOverrideVisitor{})
|
||||||
|
|
||||||
|
func (union DockerfileSrcParentOverride) Visit(visitor DockerfileSrcParentOverrideVisitor) error {
|
||||||
|
return visitUnion(union, visitor)
|
||||||
|
}
|
||||||
|
func (union *DockerfileSrcParentOverride) discriminator() *string {
|
||||||
|
return (*string)(&union.SrcType)
|
||||||
|
}
|
||||||
|
func (union *DockerfileSrcParentOverride) Normalize() error {
|
||||||
|
return normalizeUnion(union, dockerfileSrcParentOverride)
|
||||||
|
}
|
||||||
|
func (union *DockerfileSrcParentOverride) Simplify() {
|
||||||
|
simplifyUnion(union, dockerfileSrcParentOverride)
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type DockerfileSrcParentOverrideVisitor struct {
|
||||||
|
Uri func(string) error
|
||||||
|
DevfileRegistry func(*DockerfileDevfileRegistrySourceParentOverride) error
|
||||||
|
Git func(*DockerfileGitProjectSourceParentOverride) error
|
||||||
|
}
|
||||||
|
|
||||||
var k8sLikeComponentLocationPluginOverrideParentOverride reflect.Type = reflect.TypeOf(K8sLikeComponentLocationPluginOverrideParentOverrideVisitor{})
|
var k8sLikeComponentLocationPluginOverrideParentOverride reflect.Type = reflect.TypeOf(K8sLikeComponentLocationPluginOverrideParentOverrideVisitor{})
|
||||||
|
|
||||||
func (union K8sLikeComponentLocationPluginOverrideParentOverride) Visit(visitor K8sLikeComponentLocationPluginOverrideParentOverrideVisitor) error {
|
func (union K8sLikeComponentLocationPluginOverrideParentOverride) Visit(visitor K8sLikeComponentLocationPluginOverrideParentOverrideVisitor) error {
|
||||||
|
|
@ -293,6 +380,48 @@ type K8sLikeComponentLocationPluginOverrideParentOverrideVisitor struct {
|
||||||
Inlined func(string) error
|
Inlined func(string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var imageUnionPluginOverrideParentOverride reflect.Type = reflect.TypeOf(ImageUnionPluginOverrideParentOverrideVisitor{})
|
||||||
|
|
||||||
|
func (union ImageUnionPluginOverrideParentOverride) Visit(visitor ImageUnionPluginOverrideParentOverrideVisitor) error {
|
||||||
|
return visitUnion(union, visitor)
|
||||||
|
}
|
||||||
|
func (union *ImageUnionPluginOverrideParentOverride) discriminator() *string {
|
||||||
|
return (*string)(&union.ImageType)
|
||||||
|
}
|
||||||
|
func (union *ImageUnionPluginOverrideParentOverride) Normalize() error {
|
||||||
|
return normalizeUnion(union, imageUnionPluginOverrideParentOverride)
|
||||||
|
}
|
||||||
|
func (union *ImageUnionPluginOverrideParentOverride) Simplify() {
|
||||||
|
simplifyUnion(union, imageUnionPluginOverrideParentOverride)
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type ImageUnionPluginOverrideParentOverrideVisitor struct {
|
||||||
|
Dockerfile func(*DockerfileImagePluginOverrideParentOverride) error
|
||||||
|
}
|
||||||
|
|
||||||
|
var dockerfileSrcPluginOverrideParentOverride reflect.Type = reflect.TypeOf(DockerfileSrcPluginOverrideParentOverrideVisitor{})
|
||||||
|
|
||||||
|
func (union DockerfileSrcPluginOverrideParentOverride) Visit(visitor DockerfileSrcPluginOverrideParentOverrideVisitor) error {
|
||||||
|
return visitUnion(union, visitor)
|
||||||
|
}
|
||||||
|
func (union *DockerfileSrcPluginOverrideParentOverride) discriminator() *string {
|
||||||
|
return (*string)(&union.SrcType)
|
||||||
|
}
|
||||||
|
func (union *DockerfileSrcPluginOverrideParentOverride) Normalize() error {
|
||||||
|
return normalizeUnion(union, dockerfileSrcPluginOverrideParentOverride)
|
||||||
|
}
|
||||||
|
func (union *DockerfileSrcPluginOverrideParentOverride) Simplify() {
|
||||||
|
simplifyUnion(union, dockerfileSrcPluginOverrideParentOverride)
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type DockerfileSrcPluginOverrideParentOverrideVisitor struct {
|
||||||
|
Uri func(string) error
|
||||||
|
DevfileRegistry func(*DockerfileDevfileRegistrySourcePluginOverrideParentOverride) error
|
||||||
|
Git func(*DockerfileGitProjectSourcePluginOverrideParentOverride) error
|
||||||
|
}
|
||||||
|
|
||||||
var componentUnionPluginOverride reflect.Type = reflect.TypeOf(ComponentUnionPluginOverrideVisitor{})
|
var componentUnionPluginOverride reflect.Type = reflect.TypeOf(ComponentUnionPluginOverrideVisitor{})
|
||||||
|
|
||||||
func (union ComponentUnionPluginOverride) Visit(visitor ComponentUnionPluginOverrideVisitor) error {
|
func (union ComponentUnionPluginOverride) Visit(visitor ComponentUnionPluginOverrideVisitor) error {
|
||||||
|
|
@ -314,6 +443,7 @@ type ComponentUnionPluginOverrideVisitor struct {
|
||||||
Kubernetes func(*KubernetesComponentPluginOverride) error
|
Kubernetes func(*KubernetesComponentPluginOverride) error
|
||||||
Openshift func(*OpenshiftComponentPluginOverride) error
|
Openshift func(*OpenshiftComponentPluginOverride) error
|
||||||
Volume func(*VolumeComponentPluginOverride) error
|
Volume func(*VolumeComponentPluginOverride) error
|
||||||
|
Image func(*ImageComponentPluginOverride) error
|
||||||
}
|
}
|
||||||
|
|
||||||
var commandUnionPluginOverride reflect.Type = reflect.TypeOf(CommandUnionPluginOverrideVisitor{})
|
var commandUnionPluginOverride reflect.Type = reflect.TypeOf(CommandUnionPluginOverrideVisitor{})
|
||||||
|
|
@ -358,3 +488,45 @@ type K8sLikeComponentLocationPluginOverrideVisitor struct {
|
||||||
Uri func(string) error
|
Uri func(string) error
|
||||||
Inlined func(string) error
|
Inlined func(string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var imageUnionPluginOverride reflect.Type = reflect.TypeOf(ImageUnionPluginOverrideVisitor{})
|
||||||
|
|
||||||
|
func (union ImageUnionPluginOverride) Visit(visitor ImageUnionPluginOverrideVisitor) error {
|
||||||
|
return visitUnion(union, visitor)
|
||||||
|
}
|
||||||
|
func (union *ImageUnionPluginOverride) discriminator() *string {
|
||||||
|
return (*string)(&union.ImageType)
|
||||||
|
}
|
||||||
|
func (union *ImageUnionPluginOverride) Normalize() error {
|
||||||
|
return normalizeUnion(union, imageUnionPluginOverride)
|
||||||
|
}
|
||||||
|
func (union *ImageUnionPluginOverride) Simplify() {
|
||||||
|
simplifyUnion(union, imageUnionPluginOverride)
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type ImageUnionPluginOverrideVisitor struct {
|
||||||
|
Dockerfile func(*DockerfileImagePluginOverride) error
|
||||||
|
}
|
||||||
|
|
||||||
|
var dockerfileSrcPluginOverride reflect.Type = reflect.TypeOf(DockerfileSrcPluginOverrideVisitor{})
|
||||||
|
|
||||||
|
func (union DockerfileSrcPluginOverride) Visit(visitor DockerfileSrcPluginOverrideVisitor) error {
|
||||||
|
return visitUnion(union, visitor)
|
||||||
|
}
|
||||||
|
func (union *DockerfileSrcPluginOverride) discriminator() *string {
|
||||||
|
return (*string)(&union.SrcType)
|
||||||
|
}
|
||||||
|
func (union *DockerfileSrcPluginOverride) Normalize() error {
|
||||||
|
return normalizeUnion(union, dockerfileSrcPluginOverride)
|
||||||
|
}
|
||||||
|
func (union *DockerfileSrcPluginOverride) Simplify() {
|
||||||
|
simplifyUnion(union, dockerfileSrcPluginOverride)
|
||||||
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
type DockerfileSrcPluginOverrideVisitor struct {
|
||||||
|
Uri func(string) error
|
||||||
|
DevfileRegistry func(*DockerfileDevfileRegistrySourcePluginOverride) error
|
||||||
|
Git func(*DockerfileGitProjectSourcePluginOverride) error
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,4 +81,12 @@ type DevfileMetadata struct {
|
||||||
// Optional devfile website
|
// Optional devfile website
|
||||||
// +optional
|
// +optional
|
||||||
Website string `json:"website,omitempty"`
|
Website string `json:"website,omitempty"`
|
||||||
|
|
||||||
|
// Optional devfile provider information
|
||||||
|
// +optional
|
||||||
|
Provider string `json:"provider,omitempty"`
|
||||||
|
|
||||||
|
// Optional link to a page that provides support information
|
||||||
|
// +optional
|
||||||
|
SupportUrl string `json:"supportUrl,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
vendor/github.com/devfile/devworkspace-operator/apis/controller/v1alpha1/common.go
generated
vendored
1
vendor/github.com/devfile/devworkspace-operator/apis/controller/v1alpha1/common.go
generated
vendored
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import v1 "k8s.io/api/core/v1"
|
import v1 "k8s.io/api/core/v1"
|
||||||
|
|
|
||||||
1
vendor/github.com/devfile/devworkspace-operator/apis/controller/v1alpha1/devfile.go
generated
vendored
1
vendor/github.com/devfile/devworkspace-operator/apis/controller/v1alpha1/devfile.go
generated
vendored
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
type EndpointAttribute string
|
type EndpointAttribute string
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package devworkspacerouting
|
package devworkspacerouting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package devworkspacerouting
|
package devworkspacerouting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,10 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package solvers
|
package solvers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
|
|
||||||
controllerv1alpha1 "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
controllerv1alpha1 "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
||||||
"github.com/devfile/devworkspace-operator/pkg/config"
|
"github.com/devfile/devworkspace-operator/pkg/config"
|
||||||
"github.com/devfile/devworkspace-operator/pkg/constants"
|
"github.com/devfile/devworkspace-operator/pkg/constants"
|
||||||
|
|
@ -60,7 +59,7 @@ func (s *BasicSolver) GetSpecObjects(routing *controllerv1alpha1.DevWorkspaceRou
|
||||||
|
|
||||||
routingSuffix := config.Routing.ClusterHostSuffix
|
routingSuffix := config.Routing.ClusterHostSuffix
|
||||||
if routingSuffix == "" {
|
if routingSuffix == "" {
|
||||||
return routingObjects, errors.New("basic routing requires .config.routing.clusterHostSuffix to be set in operator config")
|
return routingObjects, &RoutingInvalid{"basic routing requires .config.routing.clusterHostSuffix to be set in operator config"}
|
||||||
}
|
}
|
||||||
|
|
||||||
spec := routing.Spec
|
spec := routing.Spec
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package solvers
|
package solvers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package solvers
|
package solvers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package solvers
|
package solvers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package solvers
|
package solvers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -76,7 +77,7 @@ func resolveURLForEndpoint(
|
||||||
|
|
||||||
func getURLForEndpoint(endpoint dw.Endpoint, host, basePath string, secure bool) string {
|
func getURLForEndpoint(endpoint dw.Endpoint, host, basePath string, secure bool) string {
|
||||||
protocol := endpoint.Protocol
|
protocol := endpoint.Protocol
|
||||||
if secure && endpoint.Secure {
|
if secure && endpoint.Secure != nil && *endpoint.Secure {
|
||||||
protocol = dw.EndpointProtocol(getSecureProtocol(string(protocol)))
|
protocol = dw.EndpointProtocol(getSecureProtocol(string(protocol)))
|
||||||
}
|
}
|
||||||
var p string
|
var p string
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package solvers
|
package solvers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package devworkspacerouting
|
package devworkspacerouting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -19,22 +20,15 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/devfile/devworkspace-operator/pkg/constants"
|
"github.com/devfile/devworkspace-operator/pkg/constants"
|
||||||
|
"github.com/devfile/devworkspace-operator/pkg/provision/sync"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
|
||||||
networkingv1 "k8s.io/api/networking/v1"
|
networkingv1 "k8s.io/api/networking/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
|
||||||
controllerv1alpha1 "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
controllerv1alpha1 "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ingressDiffOpts = cmp.Options{
|
|
||||||
cmpopts.IgnoreFields(networkingv1.Ingress{}, "TypeMeta", "ObjectMeta", "Status"),
|
|
||||||
cmpopts.IgnoreFields(networkingv1.HTTPIngressPath{}, "PathType"),
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *DevWorkspaceRoutingReconciler) syncIngresses(routing *controllerv1alpha1.DevWorkspaceRouting, specIngresses []networkingv1.Ingress) (ok bool, clusterIngresses []networkingv1.Ingress, err error) {
|
func (r *DevWorkspaceRoutingReconciler) syncIngresses(routing *controllerv1alpha1.DevWorkspaceRouting, specIngresses []networkingv1.Ingress) (ok bool, clusterIngresses []networkingv1.Ingress, err error) {
|
||||||
ingressesInSync := true
|
ingressesInSync := true
|
||||||
|
|
||||||
|
|
@ -52,32 +46,31 @@ func (r *DevWorkspaceRoutingReconciler) syncIngresses(routing *controllerv1alpha
|
||||||
ingressesInSync = false
|
ingressesInSync = false
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, specIngress := range specIngresses {
|
clusterAPI := sync.ClusterAPI{
|
||||||
if contains, idx := listContainsIngressByName(specIngress, clusterIngresses); contains {
|
Client: r.Client,
|
||||||
clusterIngress := clusterIngresses[idx]
|
Scheme: r.Scheme,
|
||||||
if !cmp.Equal(specIngress, clusterIngress, ingressDiffOpts) {
|
Logger: r.Log.WithValues("Request.Namespace", routing.Namespace, "Request.Name", routing.Name),
|
||||||
r.Log.Info(fmt.Sprintf("Updating ingress: %s", clusterIngress.Name))
|
Ctx: context.TODO(),
|
||||||
if r.DebugLogging {
|
|
||||||
r.Log.Info(fmt.Sprintf("Diff: %s", cmp.Diff(specIngress, clusterIngress, ingressDiffOpts)))
|
|
||||||
}
|
|
||||||
// Update ingress's spec
|
|
||||||
clusterIngress.Spec = specIngress.Spec
|
|
||||||
err := r.Update(context.TODO(), &clusterIngress)
|
|
||||||
if err != nil && !errors.IsConflict(err) {
|
|
||||||
return false, nil, err
|
|
||||||
}
|
|
||||||
ingressesInSync = false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err := r.Create(context.TODO(), &specIngress)
|
|
||||||
if err != nil {
|
|
||||||
return false, nil, err
|
|
||||||
}
|
|
||||||
ingressesInSync = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ingressesInSync, clusterIngresses, nil
|
var updatedClusterIngresses []networkingv1.Ingress
|
||||||
|
for _, specIngress := range specIngresses {
|
||||||
|
clusterObj, err := sync.SyncObjectWithCluster(&specIngress, clusterAPI)
|
||||||
|
switch t := err.(type) {
|
||||||
|
case nil:
|
||||||
|
break
|
||||||
|
case *sync.NotInSyncError:
|
||||||
|
ingressesInSync = false
|
||||||
|
continue
|
||||||
|
case *sync.UnrecoverableSyncError:
|
||||||
|
return false, nil, t.Cause
|
||||||
|
default:
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
updatedClusterIngresses = append(updatedClusterIngresses, *clusterObj.(*networkingv1.Ingress))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ingressesInSync, updatedClusterIngresses, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DevWorkspaceRoutingReconciler) getClusterIngresses(routing *controllerv1alpha1.DevWorkspaceRouting) ([]networkingv1.Ingress, error) {
|
func (r *DevWorkspaceRoutingReconciler) getClusterIngresses(routing *controllerv1alpha1.DevWorkspaceRouting) ([]networkingv1.Ingress, error) {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package devworkspacerouting
|
package devworkspacerouting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -19,23 +20,14 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/devfile/devworkspace-operator/pkg/constants"
|
"github.com/devfile/devworkspace-operator/pkg/constants"
|
||||||
|
"github.com/devfile/devworkspace-operator/pkg/provision/sync"
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
|
||||||
routeV1 "github.com/openshift/api/route/v1"
|
routeV1 "github.com/openshift/api/route/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
|
||||||
controllerv1alpha1 "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
controllerv1alpha1 "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var routeDiffOpts = cmp.Options{
|
|
||||||
cmpopts.IgnoreFields(routeV1.Route{}, "TypeMeta", "ObjectMeta", "Status"),
|
|
||||||
cmpopts.IgnoreFields(routeV1.RouteSpec{}, "WildcardPolicy", "Host"),
|
|
||||||
cmpopts.IgnoreFields(routeV1.RouteTargetReference{}, "Weight"),
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *DevWorkspaceRoutingReconciler) syncRoutes(routing *controllerv1alpha1.DevWorkspaceRouting, specRoutes []routeV1.Route) (ok bool, clusterRoutes []routeV1.Route, err error) {
|
func (r *DevWorkspaceRoutingReconciler) syncRoutes(routing *controllerv1alpha1.DevWorkspaceRouting, specRoutes []routeV1.Route) (ok bool, clusterRoutes []routeV1.Route, err error) {
|
||||||
routesInSync := true
|
routesInSync := true
|
||||||
|
|
||||||
|
|
@ -53,33 +45,31 @@ func (r *DevWorkspaceRoutingReconciler) syncRoutes(routing *controllerv1alpha1.D
|
||||||
routesInSync = false
|
routesInSync = false
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, specRoute := range specRoutes {
|
clusterAPI := sync.ClusterAPI{
|
||||||
if contains, idx := listContainsRouteByName(specRoute, clusterRoutes); contains {
|
Client: r.Client,
|
||||||
clusterRoute := clusterRoutes[idx]
|
Scheme: r.Scheme,
|
||||||
if !cmp.Equal(specRoute, clusterRoute, routeDiffOpts) {
|
Logger: r.Log.WithValues("Request.Namespace", routing.Namespace, "Request.Name", routing.Name),
|
||||||
r.Log.Info(fmt.Sprintf("Updating route: %s", clusterRoute.Name))
|
Ctx: context.TODO(),
|
||||||
if r.DebugLogging {
|
|
||||||
r.Log.Info(fmt.Sprintf("Diff: %s", cmp.Diff(specRoute, clusterRoute, routeDiffOpts)))
|
|
||||||
}
|
|
||||||
// Update route's spec
|
|
||||||
clusterRoute.Spec = specRoute.Spec
|
|
||||||
err := r.Update(context.TODO(), &clusterRoute)
|
|
||||||
if err != nil && !errors.IsConflict(err) {
|
|
||||||
return false, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
routesInSync = false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err := r.Create(context.TODO(), &specRoute)
|
|
||||||
if err != nil {
|
|
||||||
return false, nil, err
|
|
||||||
}
|
|
||||||
routesInSync = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return routesInSync, clusterRoutes, nil
|
var updatedClusterRoutes []routeV1.Route
|
||||||
|
for _, specIngress := range specRoutes {
|
||||||
|
clusterObj, err := sync.SyncObjectWithCluster(&specIngress, clusterAPI)
|
||||||
|
switch t := err.(type) {
|
||||||
|
case nil:
|
||||||
|
break
|
||||||
|
case *sync.NotInSyncError:
|
||||||
|
routesInSync = false
|
||||||
|
continue
|
||||||
|
case *sync.UnrecoverableSyncError:
|
||||||
|
return false, nil, t.Cause
|
||||||
|
default:
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
updatedClusterRoutes = append(updatedClusterRoutes, *clusterObj.(*routeV1.Route))
|
||||||
|
}
|
||||||
|
|
||||||
|
return routesInSync, updatedClusterRoutes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DevWorkspaceRoutingReconciler) getClusterRoutes(routing *controllerv1alpha1.DevWorkspaceRouting) ([]routeV1.Route, error) {
|
func (r *DevWorkspaceRoutingReconciler) getClusterRoutes(routing *controllerv1alpha1.DevWorkspaceRouting) ([]routeV1.Route, error) {
|
||||||
|
|
|
||||||
|
|
@ -12,50 +12,22 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package devworkspacerouting
|
package devworkspacerouting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/devfile/devworkspace-operator/pkg/constants"
|
"github.com/devfile/devworkspace-operator/pkg/constants"
|
||||||
|
"github.com/devfile/devworkspace-operator/pkg/provision/sync"
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
|
||||||
controllerv1alpha1 "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
controllerv1alpha1 "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var serviceDiffOpts = cmp.Options{
|
|
||||||
cmpopts.IgnoreFields(corev1.Service{}, "TypeMeta", "ObjectMeta", "Status"),
|
|
||||||
cmp.Comparer(func(x, y corev1.ServiceSpec) bool {
|
|
||||||
xCopy := x.DeepCopy()
|
|
||||||
yCopy := y.DeepCopy()
|
|
||||||
if !cmp.Equal(xCopy.Selector, yCopy.Selector) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// Function that takes a slice of servicePorts and returns the appropriate comparison
|
|
||||||
// function to pass to sort.Slice() for that slice of servicePorts.
|
|
||||||
servicePortSorter := func(servicePorts []corev1.ServicePort) func(i, j int) bool {
|
|
||||||
return func(i, j int) bool {
|
|
||||||
return strings.Compare(servicePorts[i].Name, servicePorts[j].Name) > 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Slice(xCopy.Ports, servicePortSorter(xCopy.Ports))
|
|
||||||
sort.Slice(yCopy.Ports, servicePortSorter(yCopy.Ports))
|
|
||||||
if !cmp.Equal(xCopy.Ports, yCopy.Ports) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return xCopy.Type == yCopy.Type
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *DevWorkspaceRoutingReconciler) syncServices(routing *controllerv1alpha1.DevWorkspaceRouting, specServices []corev1.Service) (ok bool, clusterServices []corev1.Service, err error) {
|
func (r *DevWorkspaceRoutingReconciler) syncServices(routing *controllerv1alpha1.DevWorkspaceRouting, specServices []corev1.Service) (ok bool, clusterServices []corev1.Service, err error) {
|
||||||
servicesInSync := true
|
servicesInSync := true
|
||||||
|
|
||||||
|
|
@ -73,34 +45,31 @@ func (r *DevWorkspaceRoutingReconciler) syncServices(routing *controllerv1alpha1
|
||||||
servicesInSync = false
|
servicesInSync = false
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, specService := range specServices {
|
clusterAPI := sync.ClusterAPI{
|
||||||
if contains, idx := listContainsByName(specService, clusterServices); contains {
|
Client: r.Client,
|
||||||
clusterService := clusterServices[idx]
|
Scheme: r.Scheme,
|
||||||
if !cmp.Equal(specService, clusterService, serviceDiffOpts) {
|
Logger: r.Log.WithValues("Request.Namespace", routing.Namespace, "Request.Name", routing.Name),
|
||||||
r.Log.Info(fmt.Sprintf("Updating service: %s", clusterService.Name))
|
Ctx: context.TODO(),
|
||||||
if r.DebugLogging {
|
|
||||||
r.Log.Info(fmt.Sprintf("Diff: %s", cmp.Diff(specService, clusterService, serviceDiffOpts)))
|
|
||||||
}
|
|
||||||
// Cannot naively copy spec, as clusterIP is unmodifiable
|
|
||||||
clusterIP := clusterService.Spec.ClusterIP
|
|
||||||
clusterService.Spec = specService.Spec
|
|
||||||
clusterService.Spec.ClusterIP = clusterIP
|
|
||||||
err := r.Update(context.TODO(), &clusterService)
|
|
||||||
if err != nil && !errors.IsConflict(err) {
|
|
||||||
return false, nil, err
|
|
||||||
}
|
|
||||||
servicesInSync = false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err := r.Create(context.TODO(), &specService)
|
|
||||||
if err != nil {
|
|
||||||
return false, nil, err
|
|
||||||
}
|
|
||||||
servicesInSync = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return servicesInSync, clusterServices, nil
|
var updatedClusterServices []corev1.Service
|
||||||
|
for _, specIngress := range specServices {
|
||||||
|
clusterObj, err := sync.SyncObjectWithCluster(&specIngress, clusterAPI)
|
||||||
|
switch t := err.(type) {
|
||||||
|
case nil:
|
||||||
|
break
|
||||||
|
case *sync.NotInSyncError:
|
||||||
|
servicesInSync = false
|
||||||
|
continue
|
||||||
|
case *sync.UnrecoverableSyncError:
|
||||||
|
return false, nil, t.Cause
|
||||||
|
default:
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
updatedClusterServices = append(updatedClusterServices, *clusterObj.(*corev1.Service))
|
||||||
|
}
|
||||||
|
|
||||||
|
return servicesInSync, updatedClusterServices, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DevWorkspaceRoutingReconciler) getClusterServices(routing *controllerv1alpha1.DevWorkspaceRouting) ([]corev1.Service, error) {
|
func (r *DevWorkspaceRoutingReconciler) getClusterServices(routing *controllerv1alpha1.DevWorkspaceRouting) ([]corev1.Service, error) {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package maputils
|
package maputils
|
||||||
|
|
||||||
func Append(target map[string]string, key, value string) map[string]string {
|
func Append(target map[string]string, key, value string) map[string]string {
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,15 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/devfile/devworkspace-operator/pkg/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
var NonAlphaNumRegexp = regexp.MustCompile(`[^a-z0-9]+`)
|
var NonAlphaNumRegexp = regexp.MustCompile(`[^a-z0-9]+`)
|
||||||
|
|
@ -94,3 +97,11 @@ func AutoMountSecretVolumeName(volumeName string) string {
|
||||||
func AutoMountPVCVolumeName(pvcName string) string {
|
func AutoMountPVCVolumeName(pvcName string) string {
|
||||||
return fmt.Sprintf("automount-pvc-%s", pvcName)
|
return fmt.Sprintf("automount-pvc-%s", pvcName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WorkspaceRoleName() string {
|
||||||
|
return "workspace"
|
||||||
|
}
|
||||||
|
|
||||||
|
func WorkspaceRolebindingName() string {
|
||||||
|
return constants.ServiceAccount + "dw"
|
||||||
|
}
|
||||||
|
|
|
||||||
145
vendor/github.com/devfile/devworkspace-operator/pkg/config/configmap/config.go
generated
vendored
Normal file
145
vendor/github.com/devfile/devworkspace-operator/pkg/config/configmap/config.go
generated
vendored
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019-2021 Red Hat, 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 configmap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||||
|
|
||||||
|
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ControllerCfg ControllerConfig
|
||||||
|
var log = logf.Log.WithName("controller_devworkspace_config")
|
||||||
|
|
||||||
|
const (
|
||||||
|
ConfigMapNameEnvVar = "CONTROLLER_CONFIG_MAP_NAME"
|
||||||
|
ConfigMapNamespaceEnvVar = "CONTROLLER_CONFIG_MAP_NAMESPACE"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ConfigMapReference = client.ObjectKey{
|
||||||
|
Namespace: "",
|
||||||
|
Name: "devworkspace-controller-configmap",
|
||||||
|
}
|
||||||
|
|
||||||
|
type ControllerConfig struct {
|
||||||
|
configMap *corev1.ConfigMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *ControllerConfig) update(configMap *corev1.ConfigMap) {
|
||||||
|
log.Info("Updating the configuration from config map '%s' in namespace '%s'", configMap.Name, configMap.Namespace)
|
||||||
|
wc.configMap = configMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *ControllerConfig) GetWorkspacePVCName() *string {
|
||||||
|
return wc.GetProperty(workspacePVCName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *ControllerConfig) GetDefaultRoutingClass() *string {
|
||||||
|
return wc.GetProperty(routingClass)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *ControllerConfig) GetClusterRoutingSuffix() *string {
|
||||||
|
return wc.GetProperty(routingSuffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
//GetExperimentalFeaturesEnabled returns true if experimental features should be enabled.
|
||||||
|
//DO NOT TURN ON IT IN THE PRODUCTION.
|
||||||
|
//Experimental features are not well tested and may be totally removed without announcement.
|
||||||
|
func (wc *ControllerConfig) GetExperimentalFeaturesEnabled() *string {
|
||||||
|
return wc.GetProperty(experimentalFeaturesEnabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *ControllerConfig) GetPVCStorageClassName() *string {
|
||||||
|
return wc.GetProperty(workspacePVCStorageClassName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *ControllerConfig) GetSidecarPullPolicy() *string {
|
||||||
|
return wc.GetProperty(sidecarPullPolicy)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *ControllerConfig) GetProperty(name string) *string {
|
||||||
|
val, exists := wc.configMap.Data[name]
|
||||||
|
if exists {
|
||||||
|
return &val
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *ControllerConfig) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *ControllerConfig) GetWorkspaceIdleTimeout() *string {
|
||||||
|
return wc.GetProperty(devworkspaceIdleTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func syncConfigmapFromCluster(client client.Client, obj client.Object) {
|
||||||
|
if obj.GetNamespace() != ConfigMapReference.Namespace ||
|
||||||
|
obj.GetName() != ConfigMapReference.Name {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if cm, isConfigMap := obj.(*corev1.ConfigMap); isConfigMap {
|
||||||
|
ControllerCfg.update(cm)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadControllerConfig(nonCachedClient client.Client) (found bool, err error) {
|
||||||
|
configMapName, found := os.LookupEnv(ConfigMapNameEnvVar)
|
||||||
|
if found && len(configMapName) > 0 {
|
||||||
|
ConfigMapReference.Name = configMapName
|
||||||
|
}
|
||||||
|
configMapNamespace, found := os.LookupEnv(ConfigMapNamespaceEnvVar)
|
||||||
|
if found && len(configMapNamespace) > 0 {
|
||||||
|
ConfigMapReference.Namespace = configMapNamespace
|
||||||
|
} else {
|
||||||
|
namespace, err := infrastructure.GetNamespace()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
ConfigMapReference.Namespace = namespace
|
||||||
|
}
|
||||||
|
|
||||||
|
if ConfigMapReference.Namespace == "" {
|
||||||
|
return false, fmt.Errorf("you should set the namespace of the controller config map through the '%s' environment variable", ConfigMapNamespaceEnvVar)
|
||||||
|
}
|
||||||
|
|
||||||
|
configMap := &corev1.ConfigMap{}
|
||||||
|
log.Info(fmt.Sprintf("Searching for config map '%s' in namespace '%s'", ConfigMapReference.Name, ConfigMapReference.Namespace))
|
||||||
|
err = nonCachedClient.Get(context.TODO(), ConfigMapReference, configMap)
|
||||||
|
if err != nil {
|
||||||
|
if !k8sErrors.IsNotFound(err) {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
} else {
|
||||||
|
log.Info(fmt.Sprintf(" => found config map '%s' in namespace '%s'", configMap.GetObjectMeta().GetName(), configMap.GetObjectMeta().GetNamespace()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if configMap.Data == nil {
|
||||||
|
configMap.Data = map[string]string{}
|
||||||
|
}
|
||||||
|
syncConfigmapFromCluster(nonCachedClient, configMap)
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
26
vendor/github.com/devfile/devworkspace-operator/pkg/config/configmap/doc.go
generated
vendored
Normal file
26
vendor/github.com/devfile/devworkspace-operator/pkg/config/configmap/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019-2021 Red Hat, 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 config is used by components to get configuration.
|
||||||
|
//
|
||||||
|
// Typically each configuration property has the default value.
|
||||||
|
// Default value is supposed to be overridden via config map.
|
||||||
|
//
|
||||||
|
// There is the following configuration names convention:
|
||||||
|
// - words are lower-cased
|
||||||
|
// - . is used to separate subcomponents
|
||||||
|
// - _ is used to separate words in the component name
|
||||||
|
//
|
||||||
|
|
||||||
|
package configmap
|
||||||
43
vendor/github.com/devfile/devworkspace-operator/pkg/config/configmap/property.go
generated
vendored
Normal file
43
vendor/github.com/devfile/devworkspace-operator/pkg/config/configmap/property.go
generated
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019-2021 Red Hat, 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 configmap
|
||||||
|
|
||||||
|
const (
|
||||||
|
// image pull policy that is applied to every container within workspace
|
||||||
|
sidecarPullPolicy = "devworkspace.sidecar.image_pull_policy"
|
||||||
|
defaultSidecarPullPolicy = "Always"
|
||||||
|
|
||||||
|
// workspacePVCName config property handles the PVC name that should be created and used for all workspaces within one kubernetes namespace
|
||||||
|
workspacePVCName = "devworkspace.pvc.name"
|
||||||
|
defaultWorkspacePVCName = "claim-devworkspace"
|
||||||
|
|
||||||
|
workspacePVCStorageClassName = "devworkspace.pvc.storage_class.name"
|
||||||
|
|
||||||
|
// routingClass defines the default routing class that should be used if user does not specify it explicitly
|
||||||
|
routingClass = "devworkspace.default_routing_class"
|
||||||
|
defaultRoutingClass = "basic"
|
||||||
|
|
||||||
|
// routingSuffix is the base domain for routes/ingresses created on the cluster. All
|
||||||
|
// routes/ingresses will be created with URL http(s)://<unique-to-workspace-part>.<routingSuffix>
|
||||||
|
// is supposed to be used by embedded routing solvers only
|
||||||
|
routingSuffix = "devworkspace.routing.cluster_host_suffix"
|
||||||
|
|
||||||
|
experimentalFeaturesEnabled = "devworkspace.experimental_features_enabled"
|
||||||
|
defaultExperimentalFeaturesEnabled = "false"
|
||||||
|
|
||||||
|
devworkspaceIdleTimeout = "devworkspace.idle_timeout"
|
||||||
|
defaultDevWorkspaceIdleTimeout = "15m"
|
||||||
|
)
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
import "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
151
vendor/github.com/devfile/devworkspace-operator/pkg/config/migrate.go
generated
vendored
Normal file
151
vendor/github.com/devfile/devworkspace-operator/pkg/config/migrate.go
generated
vendored
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019-2021 Red Hat, Inc.
|
||||||
|
// This program and the accompanying materials are made
|
||||||
|
// available under the terms of the Eclipse Public License 2.0
|
||||||
|
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: EPL-2.0
|
||||||
|
//
|
||||||
|
// Contributors:
|
||||||
|
// Red Hat, Inc. - initial API and implementation
|
||||||
|
//
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/equality"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
crclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
|
||||||
|
dw "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
||||||
|
"github.com/devfile/devworkspace-operator/pkg/config/configmap"
|
||||||
|
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||||
|
)
|
||||||
|
|
||||||
|
func MigrateConfigFromConfigMap(client crclient.Client) error {
|
||||||
|
migratedConfig, err := convertConfigMapToConfigCRD(client)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if migratedConfig == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace, err := infrastructure.GetNamespace()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
clusterConfig, err := getClusterConfig(namespace, client)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if clusterConfig != nil {
|
||||||
|
// Check using DeepDerivative in case cluster config contains default/additional values -- we only care
|
||||||
|
// that values in migratedConfig are propagated to the cluster DWOC.
|
||||||
|
if equality.Semantic.DeepDerivative(migratedConfig.Config, clusterConfig.Config) {
|
||||||
|
log.Info("Found deprecated operator configmap matching config custom resource. Deleting.")
|
||||||
|
// In case we migrated before but failed to delete
|
||||||
|
return deleteMigratedConfigmap(client)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("found both DevWorkspaceOperatorConfig and configmap on cluster -- cannot migrate")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set namespace in case obsolete env vars were used to specify a custom namespace for the configmap
|
||||||
|
migratedConfig.Namespace = namespace
|
||||||
|
if err := client.Create(context.Background(), migratedConfig); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info("Migrated operator configuration from configmap")
|
||||||
|
return deleteMigratedConfigmap(client)
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteMigratedConfigmap(client crclient.Client) error {
|
||||||
|
obsoleteConfigmap := &corev1.ConfigMap{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: configmap.ConfigMapReference.Name,
|
||||||
|
Namespace: configmap.ConfigMapReference.Namespace,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return client.Delete(context.Background(), obsoleteConfigmap)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertConfigMapToConfigCRD converts a earlier devworkspace configuration configmap (if present)
|
||||||
|
// into a DevWorkspaceOperatorConfig. Values matching the current default config settings are ignored.
|
||||||
|
// If the configmap is not present, or if the configmap is present but all values are default, returns
|
||||||
|
// nil. Returns an error if we fail to load the controller config from configmap.
|
||||||
|
func convertConfigMapToConfigCRD(client crclient.Client) (*dw.DevWorkspaceOperatorConfig, error) {
|
||||||
|
found, err := configmap.LoadControllerConfig(client)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
migratedRoutingConfig := &dw.RoutingConfig{}
|
||||||
|
setRoutingConfig := false
|
||||||
|
routingSuffix := configmap.ControllerCfg.GetClusterRoutingSuffix()
|
||||||
|
if routingSuffix != nil && *routingSuffix != DefaultConfig.Routing.ClusterHostSuffix {
|
||||||
|
migratedRoutingConfig.ClusterHostSuffix = *routingSuffix
|
||||||
|
setRoutingConfig = true
|
||||||
|
}
|
||||||
|
defaultRoutingClass := configmap.ControllerCfg.GetDefaultRoutingClass()
|
||||||
|
if defaultRoutingClass != nil && *defaultRoutingClass != DefaultConfig.Routing.DefaultRoutingClass {
|
||||||
|
migratedRoutingConfig.DefaultRoutingClass = *defaultRoutingClass
|
||||||
|
setRoutingConfig = true
|
||||||
|
}
|
||||||
|
|
||||||
|
migratedWorkspaceConfig := &dw.WorkspaceConfig{}
|
||||||
|
setWorkspaceConfig := false
|
||||||
|
storageClassName := configmap.ControllerCfg.GetPVCStorageClassName()
|
||||||
|
if storageClassName != DefaultConfig.Workspace.StorageClassName {
|
||||||
|
migratedWorkspaceConfig.StorageClassName = storageClassName
|
||||||
|
setWorkspaceConfig = true
|
||||||
|
}
|
||||||
|
sidecarPullPolicy := configmap.ControllerCfg.GetSidecarPullPolicy()
|
||||||
|
if sidecarPullPolicy != nil && *sidecarPullPolicy != DefaultConfig.Workspace.ImagePullPolicy {
|
||||||
|
migratedWorkspaceConfig.ImagePullPolicy = *sidecarPullPolicy
|
||||||
|
setWorkspaceConfig = true
|
||||||
|
}
|
||||||
|
idleTimeout := configmap.ControllerCfg.GetWorkspaceIdleTimeout()
|
||||||
|
if idleTimeout != nil && *idleTimeout != DefaultConfig.Workspace.IdleTimeout {
|
||||||
|
migratedWorkspaceConfig.IdleTimeout = *idleTimeout
|
||||||
|
setWorkspaceConfig = true
|
||||||
|
}
|
||||||
|
pvcName := configmap.ControllerCfg.GetWorkspacePVCName()
|
||||||
|
if pvcName != nil && *pvcName != DefaultConfig.Workspace.PVCName {
|
||||||
|
migratedWorkspaceConfig.PVCName = *pvcName
|
||||||
|
setWorkspaceConfig = true
|
||||||
|
}
|
||||||
|
|
||||||
|
var experimentalFeatures *bool
|
||||||
|
experimentalFeaturesStr := configmap.ControllerCfg.GetExperimentalFeaturesEnabled()
|
||||||
|
if experimentalFeaturesStr != nil && *experimentalFeaturesStr == "true" {
|
||||||
|
trueBool := true
|
||||||
|
experimentalFeatures = &trueBool
|
||||||
|
}
|
||||||
|
|
||||||
|
if !setRoutingConfig && !setWorkspaceConfig && experimentalFeatures == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
migratedConfig := &dw.DevWorkspaceOperatorConfig{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: OperatorConfigName,
|
||||||
|
Namespace: configmap.ConfigMapReference.Namespace,
|
||||||
|
},
|
||||||
|
Config: &dw.OperatorConfiguration{},
|
||||||
|
}
|
||||||
|
migratedConfig.Config.EnableExperimentalFeatures = experimentalFeatures
|
||||||
|
if setRoutingConfig {
|
||||||
|
migratedConfig.Config.Routing = migratedRoutingConfig
|
||||||
|
}
|
||||||
|
if setWorkspaceConfig {
|
||||||
|
migratedConfig.Config.Workspace = migratedWorkspaceConfig
|
||||||
|
}
|
||||||
|
return migratedConfig, nil
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -73,14 +74,13 @@ func SetupControllerConfig(client crclient.Client) error {
|
||||||
} else {
|
} else {
|
||||||
syncConfigFrom(config)
|
syncConfigFrom(config)
|
||||||
}
|
}
|
||||||
|
defaultRoutingSuffix, err := discoverRouteSuffix(client)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
DefaultConfig.Routing.ClusterHostSuffix = defaultRoutingSuffix
|
||||||
if internalConfig.Routing.ClusterHostSuffix == "" {
|
if internalConfig.Routing.ClusterHostSuffix == "" {
|
||||||
routeSuffix, err := discoverRouteSuffix(client)
|
internalConfig.Routing.ClusterHostSuffix = defaultRoutingSuffix
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
internalConfig.Routing.ClusterHostSuffix = routeSuffix
|
|
||||||
// Set routing suffix in default config as well to ensure value is persisted across config changes
|
|
||||||
DefaultConfig.Routing.ClusterHostSuffix = routeSuffix
|
|
||||||
updatePublicConfig()
|
updatePublicConfig()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,60 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package constants
|
package constants
|
||||||
|
|
||||||
// Constants that are used in attributes on DevWorkspace elements (components, endpoints, etc.)
|
// Constants that are used in attributes on DevWorkspace elements (components, endpoints, etc.)
|
||||||
const (
|
const (
|
||||||
|
// DevWorkspaceStorageTypeAttribute defines the strategy used for provisioning storage for the workspace.
|
||||||
|
// If empty, the common PVC strategy is used.
|
||||||
|
// Supported options:
|
||||||
|
// - "common": Create one PVC per namespace, and store data for all workspaces in that namespace in that PVC
|
||||||
|
// - "async" : Create one PVC per namespace, and create a remote server that syncs data from workspaces to the PVC.
|
||||||
|
// All volumeMounts used for devworkspaces are emptyDir
|
||||||
|
// - "ephemeral": Use emptyDir volumes for all volumes in the DevWorkspace. All data is lost when the workspace is
|
||||||
|
// stopped.
|
||||||
|
DevWorkspaceStorageTypeAttribute = "controller.devfile.io/storage-type"
|
||||||
|
|
||||||
|
// WorkspaceEnvAttribute is an attribute that specifies a set of environment variables provided by a component
|
||||||
|
// that should be added to all workspace containers. The structure of the attribute value should be a list of
|
||||||
|
// Devfile 2.0 EnvVar, e.g.
|
||||||
|
//
|
||||||
|
// attributes:
|
||||||
|
// workspaceEnv:
|
||||||
|
// - name: ENV_1
|
||||||
|
// value: VAL_1
|
||||||
|
// - name: ENV_2
|
||||||
|
// value: VAL_2
|
||||||
|
WorkspaceEnvAttribute = "workspaceEnv"
|
||||||
|
|
||||||
|
// WorkspaceSCCAttribute defines additional SCCs that should be added to the DevWorkspace. The user adding
|
||||||
|
// this attribute to a workspace must have the RBAC permissions to "use" the SCC with the given name. For example,
|
||||||
|
// to add the 'anyuid' SCC to the workspace Pod, the DevWorkspace should contain
|
||||||
|
//
|
||||||
|
// spec:
|
||||||
|
// template:
|
||||||
|
// attributes:
|
||||||
|
// controller.devfile.io/scc: "anyuid"
|
||||||
|
//
|
||||||
|
// Creating a workspace with this attribute, or updating an existing workspace to include this attribute will fail
|
||||||
|
// if the user making the request does not have the "use" permission for the "anyuid" SCC.
|
||||||
|
// Only supported on OpenShift.
|
||||||
|
WorkspaceSCCAttribute = "controller.devfile.io/scc"
|
||||||
|
|
||||||
|
// ProjectCloneAttribute configures how the DevWorkspace will treat project cloning. By default, an init container
|
||||||
|
// will be added to the workspace deployment to clone projects to the workspace before it starts. This attribute
|
||||||
|
// must be applied to top-level attributes field in the DevWorkspace.
|
||||||
|
// Supported options:
|
||||||
|
// - "disable" - Disable automatic project cloning. No init container will be added to the workspace and projects
|
||||||
|
// will not be cloned into the workspace on start.
|
||||||
|
ProjectCloneAttribute = "controller.devfile.io/project-clone"
|
||||||
|
|
||||||
// PluginSourceAttribute is an attribute added to components, commands, and projects in a flattened
|
// PluginSourceAttribute is an attribute added to components, commands, and projects in a flattened
|
||||||
// DevWorkspace representation to signify where the respective component came from (i.e. which plugin
|
// DevWorkspace representation to signify where the respective component came from (i.e. which plugin
|
||||||
// or parent imported it)
|
// or parent imported it)
|
||||||
PluginSourceAttribute = "controller.devfile.io/imported-by"
|
PluginSourceAttribute = "controller.devfile.io/imported-by"
|
||||||
|
|
||||||
// EndpointURLAttribute is an attribute added to endpoints to denote the endpoint on the cluster that
|
// EndpointURLAttribute is an attribute added to endpoints to denote the endpoint on the cluster that
|
||||||
// was created to route to this endpoint
|
// was created to route to this endpoint
|
||||||
EndpointURLAttribute = "controller.devfile.io/endpoint-url"
|
EndpointURLAttribute = "controller.devfile.io/endpoint-url"
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
// package constants defines constant values used throughout the DevWorkspace Operator
|
|
||||||
|
// Package constants defines constant values used throughout the DevWorkspace Operator
|
||||||
package constants
|
package constants
|
||||||
|
|
||||||
// Labels which should be used for controller related objects
|
// Labels which should be used for controller related objects
|
||||||
|
|
@ -62,6 +63,7 @@ const (
|
||||||
ProjectCloneCPURequest = "100m"
|
ProjectCloneCPURequest = "100m"
|
||||||
|
|
||||||
// Constants describing storage classes supported by the controller
|
// Constants describing storage classes supported by the controller
|
||||||
|
|
||||||
// CommonStorageClassType defines the 'common' storage policy -- one PVC is provisioned per namespace and all devworkspace storage
|
// CommonStorageClassType defines the 'common' storage policy -- one PVC is provisioned per namespace and all devworkspace storage
|
||||||
// is mounted in it on subpaths according to devworkspace ID.
|
// is mounted in it on subpaths according to devworkspace ID.
|
||||||
CommonStorageClassType = "common"
|
CommonStorageClassType = "common"
|
||||||
|
|
@ -71,4 +73,9 @@ const (
|
||||||
// EphemeralStorageClassType defines the 'ephemeral' storage policy: all volumes are allocated as emptyDir volumes and
|
// EphemeralStorageClassType defines the 'ephemeral' storage policy: all volumes are allocated as emptyDir volumes and
|
||||||
// so do not require cleanup. When a DevWorkspace is stopped, all local changes are lost.
|
// so do not require cleanup. When a DevWorkspace is stopped, all local changes are lost.
|
||||||
EphemeralStorageClassType = "ephemeral"
|
EphemeralStorageClassType = "ephemeral"
|
||||||
|
|
||||||
|
// Constants describing configuration for automatic project cloning
|
||||||
|
|
||||||
|
// ProjectCloneDisable specifies that project cloning should be disabled.
|
||||||
|
ProjectCloneDisable = "disable"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package constants
|
package constants
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,10 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package constants
|
package constants
|
||||||
|
|
||||||
// Constants that are used in labels and annotation on DevWorkspace-related resources.
|
// Constants that are used in labels and annotations on DevWorkspace-related resources.
|
||||||
const (
|
const (
|
||||||
// DevWorkspaceIDLabel is the label key to store workspace identifier
|
// DevWorkspaceIDLabel is the label key to store workspace identifier
|
||||||
DevWorkspaceIDLabel = "controller.devfile.io/devworkspace_id"
|
DevWorkspaceIDLabel = "controller.devfile.io/devworkspace_id"
|
||||||
|
|
@ -25,6 +26,14 @@ const (
|
||||||
// DevWorkspaceNameLabel is the label key to store workspace name
|
// DevWorkspaceNameLabel is the label key to store workspace name
|
||||||
DevWorkspaceNameLabel = "controller.devfile.io/devworkspace_name"
|
DevWorkspaceNameLabel = "controller.devfile.io/devworkspace_name"
|
||||||
|
|
||||||
|
// DevWorkspaceWatchConfigMapLabel marks a configmap so that it is watched by the controller. This label is required on all
|
||||||
|
// configmaps that should be seen by the controller
|
||||||
|
DevWorkspaceWatchConfigMapLabel = "controller.devfile.io/watch-configmap"
|
||||||
|
|
||||||
|
// DevWorkspaceWatchSecretLabel marks a secret so that it is watched by the controller. This label is required on all
|
||||||
|
// secrets that should be seen by the controller
|
||||||
|
DevWorkspaceWatchSecretLabel = "controller.devfile.io/watch-secret"
|
||||||
|
|
||||||
// DevWorkspaceMountLabel is the label key to store if a configmap or secret should be mounted to the devworkspace
|
// DevWorkspaceMountLabel is the label key to store if a configmap or secret should be mounted to the devworkspace
|
||||||
DevWorkspaceMountLabel = "controller.devfile.io/mount-to-devworkspace"
|
DevWorkspaceMountLabel = "controller.devfile.io/mount-to-devworkspace"
|
||||||
|
|
||||||
|
|
@ -36,6 +45,14 @@ const (
|
||||||
// see https://git-scm.com/docs/git-credential-store#_storage_format for more details
|
// see https://git-scm.com/docs/git-credential-store#_storage_format for more details
|
||||||
DevWorkspaceGitCredentialLabel = "controller.devfile.io/git-credential"
|
DevWorkspaceGitCredentialLabel = "controller.devfile.io/git-credential"
|
||||||
|
|
||||||
|
// DevWorkspaceGitTLSLabel is the label key to specify if the configmap is credentials for accessing a git server.
|
||||||
|
// Configmap must contain the following data:
|
||||||
|
// certificate: the certificate used to access the git server in Base64 ASCII
|
||||||
|
// You can also optionally define the git host.
|
||||||
|
// host: the url of the git server
|
||||||
|
// If the git host is not defined then the certificate will be used for all http repositories.
|
||||||
|
DevWorkspaceGitTLSLabel = "controller.devfile.io/git-tls-credential"
|
||||||
|
|
||||||
// DevWorkspaceMountPathAnnotation is the annotation key to store the mount path for the secret or configmap.
|
// DevWorkspaceMountPathAnnotation is the annotation key to store the mount path for the secret or configmap.
|
||||||
// If no mount path is provided, configmaps will be mounted at /etc/config/<configmap-name>, secrets will
|
// If no mount path is provided, configmaps will be mounted at /etc/config/<configmap-name>, secrets will
|
||||||
// be mounted at /etc/secret/<secret-name>, and persistent volume claims will be mounted to /tmp/<claim-name>
|
// be mounted at /etc/secret/<secret-name>, and persistent volume claims will be mounted to /tmp/<claim-name>
|
||||||
|
|
@ -74,26 +91,21 @@ const (
|
||||||
// WebhookRestartedAtAnnotation holds the the time (unixnano) of when the webhook server was forced to restart by controller
|
// WebhookRestartedAtAnnotation holds the the time (unixnano) of when the webhook server was forced to restart by controller
|
||||||
WebhookRestartedAtAnnotation = "controller.devfile.io/restarted-at"
|
WebhookRestartedAtAnnotation = "controller.devfile.io/restarted-at"
|
||||||
|
|
||||||
|
// DevWorkspaceStartedAtAnnotation holds the the time (unixnano) of when the devworkspace was started
|
||||||
|
DevWorkspaceStartedAtAnnotation = "controller.devfile.io/started-at"
|
||||||
|
|
||||||
// RoutingAnnotationInfix is the infix of the annotations of DevWorkspace that are passed down as annotation to the DevWorkspaceRouting objects.
|
// RoutingAnnotationInfix is the infix of the annotations of DevWorkspace that are passed down as annotation to the DevWorkspaceRouting objects.
|
||||||
// The full annotation name is supposed to be "<routingClass>.routing.controller.devfile.io/<anything>"
|
// The full annotation name is supposed to be "<routingClass>.routing.controller.devfile.io/<anything>"
|
||||||
RoutingAnnotationInfix = ".routing.controller.devfile.io/"
|
RoutingAnnotationInfix = ".routing.controller.devfile.io/"
|
||||||
|
|
||||||
// DevWorkspaceStorageTypeAtrr defines the strategy used for provisioning storage for the workspace.
|
// DevWorkspaceEndpointNameAnnotation is the annotation key for storing an endpoint's name from the devfile representation
|
||||||
// If empty, the common PVC strategy is used.
|
|
||||||
// Supported options:
|
|
||||||
// - "common": Create one PVC per namespace, and store data for all workspaces in that namespace in that PVC
|
|
||||||
// - "async" : Create one PVC per namespace, and create a remote server that syncs data from workspaces to the PVC.
|
|
||||||
// All volumeMounts used for devworkspaces are emptyDir
|
|
||||||
DevWorkspaceStorageTypeAtrr = "controller.devfile.io/storage-type"
|
|
||||||
|
|
||||||
// WorkspaceEndpointNameAnnotation is the annotation key for storing an endpoint's name from the devfile representation
|
|
||||||
DevWorkspaceEndpointNameAnnotation = "controller.devfile.io/endpoint_name"
|
DevWorkspaceEndpointNameAnnotation = "controller.devfile.io/endpoint_name"
|
||||||
|
|
||||||
// DevWorkspaceDiscoverableServiceAnnotation marks a service in a devworkspace as created for a discoverable endpoint,
|
// DevWorkspaceDiscoverableServiceAnnotation marks a service in a devworkspace as created for a discoverable endpoint,
|
||||||
// as opposed to a service created to support the devworkspace itself.
|
// as opposed to a service created to support the devworkspace itself.
|
||||||
DevWorkspaceDiscoverableServiceAnnotation = "controller.devfile.io/discoverable-service"
|
DevWorkspaceDiscoverableServiceAnnotation = "controller.devfile.io/discoverable-service"
|
||||||
|
|
||||||
// PullSecretLabel marks the intention that secret should be used as pull secret for devworkspaces withing namespace
|
// DevWorkspacePullSecretLabel marks the intention that this secret should be used as a pull secret for devworkspaces within namespace
|
||||||
// Only secrets with 'true' value will be mount as pull secret
|
// Only secrets with 'true' value will be mount as pull secret
|
||||||
// Should be assigned to secrets with type docker config types (kubernetes.io/dockercfg and kubernetes.io/dockerconfigjson)
|
// Should be assigned to secrets with type docker config types (kubernetes.io/dockercfg and kubernetes.io/dockerconfigjson)
|
||||||
DevWorkspacePullSecretLabel = "controller.devfile.io/devworkspace_pullsecret"
|
DevWorkspacePullSecretLabel = "controller.devfile.io/devworkspace_pullsecret"
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package infrastructure
|
package infrastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
1
vendor/github.com/devfile/devworkspace-operator/pkg/infrastructure/namespace.go
generated
vendored
1
vendor/github.com/devfile/devworkspace-operator/pkg/infrastructure/namespace.go
generated
vendored
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package infrastructure
|
package infrastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
package infrastructure
|
package infrastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
69
vendor/github.com/devfile/devworkspace-operator/pkg/provision/sync/cluster_api.go
generated
vendored
Normal file
69
vendor/github.com/devfile/devworkspace-operator/pkg/provision/sync/cluster_api.go
generated
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
// Copyright (c) 2019-2021 Red Hat, 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 sync
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
crclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ClusterAPI struct {
|
||||||
|
Client crclient.Client
|
||||||
|
NonCachingClient crclient.Client
|
||||||
|
Scheme *runtime.Scheme
|
||||||
|
Logger logr.Logger
|
||||||
|
Ctx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotInSyncError is returned when a spec object is out-of-sync with its cluster counterpart
|
||||||
|
type NotInSyncError struct {
|
||||||
|
Reason NotInSyncReason
|
||||||
|
Object crclient.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
type NotInSyncReason string
|
||||||
|
|
||||||
|
const (
|
||||||
|
UpdatedObjectReason NotInSyncReason = "Updated object"
|
||||||
|
CreatedObjectReason NotInSyncReason = "Created object"
|
||||||
|
DeletedObjectReason NotInSyncReason = "Deleted object"
|
||||||
|
NeedRetryReason NotInSyncReason = "Need to retry"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (e *NotInSyncError) Error() string {
|
||||||
|
return fmt.Sprintf("%s %s is not ready: %s", reflect.TypeOf(e.Object).Elem().String(), e.Object.GetName(), e.Reason)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotInSync wraps creation of NotInSyncErrors for simplicity
|
||||||
|
func NewNotInSync(obj crclient.Object, reason NotInSyncReason) *NotInSyncError {
|
||||||
|
return &NotInSyncError{
|
||||||
|
Reason: reason,
|
||||||
|
Object: obj,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnrecoverableSyncError is returned when provided objects cannot be synced with the cluster due to
|
||||||
|
// an unexpected error (e.g. they are invalid according to the object's spec).
|
||||||
|
type UnrecoverableSyncError struct {
|
||||||
|
Cause error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *UnrecoverableSyncError) Error() string {
|
||||||
|
return e.Cause.Error()
|
||||||
|
}
|
||||||
135
vendor/github.com/devfile/devworkspace-operator/pkg/provision/sync/diff.go
generated
vendored
Normal file
135
vendor/github.com/devfile/devworkspace-operator/pkg/provision/sync/diff.go
generated
vendored
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
// Copyright (c) 2019-2021 Red Hat, 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 sync
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
routev1 "github.com/openshift/api/route/v1"
|
||||||
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
batchv1 "k8s.io/api/batch/v1"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
networkingv1 "k8s.io/api/networking/v1"
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/equality"
|
||||||
|
crclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// diffFunc represents a function that compares a spec object against the corresponding cluster object and
|
||||||
|
// returns whether the object should be deleted or updated.
|
||||||
|
type diffFunc func(spec crclient.Object, cluster crclient.Object) (delete, update bool)
|
||||||
|
|
||||||
|
var diffFuncs = map[reflect.Type]diffFunc{
|
||||||
|
reflect.TypeOf(rbacv1.Role{}): basicDiffFunc(roleDiffOpts),
|
||||||
|
reflect.TypeOf(rbacv1.RoleBinding{}): basicDiffFunc(rolebindingDiffOpts),
|
||||||
|
reflect.TypeOf(corev1.ServiceAccount{}): labelsAndAnnotationsDiffFunc,
|
||||||
|
reflect.TypeOf(appsv1.Deployment{}): allDiffFuncs(deploymentDiffFunc, basicDiffFunc(deploymentDiffOpts)),
|
||||||
|
reflect.TypeOf(corev1.ConfigMap{}): basicDiffFunc(configmapDiffOpts),
|
||||||
|
reflect.TypeOf(v1alpha1.DevWorkspaceRouting{}): allDiffFuncs(routingDiffFunc, labelsAndAnnotationsDiffFunc, basicDiffFunc(routingDiffOpts)),
|
||||||
|
reflect.TypeOf(batchv1.Job{}): jobDiffFunc,
|
||||||
|
reflect.TypeOf(corev1.Service{}): serviceDiffFunc,
|
||||||
|
reflect.TypeOf(networkingv1.Ingress{}): basicDiffFunc(ingressDiffOpts),
|
||||||
|
reflect.TypeOf(routev1.Route{}): basicDiffFunc(routeDiffOpts),
|
||||||
|
}
|
||||||
|
|
||||||
|
// basicDiffFunc returns a diffFunc that specifies an object needs an update if cmp.Equal fails
|
||||||
|
func basicDiffFunc(diffOpt cmp.Options) diffFunc {
|
||||||
|
return func(spec, cluster crclient.Object) (delete, update bool) {
|
||||||
|
return false, !cmp.Equal(spec, cluster, diffOpt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// labelsAndAnnotationsDiffFunc requires an object to be updated if any label or annotation present in the spec
|
||||||
|
// object is not present in the cluster object.
|
||||||
|
func labelsAndAnnotationsDiffFunc(spec, cluster crclient.Object) (delete, update bool) {
|
||||||
|
clusterAnnotations := cluster.GetAnnotations()
|
||||||
|
for k, v := range spec.GetAnnotations() {
|
||||||
|
if clusterAnnotations[k] != v {
|
||||||
|
return false, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clusterLabels := cluster.GetLabels()
|
||||||
|
for k, v := range spec.GetLabels() {
|
||||||
|
if clusterLabels[k] != v {
|
||||||
|
return false, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// allDiffFuncs represents an 'and' condition across specified diffFuncs. Functions are checked in provided order,
|
||||||
|
// returning the result of the first function to require an update/deletion.
|
||||||
|
func allDiffFuncs(funcs ...diffFunc) diffFunc {
|
||||||
|
return func(spec, cluster crclient.Object) (delete, update bool) {
|
||||||
|
for _, df := range funcs {
|
||||||
|
shouldDelete, shouldUpdate := df(spec, cluster)
|
||||||
|
if shouldDelete || shouldUpdate {
|
||||||
|
return shouldDelete, shouldUpdate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deploymentDiffFunc(spec, cluster crclient.Object) (delete, update bool) {
|
||||||
|
specDeploy := spec.(*appsv1.Deployment)
|
||||||
|
clusterDeploy := cluster.(*appsv1.Deployment)
|
||||||
|
if !cmp.Equal(specDeploy.Spec.Selector, clusterDeploy.Spec.Selector) {
|
||||||
|
return true, false
|
||||||
|
}
|
||||||
|
return false, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func routingDiffFunc(spec, cluster crclient.Object) (delete, update bool) {
|
||||||
|
specRouting := spec.(*v1alpha1.DevWorkspaceRouting)
|
||||||
|
clusterRouting := cluster.(*v1alpha1.DevWorkspaceRouting)
|
||||||
|
if specRouting.Spec.RoutingClass != clusterRouting.Spec.RoutingClass {
|
||||||
|
return true, false
|
||||||
|
}
|
||||||
|
return false, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func jobDiffFunc(spec, cluster crclient.Object) (delete, update bool) {
|
||||||
|
specJob := spec.(*batchv1.Job)
|
||||||
|
clusterJob := cluster.(*batchv1.Job)
|
||||||
|
// TODO: previously, this delete was specified with a background deletion policy, which is currently unsupported.
|
||||||
|
return !equality.Semantic.DeepDerivative(specJob.Spec, clusterJob.Spec), false
|
||||||
|
}
|
||||||
|
|
||||||
|
func serviceDiffFunc(spec, cluster crclient.Object) (delete, update bool) {
|
||||||
|
specService := spec.(*corev1.Service)
|
||||||
|
clusterService := cluster.(*corev1.Service)
|
||||||
|
specCopy := specService.DeepCopy()
|
||||||
|
clusterCopy := clusterService.DeepCopy()
|
||||||
|
if !cmp.Equal(specCopy.Spec.Selector, clusterCopy.Spec.Selector) {
|
||||||
|
return false, true
|
||||||
|
}
|
||||||
|
// Function that takes a slice of servicePorts and returns the appropriate comparison
|
||||||
|
// function to pass to sort.Slice() for that slice of servicePorts.
|
||||||
|
servicePortSorter := func(servicePorts []corev1.ServicePort) func(i, j int) bool {
|
||||||
|
return func(i, j int) bool {
|
||||||
|
return strings.Compare(servicePorts[i].Name, servicePorts[j].Name) > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Slice(specCopy.Spec.Ports, servicePortSorter(specCopy.Spec.Ports))
|
||||||
|
sort.Slice(clusterCopy.Spec.Ports, servicePortSorter(clusterCopy.Spec.Ports))
|
||||||
|
if !cmp.Equal(specCopy.Spec.Ports, clusterCopy.Spec.Ports) {
|
||||||
|
return false, true
|
||||||
|
}
|
||||||
|
return false, specCopy.Spec.Type != clusterCopy.Spec.Type
|
||||||
|
}
|
||||||
72
vendor/github.com/devfile/devworkspace-operator/pkg/provision/sync/diffopts.go
generated
vendored
Normal file
72
vendor/github.com/devfile/devworkspace-operator/pkg/provision/sync/diffopts.go
generated
vendored
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
// Copyright (c) 2019-2021 Red Hat, 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 sync
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
|
routeV1 "github.com/openshift/api/route/v1"
|
||||||
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
networkingv1 "k8s.io/api/networking/v1"
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
var roleDiffOpts = cmp.Options{
|
||||||
|
cmpopts.IgnoreFields(rbacv1.Role{}, "TypeMeta", "ObjectMeta"),
|
||||||
|
}
|
||||||
|
|
||||||
|
var rolebindingDiffOpts = cmp.Options{
|
||||||
|
cmpopts.IgnoreFields(rbacv1.RoleBinding{}, "TypeMeta", "ObjectMeta"),
|
||||||
|
cmpopts.IgnoreFields(rbacv1.RoleRef{}, "APIGroup"),
|
||||||
|
cmpopts.IgnoreFields(rbacv1.Subject{}, "APIGroup"),
|
||||||
|
}
|
||||||
|
|
||||||
|
var deploymentDiffOpts = cmp.Options{
|
||||||
|
cmpopts.IgnoreFields(appsv1.Deployment{}, "TypeMeta", "ObjectMeta", "Status"),
|
||||||
|
cmpopts.IgnoreFields(appsv1.DeploymentSpec{}, "RevisionHistoryLimit", "ProgressDeadlineSeconds"),
|
||||||
|
cmpopts.IgnoreFields(corev1.PodSpec{}, "DNSPolicy", "SchedulerName", "DeprecatedServiceAccount"),
|
||||||
|
cmpopts.IgnoreFields(corev1.Container{}, "TerminationMessagePath", "TerminationMessagePolicy", "ImagePullPolicy"),
|
||||||
|
cmpopts.SortSlices(func(a, b corev1.Container) bool {
|
||||||
|
return strings.Compare(a.Name, b.Name) > 0
|
||||||
|
}),
|
||||||
|
cmpopts.SortSlices(func(a, b corev1.Volume) bool {
|
||||||
|
return strings.Compare(a.Name, b.Name) > 0
|
||||||
|
}),
|
||||||
|
cmpopts.SortSlices(func(a, b corev1.VolumeMount) bool {
|
||||||
|
return strings.Compare(a.Name, b.Name) > 0
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
var configmapDiffOpts = cmp.Options{
|
||||||
|
cmpopts.IgnoreFields(corev1.ConfigMap{}, "TypeMeta", "ObjectMeta"),
|
||||||
|
}
|
||||||
|
|
||||||
|
var routingDiffOpts = cmp.Options{
|
||||||
|
cmpopts.IgnoreFields(v1alpha1.DevWorkspaceRouting{}, "ObjectMeta", "TypeMeta", "Status"),
|
||||||
|
}
|
||||||
|
|
||||||
|
var routeDiffOpts = cmp.Options{
|
||||||
|
cmpopts.IgnoreFields(routeV1.Route{}, "TypeMeta", "ObjectMeta", "Status"),
|
||||||
|
cmpopts.IgnoreFields(routeV1.RouteSpec{}, "WildcardPolicy", "Host"),
|
||||||
|
cmpopts.IgnoreFields(routeV1.RouteTargetReference{}, "Weight"),
|
||||||
|
}
|
||||||
|
|
||||||
|
var ingressDiffOpts = cmp.Options{
|
||||||
|
cmpopts.IgnoreFields(networkingv1.Ingress{}, "TypeMeta", "ObjectMeta", "Status"),
|
||||||
|
cmpopts.IgnoreFields(networkingv1.HTTPIngressPath{}, "PathType"),
|
||||||
|
}
|
||||||
150
vendor/github.com/devfile/devworkspace-operator/pkg/provision/sync/sync.go
generated
vendored
Normal file
150
vendor/github.com/devfile/devworkspace-operator/pkg/provision/sync/sync.go
generated
vendored
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
// Copyright (c) 2019-2021 Red Hat, 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 sync
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
||||||
|
"github.com/devfile/devworkspace-operator/pkg/config"
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
routev1 "github.com/openshift/api/route/v1"
|
||||||
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
networkingv1 "k8s.io/api/networking/v1"
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
crclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SyncObjectWithCluster synchronises the state of specObj to the cluster, creating or updating the cluster object
|
||||||
|
// as required. If specObj is in sync with the cluster, returns the object as it exists on the cluster. Returns a
|
||||||
|
// NotInSyncError if an update is required, UnrecoverableSyncError if object provided is invalid, or generic error
|
||||||
|
// if an unexpected error is encountered
|
||||||
|
func SyncObjectWithCluster(specObj crclient.Object, api ClusterAPI) (crclient.Object, error) {
|
||||||
|
objType := reflect.TypeOf(specObj).Elem()
|
||||||
|
clusterObj := reflect.New(objType).Interface().(crclient.Object)
|
||||||
|
|
||||||
|
err := api.Client.Get(api.Ctx, types.NamespacedName{Name: specObj.GetName(), Namespace: specObj.GetNamespace()}, clusterObj)
|
||||||
|
if err != nil {
|
||||||
|
if k8sErrors.IsNotFound(err) {
|
||||||
|
return nil, createObjectGeneric(specObj, api)
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isMutableObject(specObj) { // TODO: we could still update labels here, or treat a need to update as a fatal error
|
||||||
|
return clusterObj, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
diffFunc := diffFuncs[objType]
|
||||||
|
if diffFunc == nil {
|
||||||
|
return nil, &UnrecoverableSyncError{fmt.Errorf("attempting to sync unrecognized object %s", objType)}
|
||||||
|
}
|
||||||
|
shouldDelete, shouldUpdate := diffFunc(specObj, clusterObj)
|
||||||
|
if shouldDelete {
|
||||||
|
printDiff(specObj, clusterObj, api.Logger)
|
||||||
|
err := api.Client.Delete(api.Ctx, specObj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
api.Logger.Info("Deleted object", "kind", objType.String(), "name", specObj.GetName())
|
||||||
|
return nil, NewNotInSync(specObj, DeletedObjectReason)
|
||||||
|
}
|
||||||
|
if shouldUpdate {
|
||||||
|
printDiff(specObj, clusterObj, api.Logger)
|
||||||
|
return nil, updateObjectGeneric(specObj, clusterObj, api)
|
||||||
|
}
|
||||||
|
return clusterObj, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createObjectGeneric(specObj crclient.Object, api ClusterAPI) error {
|
||||||
|
err := api.Client.Create(api.Ctx, specObj)
|
||||||
|
switch {
|
||||||
|
case err == nil:
|
||||||
|
api.Logger.Info("Created object", "kind", reflect.TypeOf(specObj).Elem().String(), "name", specObj.GetName())
|
||||||
|
return NewNotInSync(specObj, CreatedObjectReason)
|
||||||
|
case k8sErrors.IsAlreadyExists(err):
|
||||||
|
// Need to try to update the object to address an edge case where removing a labelselector
|
||||||
|
// results in the object not being tracked by the controller's cache.
|
||||||
|
return updateObjectGeneric(specObj, nil, api)
|
||||||
|
case k8sErrors.IsInvalid(err):
|
||||||
|
return &UnrecoverableSyncError{err}
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateObjectGeneric(specObj, clusterObj crclient.Object, api ClusterAPI) error {
|
||||||
|
updateFunc := getUpdateFunc(specObj)
|
||||||
|
updatedObj, err := updateFunc(specObj, clusterObj)
|
||||||
|
if err != nil {
|
||||||
|
if err := api.Client.Delete(api.Ctx, specObj); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
api.Logger.Info("Deleted object", "kind", reflect.TypeOf(specObj).Elem().String(), "name", specObj.GetName())
|
||||||
|
return NewNotInSync(specObj, DeletedObjectReason)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = api.Client.Update(api.Ctx, updatedObj)
|
||||||
|
switch {
|
||||||
|
case err == nil:
|
||||||
|
api.Logger.Info("Updated object", "kind", reflect.TypeOf(specObj).Elem().String(), "name", specObj.GetName())
|
||||||
|
return NewNotInSync(specObj, UpdatedObjectReason)
|
||||||
|
case k8sErrors.IsConflict(err), k8sErrors.IsNotFound(err):
|
||||||
|
// Need to catch IsNotFound here because we attempt to update when creation fails with AlreadyExists
|
||||||
|
return NewNotInSync(specObj, NeedRetryReason)
|
||||||
|
case k8sErrors.IsInvalid(err):
|
||||||
|
return &UnrecoverableSyncError{err}
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isMutableObject(obj crclient.Object) bool {
|
||||||
|
switch obj.(type) {
|
||||||
|
case *corev1.PersistentVolumeClaim:
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printDiff(specObj, clusterObj crclient.Object, log logr.Logger) {
|
||||||
|
if config.ExperimentalFeaturesEnabled() {
|
||||||
|
var diffOpts cmp.Options
|
||||||
|
switch specObj.(type) {
|
||||||
|
case *rbacv1.Role:
|
||||||
|
diffOpts = roleDiffOpts
|
||||||
|
case *rbacv1.RoleBinding:
|
||||||
|
diffOpts = rolebindingDiffOpts
|
||||||
|
case *appsv1.Deployment:
|
||||||
|
diffOpts = deploymentDiffOpts
|
||||||
|
case *corev1.ConfigMap:
|
||||||
|
diffOpts = configmapDiffOpts
|
||||||
|
case *v1alpha1.DevWorkspaceRouting:
|
||||||
|
diffOpts = routingDiffOpts
|
||||||
|
case *networkingv1.Ingress:
|
||||||
|
diffOpts = ingressDiffOpts
|
||||||
|
case *routev1.Route:
|
||||||
|
diffOpts = routeDiffOpts
|
||||||
|
default:
|
||||||
|
diffOpts = nil
|
||||||
|
}
|
||||||
|
log.Info(fmt.Sprintf("Diff: %s", cmp.Diff(specObj, clusterObj, diffOpts)))
|
||||||
|
}
|
||||||
|
}
|
||||||
61
vendor/github.com/devfile/devworkspace-operator/pkg/provision/sync/update.go
generated
vendored
Normal file
61
vendor/github.com/devfile/devworkspace-operator/pkg/provision/sync/update.go
generated
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
// Copyright (c) 2019-2021 Red Hat, 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 sync
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
crclient "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// updateFunc returns the object that should be applied to the client.Update function
|
||||||
|
// when updating an object on the cluster. Typically, this will just be defaultUpdateFunc,
|
||||||
|
// which returns the spec obejct unmodified. However, some objects, such as Services, require
|
||||||
|
// fields to be copied over from the cluster object, e.g. .spec.clusterIP. If an updated object
|
||||||
|
// cannot be resolved, an error should be returned to signal that the object in question should
|
||||||
|
// be deleted instead.
|
||||||
|
//
|
||||||
|
// The 'cluster' argument may be specified as nil in the case where a cluster version of the
|
||||||
|
// spec object is inaccessible (not cached) and has to be handled specifically.
|
||||||
|
type updateFunc func(spec, cluster crclient.Object) (crclient.Object, error)
|
||||||
|
|
||||||
|
func defaultUpdateFunc(spec, cluster crclient.Object) (crclient.Object, error) {
|
||||||
|
if cluster != nil {
|
||||||
|
spec.SetResourceVersion(cluster.GetResourceVersion())
|
||||||
|
}
|
||||||
|
return spec, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func serviceUpdateFunc(spec, cluster crclient.Object) (crclient.Object, error) {
|
||||||
|
if cluster == nil {
|
||||||
|
return nil, errors.New("updating a service requires the cluster instance")
|
||||||
|
}
|
||||||
|
specService := spec.DeepCopyObject().(*corev1.Service)
|
||||||
|
clusterService := cluster.(*corev1.Service)
|
||||||
|
specService.ResourceVersion = clusterService.ResourceVersion
|
||||||
|
specService.Spec.ClusterIP = clusterService.Spec.ClusterIP
|
||||||
|
return specService, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getUpdateFunc(obj crclient.Object) updateFunc {
|
||||||
|
objType := reflect.TypeOf(obj).Elem()
|
||||||
|
switch objType {
|
||||||
|
case reflect.TypeOf(corev1.Service{}):
|
||||||
|
return serviceUpdateFunc
|
||||||
|
default:
|
||||||
|
return defaultUpdateFunc
|
||||||
|
}
|
||||||
|
}
|
||||||
0
vendor/google.golang.org/appengine/internal/regen.sh
generated
vendored
Executable file → Normal file
0
vendor/google.golang.org/appengine/internal/regen.sh
generated
vendored
Executable file → Normal file
0
vendor/google.golang.org/appengine/travis_install.sh
generated
vendored
Executable file → Normal file
0
vendor/google.golang.org/appengine/travis_install.sh
generated
vendored
Executable file → Normal file
0
vendor/google.golang.org/appengine/travis_test.sh
generated
vendored
Executable file → Normal file
0
vendor/google.golang.org/appengine/travis_test.sh
generated
vendored
Executable file → Normal file
0
vendor/google.golang.org/grpc/internal/binarylog/regenerate.sh
generated
vendored
Executable file → Normal file
0
vendor/google.golang.org/grpc/internal/binarylog/regenerate.sh
generated
vendored
Executable file → Normal file
|
|
@ -33,12 +33,12 @@ github.com/cespare/xxhash/v2
|
||||||
github.com/che-incubator/kubernetes-image-puller-operator/api/v1alpha1
|
github.com/che-incubator/kubernetes-image-puller-operator/api/v1alpha1
|
||||||
# github.com/davecgh/go-spew v1.1.1 => github.com/davecgh/go-spew v1.1.1
|
# github.com/davecgh/go-spew v1.1.1 => github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/davecgh/go-spew/spew
|
github.com/davecgh/go-spew/spew
|
||||||
# github.com/devfile/api/v2 v2.0.0-20210713124824-03e023e7078b
|
# github.com/devfile/api/v2 v2.0.0-20210917193329-089a48011460
|
||||||
## explicit
|
## explicit
|
||||||
github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2
|
github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2
|
||||||
github.com/devfile/api/v2/pkg/attributes
|
github.com/devfile/api/v2/pkg/attributes
|
||||||
github.com/devfile/api/v2/pkg/devfile
|
github.com/devfile/api/v2/pkg/devfile
|
||||||
# github.com/devfile/devworkspace-operator v0.2.1-0.20211005102315-728dff7e987c
|
# github.com/devfile/devworkspace-operator v0.2.1-0.20211213140302-4226bdb05e56
|
||||||
## explicit
|
## explicit
|
||||||
github.com/devfile/devworkspace-operator/apis/controller/v1alpha1
|
github.com/devfile/devworkspace-operator/apis/controller/v1alpha1
|
||||||
github.com/devfile/devworkspace-operator/controllers/controller/devworkspacerouting
|
github.com/devfile/devworkspace-operator/controllers/controller/devworkspacerouting
|
||||||
|
|
@ -46,8 +46,10 @@ github.com/devfile/devworkspace-operator/controllers/controller/devworkspacerout
|
||||||
github.com/devfile/devworkspace-operator/internal/map
|
github.com/devfile/devworkspace-operator/internal/map
|
||||||
github.com/devfile/devworkspace-operator/pkg/common
|
github.com/devfile/devworkspace-operator/pkg/common
|
||||||
github.com/devfile/devworkspace-operator/pkg/config
|
github.com/devfile/devworkspace-operator/pkg/config
|
||||||
|
github.com/devfile/devworkspace-operator/pkg/config/configmap
|
||||||
github.com/devfile/devworkspace-operator/pkg/constants
|
github.com/devfile/devworkspace-operator/pkg/constants
|
||||||
github.com/devfile/devworkspace-operator/pkg/infrastructure
|
github.com/devfile/devworkspace-operator/pkg/infrastructure
|
||||||
|
github.com/devfile/devworkspace-operator/pkg/provision/sync
|
||||||
# github.com/dgrijalva/jwt-go v3.2.0+incompatible => github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
# github.com/dgrijalva/jwt-go v3.2.0+incompatible => github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
github.com/dgrijalva/jwt-go
|
github.com/dgrijalva/jwt-go
|
||||||
# github.com/evanphx/json-patch v4.11.0+incompatible => github.com/evanphx/json-patch v4.11.0+incompatible
|
# github.com/evanphx/json-patch v4.11.0+incompatible => github.com/evanphx/json-patch v4.11.0+incompatible
|
||||||
|
|
@ -886,7 +888,7 @@ sigs.k8s.io/yaml
|
||||||
# github.com/huandu/xstrings => github.com/huandu/xstrings v1.2.0
|
# github.com/huandu/xstrings => github.com/huandu/xstrings v1.2.0
|
||||||
# github.com/imdario/mergo => github.com/imdario/mergo v0.3.5
|
# github.com/imdario/mergo => github.com/imdario/mergo v0.3.5
|
||||||
# github.com/inconshreveable/mousetrap => github.com/inconshreveable/mousetrap v1.0.0
|
# github.com/inconshreveable/mousetrap => github.com/inconshreveable/mousetrap v1.0.0
|
||||||
# github.com/irifrance/gini => github.com/irifrance/gini v1.0.1
|
# github.com/irifrance/gini => github.com/go-air/gini v1.0.1
|
||||||
# github.com/itchyny/astgen-go => github.com/itchyny/astgen-go v0.0.0-20200519013840-cf3ea398f645
|
# github.com/itchyny/astgen-go => github.com/itchyny/astgen-go v0.0.0-20200519013840-cf3ea398f645
|
||||||
# github.com/itchyny/go-flags => github.com/itchyny/go-flags v1.5.0
|
# github.com/itchyny/go-flags => github.com/itchyny/go-flags v1.5.0
|
||||||
# github.com/itchyny/gojq => github.com/itchyny/gojq v0.11.0
|
# github.com/itchyny/gojq => github.com/itchyny/gojq v0.11.0
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue