mirror of https://github.com/linkerd/linkerd2.git
destination: pass opaque-ports through cmd flag (#5829)
* destination: pass opaque-ports through cmd flag Fixes #5817 Currently, Default opaque ports are stored at two places i.e `Values.yaml` and also at `opaqueports/defaults.go`. As these ports are used only in destination, We can instead pass these values as a cmd flag for destination component from Values.yaml and remove defaultPorts in `defaults.go`. This means that users if they override `Values.yaml`'s opauePorts field, That change is propogated both for injection and also discovery like expected. Signed-off-by: Tarun Pothulapati <tarunpothulapati@outlook.com>
This commit is contained in:
parent
069162854f
commit
5c1a375a51
|
@ -119,6 +119,7 @@ spec:
|
|||
- -enable-endpoint-slices={{.Values.enableEndpointSlices}}
|
||||
- -cluster-domain={{.Values.clusterDomain}}
|
||||
- -identity-trust-domain={{.Values.identityTrustDomain | default .Values.clusterDomain}}
|
||||
- -default-opaque-ports={{.Values.proxy.opaquePorts}}
|
||||
{{- include "partials.linkerd.trace" . | nindent 8 -}}
|
||||
image: {{.Values.controllerImage}}:{{default .Values.linkerdVersion .Values.controllerImageVersion}}
|
||||
imagePullPolicy: {{.Values.imagePullPolicy}}
|
||||
|
|
|
@ -78,7 +78,8 @@ func TestRender(t *testing.T) {
|
|||
Inbound: 4143,
|
||||
Outbound: 4140,
|
||||
},
|
||||
UID: 2102,
|
||||
UID: 2102,
|
||||
OpaquePorts: "25,443,587,3306,5432,11211",
|
||||
},
|
||||
ProxyInit: &charts.ProxyInit{
|
||||
Image: &charts.Image{
|
||||
|
|
|
@ -1619,6 +1619,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=cluster.local
|
||||
- -identity-trust-domain=cluster.local
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
- -trace-collector=collector.linkerd-jaeger.svc.cluster.local:55678
|
||||
image: cr.l5d.io/linkerd/controller:install-control-plane-version
|
||||
imagePullPolicy: IfNotPresent
|
||||
|
|
|
@ -1617,6 +1617,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=cluster.local
|
||||
- -identity-trust-domain=cluster.local
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
image: cr.l5d.io/linkerd/controller:install-control-plane-version
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
|
|
|
@ -1617,6 +1617,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=cluster.local
|
||||
- -identity-trust-domain=cluster.local
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
image: my.custom.registry/linkerd-io/controller:install-control-plane-version
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
|
|
|
@ -1617,6 +1617,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=cluster.local
|
||||
- -identity-trust-domain=cluster.local
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
image: cr.l5d.io/linkerd/controller:install-control-plane-version
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
|
|
|
@ -1617,6 +1617,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=cluster.local
|
||||
- -identity-trust-domain=cluster.local
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
image: cr.l5d.io/linkerd/controller:install-control-plane-version
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
|
|
|
@ -1792,6 +1792,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=cluster.local
|
||||
- -identity-trust-domain=cluster.local
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
image: cr.l5d.io/linkerd/controller:install-control-plane-version
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
|
|
|
@ -1792,6 +1792,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=cluster.local
|
||||
- -identity-trust-domain=cluster.local
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
image: cr.l5d.io/linkerd/controller:install-control-plane-version
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
|
|
|
@ -1545,6 +1545,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=cluster.local
|
||||
- -identity-trust-domain=cluster.local
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
image: cr.l5d.io/linkerd/controller:install-control-plane-version
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
|
|
|
@ -1603,6 +1603,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=cluster.local
|
||||
- -identity-trust-domain=test.trust.domain
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
image: cr.l5d.io/linkerd/controller:linkerd-version
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
|
|
|
@ -1778,6 +1778,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=cluster.local
|
||||
- -identity-trust-domain=test.trust.domain
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
image: cr.l5d.io/linkerd/controller:linkerd-version
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
|
|
|
@ -1794,6 +1794,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=cluster.local
|
||||
- -identity-trust-domain=test.trust.domain
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
image: cr.l5d.io/linkerd/controller:linkerd-version
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
|
|
|
@ -1778,6 +1778,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=cluster.local
|
||||
- -identity-trust-domain=test.trust.domain
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
image: cr.l5d.io/linkerd/controller:linkerd-version
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
|
|
|
@ -1538,6 +1538,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=cluster.local
|
||||
- -identity-trust-domain=cluster.local
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
image: cr.l5d.io/linkerd/controller:install-control-plane-version
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
|
|
|
@ -966,7 +966,7 @@ data:
|
|||
isIngress: false
|
||||
logFormat: plain
|
||||
logLevel: warn,linkerd=info
|
||||
opaquePorts: ""
|
||||
opaquePorts: 25,443,587,3306,5432,11211
|
||||
outboundConnectTimeout: ""
|
||||
ports:
|
||||
admin: 4191
|
||||
|
@ -1177,6 +1177,8 @@ spec:
|
|||
value: 10000ms
|
||||
- name: LINKERD2_PROXY_OUTBOUND_CONNECT_KEEPALIVE
|
||||
value: 10000ms
|
||||
- name: LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION
|
||||
value: "25,443,587,3306,5432,11211"
|
||||
- name: _pod_ns
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
|
@ -1409,6 +1411,8 @@ spec:
|
|||
value: 10000ms
|
||||
- name: LINKERD2_PROXY_OUTBOUND_CONNECT_KEEPALIVE
|
||||
value: 10000ms
|
||||
- name: LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION
|
||||
value: "25,443,587,3306,5432,11211"
|
||||
- name: _pod_ns
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
|
@ -1617,6 +1621,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=cluster.local
|
||||
- -identity-trust-domain=cluster.local
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
image: ControllerImage:ControllerImageVersion
|
||||
imagePullPolicy: ImagePullPolicy
|
||||
livenessProbe:
|
||||
|
@ -1660,6 +1665,8 @@ spec:
|
|||
value: 10000ms
|
||||
- name: LINKERD2_PROXY_OUTBOUND_CONNECT_KEEPALIVE
|
||||
value: 10000ms
|
||||
- name: LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION
|
||||
value: "25,443,587,3306,5432,11211"
|
||||
- name: _pod_ns
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
|
@ -1921,6 +1928,8 @@ spec:
|
|||
value: 10000ms
|
||||
- name: LINKERD2_PROXY_OUTBOUND_CONNECT_KEEPALIVE
|
||||
value: 10000ms
|
||||
- name: LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION
|
||||
value: "25,443,587,3306,5432,11211"
|
||||
- name: _pod_ns
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
|
@ -2175,6 +2184,8 @@ spec:
|
|||
value: 10000ms
|
||||
- name: LINKERD2_PROXY_OUTBOUND_CONNECT_KEEPALIVE
|
||||
value: 10000ms
|
||||
- name: LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION
|
||||
value: "25,443,587,3306,5432,11211"
|
||||
- name: _pod_ns
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
|
@ -2302,7 +2313,7 @@ spec:
|
|||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
linkerd-config-overrides: Y2xpVmVyc2lvbjogQ2xpVmVyc2lvbgpjbHVzdGVyTmV0d29ya3M6IENsdXN0ZXJOZXR3b3Jrcwpjb250cm9sUGxhbmVUcmFjaW5nTmFtZXNwYWNlOiAiIgpjb250cm9sbGVySW1hZ2U6IENvbnRyb2xsZXJJbWFnZQpjb250cm9sbGVySW1hZ2VWZXJzaW9uOiBDb250cm9sbGVySW1hZ2VWZXJzaW9uCmNvbnRyb2xsZXJMb2dGb3JtYXQ6IENvbnRyb2xsZXJMb2dGb3JtYXQKY29udHJvbGxlckxvZ0xldmVsOiBDb250cm9sbGVyTG9nTGV2ZWwKZGVidWdDb250YWluZXI6CiAgaW1hZ2U6CiAgICBuYW1lOiBEZWJ1Z0ltYWdlTmFtZQogICAgcHVsbFBvbGljeTogRGVidWdJbWFnZVB1bGxQb2xpY3kKICAgIHZlcnNpb246IERlYnVnVmVyc2lvbgpoZWFydGJlYXRTY2hlZHVsZTogIiIKaWRlbnRpdHk6CiAgaXNzdWVyOgogICAgY3J0RXhwaXJ5OiAiMjAzMC0wOC0yNlQwNzoxMzo0N1oiCiAgICB0bHM6CiAgICAgIGNydFBFTTogfAogICAgICAgIC0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQogICAgICAgIE1JSUJ3RENDQVdlZ0F3SUJBZ0lSQUpSSWdaOFJ0TzhFd2cxWGVwZjhUNDR3Q2dZSUtvWkl6ajBFQXdJd0tURW4KICAgICAgICBNQ1VHQTFVRUF4TWVhV1JsYm5ScGRIa3ViR2x1YTJWeVpDNWpiSFZ6ZEdWeUxteHZZMkZzTUI0WERUSXdNRGd5CiAgICAgICAgT0RBM01UTTBOMW9YRFRNd01EZ3lOakEzTVRNME4xb3dLVEVuTUNVR0ExVUVBeE1lYVdSbGJuUnBkSGt1YkdsdQogICAgICAgIGEyVnlaQzVqYkhWemRHVnlMbXh2WTJGc01Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTEvRnAKICAgICAgICBmY1JuRGNlZEw2QWpVYVhZUHY0RElNQmFKdWZPSTVOV3R5K1hTWDdKalhnWnRNNzJkUXZSYVlhbnV4RDM2RHQxCiAgICAgICAgMi9KeHlpU2d4S1dSZG9heSthTndNRzR3RGdZRFZSMFBBUUgvQkFRREFnRUdNQklHQTFVZEV3RUIvd1FJTUFZQgogICAgICAgIEFmOENBUUF3SFFZRFZSME9CQllFRkkxV25ycU1ZS2FISE9vK3pweWlpRHEycE8wS01Da0dBMVVkRVFRaU1DQ0MKICAgICAgICBIbWxrWlc1MGFYUjVMbXhwYm10bGNtUXVZMngxYzNSbGNpNXNiMk5oYkRBS0JnZ3Foa2pPUFFRREFnTkhBREJFCiAgICAgICAgQWlBdHVvSTVYdUN0ckdWUnpTbVJUbDJyYTI4YVY5TXlUVTdkNXFuVEFGSEtTZ0lnUktDdmx1T1NnQTVPMjFwNQogICAgICAgIDUxdGRybWtIRVpScjBxbExTSmRIWWdFZk16az0KICAgICAgICAtLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCiAgICAgIGtleVBFTTogfAogICAgICAgIC0tLS0tQkVHSU4gRUMgUFJJVkFURSBLRVktLS0tLQogICAgICAgIE1IY0NBUUVFSUFBZThuZmJ6WnU5Yy9PQjIrOHhKTTBGejdOVXdUUWF6dWxrRk5zNFRJNStvQW9HQ0NxR1NNNDkKICAgICAgICBBd0VIb1VRRFFnQUUxL0ZwZmNSbkRjZWRMNkFqVWFYWVB2NERJTUJhSnVmT0k1Tld0eStYU1g3SmpYZ1p0TTcyCiAgICAgICAgZFF2UmFZYW51eEQzNkR0MTIvSnh5aVNneEtXUmRvYXkrUT09CiAgICAgICAgLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQppZGVudGl0eVRydXN0QW5jaG9yc1BFTTogfAogIC0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQogIE1JSUJ3VENDQVdhZ0F3SUJBZ0lRZURacDVsRGFJeWdRNVVmTUtackZBVEFLQmdncWhrak9QUVFEQWpBcE1TY3cKICBKUVlEVlFRREV4NXBaR1Z1ZEdsMGVTNXNhVzVyWlhKa0xtTnNkWE4wWlhJdWJHOWpZV3d3SGhjTk1qQXdPREk0CiAgTURjeE1qUTNXaGNOTXpBd09ESTJNRGN4TWpRM1dqQXBNU2N3SlFZRFZRUURFeDVwWkdWdWRHbDBlUzVzYVc1cgogIFpYSmtMbU5zZFhOMFpYSXViRzlqWVd3d1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFScWM3MFoKICBsMXZndzc5cmpCNXVTSVRJQ1VBNkd5ZnZTRmZjdUlpczdCL1hGU2trd0FIVTVTL3MxQUFQK1IwVFg3SEJXVUM0CiAgdWFHNFdXc2l3SktObjdtZ28zQXdiakFPQmdOVkhROEJBZjhFQkFNQ0FRWXdFZ1lEVlIwVEFRSC9CQWd3QmdFQgogIC93SUJBVEFkQmdOVkhRNEVGZ1FVNVl0alZWUGZkN0k3TkxIc24yQzI2RUJ5R1Ywd0tRWURWUjBSQkNJd0lJSWUKICBhV1JsYm5ScGRIa3ViR2x1YTJWeVpDNWpiSFZ6ZEdWeUxteHZZMkZzTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDCiAgSVFDTjdsQkZMRER2ang2VjArWGtqcEtFUlJzSllmNWFkTXZubG9GbDQ4aWxKZ0loQU50eGhuZGNyK1FKUHVDOAogIHZnVUMwZDIvOUZNdWVJVk1iKzQ2V1RDT2pzcXIKICAtLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCmltYWdlUHVsbFBvbGljeTogSW1hZ2VQdWxsUG9saWN5CmltYWdlUHVsbFNlY3JldHM6IG51bGwKbGlua2VyZFZlcnNpb246ICIiCnByb2ZpbGVWYWxpZGF0b3I6CiAgY2FCdW5kbGU6IHByb2ZpbGUgdmFsaWRhdG9yIENBIGJ1bmRsZQogIGNydFBFTTogcHJvZmlsZSB2YWxpZGF0b3IgY3J0CiAga2V5UEVNOiBwcm9maWxlIHZhbGlkYXRvciBrZXkKcHJveHk6CiAgaW1hZ2U6CiAgICBuYW1lOiBQcm94eUltYWdlTmFtZQogICAgcHVsbFBvbGljeTogSW1hZ2VQdWxsUG9saWN5CiAgICB2ZXJzaW9uOiBQcm94eVZlcnNpb24KICBpbmJvdW5kQ29ubmVjdFRpbWVvdXQ6ICIiCiAgb3BhcXVlUG9ydHM6ICIiCiAgb3V0Ym91bmRDb25uZWN0VGltZW91dDogIiIKICByZXNvdXJjZXM6CiAgICBjcHU6CiAgICAgIGxpbWl0OiBjcHUtbGltaXQKICAgICAgcmVxdWVzdDogY3B1LXJlcXVlc3QKICAgIG1lbW9yeToKICAgICAgbGltaXQ6IG1lbW9yeS1saW1pdAogICAgICByZXF1ZXN0OiBtZW1vcnktcmVxdWVzdApwcm94eUNvbnRhaW5lck5hbWU6IFByb3h5Q29udGFpbmVyTmFtZQpwcm94eUluaXQ6CiAgaWdub3JlT3V0Ym91bmRQb3J0czogIjQ0MyIKICBpbWFnZToKICAgIG5hbWU6IFByb3h5SW5pdEltYWdlTmFtZQogICAgcHVsbFBvbGljeTogSW1hZ2VQdWxsUG9saWN5CiAgICB2ZXJzaW9uOiBQcm94eUluaXRWZXJzaW9uCnByb3h5SW5qZWN0b3I6CiAgY2FCdW5kbGU6IHByb3h5IGluamVjdG9yIENBIGJ1bmRsZQogIGNydFBFTTogcHJveHkgaW5qZWN0b3IgY3J0CiAga2V5UEVNOiBwcm94eSBpbmplY3RvciBrZXkKd2ViaG9va0ZhaWx1cmVQb2xpY3k6IFdlYmhvb2tGYWlsdXJlUG9saWN5Cg==
|
||||
linkerd-config-overrides: Y2xpVmVyc2lvbjogQ2xpVmVyc2lvbgpjbHVzdGVyTmV0d29ya3M6IENsdXN0ZXJOZXR3b3Jrcwpjb250cm9sUGxhbmVUcmFjaW5nTmFtZXNwYWNlOiAiIgpjb250cm9sbGVySW1hZ2U6IENvbnRyb2xsZXJJbWFnZQpjb250cm9sbGVySW1hZ2VWZXJzaW9uOiBDb250cm9sbGVySW1hZ2VWZXJzaW9uCmNvbnRyb2xsZXJMb2dGb3JtYXQ6IENvbnRyb2xsZXJMb2dGb3JtYXQKY29udHJvbGxlckxvZ0xldmVsOiBDb250cm9sbGVyTG9nTGV2ZWwKZGVidWdDb250YWluZXI6CiAgaW1hZ2U6CiAgICBuYW1lOiBEZWJ1Z0ltYWdlTmFtZQogICAgcHVsbFBvbGljeTogRGVidWdJbWFnZVB1bGxQb2xpY3kKICAgIHZlcnNpb246IERlYnVnVmVyc2lvbgpoZWFydGJlYXRTY2hlZHVsZTogIiIKaWRlbnRpdHk6CiAgaXNzdWVyOgogICAgY3J0RXhwaXJ5OiAiMjAzMC0wOC0yNlQwNzoxMzo0N1oiCiAgICB0bHM6CiAgICAgIGNydFBFTTogfAogICAgICAgIC0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQogICAgICAgIE1JSUJ3RENDQVdlZ0F3SUJBZ0lSQUpSSWdaOFJ0TzhFd2cxWGVwZjhUNDR3Q2dZSUtvWkl6ajBFQXdJd0tURW4KICAgICAgICBNQ1VHQTFVRUF4TWVhV1JsYm5ScGRIa3ViR2x1YTJWeVpDNWpiSFZ6ZEdWeUxteHZZMkZzTUI0WERUSXdNRGd5CiAgICAgICAgT0RBM01UTTBOMW9YRFRNd01EZ3lOakEzTVRNME4xb3dLVEVuTUNVR0ExVUVBeE1lYVdSbGJuUnBkSGt1YkdsdQogICAgICAgIGEyVnlaQzVqYkhWemRHVnlMbXh2WTJGc01Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTEvRnAKICAgICAgICBmY1JuRGNlZEw2QWpVYVhZUHY0RElNQmFKdWZPSTVOV3R5K1hTWDdKalhnWnRNNzJkUXZSYVlhbnV4RDM2RHQxCiAgICAgICAgMi9KeHlpU2d4S1dSZG9heSthTndNRzR3RGdZRFZSMFBBUUgvQkFRREFnRUdNQklHQTFVZEV3RUIvd1FJTUFZQgogICAgICAgIEFmOENBUUF3SFFZRFZSME9CQllFRkkxV25ycU1ZS2FISE9vK3pweWlpRHEycE8wS01Da0dBMVVkRVFRaU1DQ0MKICAgICAgICBIbWxrWlc1MGFYUjVMbXhwYm10bGNtUXVZMngxYzNSbGNpNXNiMk5oYkRBS0JnZ3Foa2pPUFFRREFnTkhBREJFCiAgICAgICAgQWlBdHVvSTVYdUN0ckdWUnpTbVJUbDJyYTI4YVY5TXlUVTdkNXFuVEFGSEtTZ0lnUktDdmx1T1NnQTVPMjFwNQogICAgICAgIDUxdGRybWtIRVpScjBxbExTSmRIWWdFZk16az0KICAgICAgICAtLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCiAgICAgIGtleVBFTTogfAogICAgICAgIC0tLS0tQkVHSU4gRUMgUFJJVkFURSBLRVktLS0tLQogICAgICAgIE1IY0NBUUVFSUFBZThuZmJ6WnU5Yy9PQjIrOHhKTTBGejdOVXdUUWF6dWxrRk5zNFRJNStvQW9HQ0NxR1NNNDkKICAgICAgICBBd0VIb1VRRFFnQUUxL0ZwZmNSbkRjZWRMNkFqVWFYWVB2NERJTUJhSnVmT0k1Tld0eStYU1g3SmpYZ1p0TTcyCiAgICAgICAgZFF2UmFZYW51eEQzNkR0MTIvSnh5aVNneEtXUmRvYXkrUT09CiAgICAgICAgLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQppZGVudGl0eVRydXN0QW5jaG9yc1BFTTogfAogIC0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQogIE1JSUJ3VENDQVdhZ0F3SUJBZ0lRZURacDVsRGFJeWdRNVVmTUtackZBVEFLQmdncWhrak9QUVFEQWpBcE1TY3cKICBKUVlEVlFRREV4NXBaR1Z1ZEdsMGVTNXNhVzVyWlhKa0xtTnNkWE4wWlhJdWJHOWpZV3d3SGhjTk1qQXdPREk0CiAgTURjeE1qUTNXaGNOTXpBd09ESTJNRGN4TWpRM1dqQXBNU2N3SlFZRFZRUURFeDVwWkdWdWRHbDBlUzVzYVc1cgogIFpYSmtMbU5zZFhOMFpYSXViRzlqWVd3d1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFScWM3MFoKICBsMXZndzc5cmpCNXVTSVRJQ1VBNkd5ZnZTRmZjdUlpczdCL1hGU2trd0FIVTVTL3MxQUFQK1IwVFg3SEJXVUM0CiAgdWFHNFdXc2l3SktObjdtZ28zQXdiakFPQmdOVkhROEJBZjhFQkFNQ0FRWXdFZ1lEVlIwVEFRSC9CQWd3QmdFQgogIC93SUJBVEFkQmdOVkhRNEVGZ1FVNVl0alZWUGZkN0k3TkxIc24yQzI2RUJ5R1Ywd0tRWURWUjBSQkNJd0lJSWUKICBhV1JsYm5ScGRIa3ViR2x1YTJWeVpDNWpiSFZ6ZEdWeUxteHZZMkZzTUFvR0NDcUdTTTQ5QkFNQ0Ewa0FNRVlDCiAgSVFDTjdsQkZMRER2ang2VjArWGtqcEtFUlJzSllmNWFkTXZubG9GbDQ4aWxKZ0loQU50eGhuZGNyK1FKUHVDOAogIHZnVUMwZDIvOUZNdWVJVk1iKzQ2V1RDT2pzcXIKICAtLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCmltYWdlUHVsbFBvbGljeTogSW1hZ2VQdWxsUG9saWN5CmltYWdlUHVsbFNlY3JldHM6IG51bGwKbGlua2VyZFZlcnNpb246ICIiCnByb2ZpbGVWYWxpZGF0b3I6CiAgY2FCdW5kbGU6IHByb2ZpbGUgdmFsaWRhdG9yIENBIGJ1bmRsZQogIGNydFBFTTogcHJvZmlsZSB2YWxpZGF0b3IgY3J0CiAga2V5UEVNOiBwcm9maWxlIHZhbGlkYXRvciBrZXkKcHJveHk6CiAgaW1hZ2U6CiAgICBuYW1lOiBQcm94eUltYWdlTmFtZQogICAgcHVsbFBvbGljeTogSW1hZ2VQdWxsUG9saWN5CiAgICB2ZXJzaW9uOiBQcm94eVZlcnNpb24KICBpbmJvdW5kQ29ubmVjdFRpbWVvdXQ6ICIiCiAgb3V0Ym91bmRDb25uZWN0VGltZW91dDogIiIKICByZXNvdXJjZXM6CiAgICBjcHU6CiAgICAgIGxpbWl0OiBjcHUtbGltaXQKICAgICAgcmVxdWVzdDogY3B1LXJlcXVlc3QKICAgIG1lbW9yeToKICAgICAgbGltaXQ6IG1lbW9yeS1saW1pdAogICAgICByZXF1ZXN0OiBtZW1vcnktcmVxdWVzdApwcm94eUNvbnRhaW5lck5hbWU6IFByb3h5Q29udGFpbmVyTmFtZQpwcm94eUluaXQ6CiAgaWdub3JlT3V0Ym91bmRQb3J0czogIjQ0MyIKICBpbWFnZToKICAgIG5hbWU6IFByb3h5SW5pdEltYWdlTmFtZQogICAgcHVsbFBvbGljeTogSW1hZ2VQdWxsUG9saWN5CiAgICB2ZXJzaW9uOiBQcm94eUluaXRWZXJzaW9uCnByb3h5SW5qZWN0b3I6CiAgY2FCdW5kbGU6IHByb3h5IGluamVjdG9yIENBIGJ1bmRsZQogIGNydFBFTTogcHJveHkgaW5qZWN0b3IgY3J0CiAga2V5UEVNOiBwcm94eSBpbmplY3RvciBrZXkKd2ViaG9va0ZhaWx1cmVQb2xpY3k6IFdlYmhvb2tGYWlsdXJlUG9saWN5Cg==
|
||||
kind: Secret
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
|
|
|
@ -1617,6 +1617,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=cluster.local
|
||||
- -identity-trust-domain=cluster.local
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
image: cr.l5d.io/linkerd/controller:install-control-plane-version
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
|
|
|
@ -1603,6 +1603,7 @@ spec:
|
|||
- -enable-endpoint-slices=false
|
||||
- -cluster-domain=example.com
|
||||
- -identity-trust-domain=example.com
|
||||
- -default-opaque-ports=25,443,587,3306,5432,11211
|
||||
image: cr.l5d.io/linkerd/controller:install-control-plane-version
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/linkerd/linkerd2/controller/api/destination/watcher"
|
||||
"github.com/linkerd/linkerd2/pkg/addr"
|
||||
"github.com/linkerd/linkerd2/pkg/k8s"
|
||||
"github.com/linkerd/linkerd2/pkg/opaqueports"
|
||||
logging "github.com/sirupsen/logrus"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
coreinformers "k8s.io/client-go/informers/core/v1"
|
||||
|
@ -30,6 +29,7 @@ type endpointTranslator struct {
|
|||
identityTrustDomain string
|
||||
enableH2Upgrade bool
|
||||
nodeTopologyLabels map[string]string
|
||||
defaultOpaquePorts map[uint32]struct{}
|
||||
|
||||
availableEndpoints watcher.AddressSet
|
||||
filteredSnapshot watcher.AddressSet
|
||||
|
@ -43,6 +43,7 @@ func newEndpointTranslator(
|
|||
enableH2Upgrade bool,
|
||||
service string,
|
||||
srcNodeName string,
|
||||
defaultOpaquePorts map[uint32]struct{},
|
||||
nodes coreinformers.NodeInformer,
|
||||
stream pb.Destination_GetServer,
|
||||
log *logging.Entry,
|
||||
|
@ -65,6 +66,7 @@ func newEndpointTranslator(
|
|||
identityTrustDomain,
|
||||
enableH2Upgrade,
|
||||
nodeTopologyLabels,
|
||||
defaultOpaquePorts,
|
||||
availableEndpoints,
|
||||
filteredSnapshot,
|
||||
stream,
|
||||
|
@ -221,7 +223,7 @@ func (et *endpointTranslator) sendClientAdd(set watcher.AddressSet) {
|
|||
// If the opaque ports annotation was not set, then set the
|
||||
// endpoint's opaque ports to the default value.
|
||||
if !ok {
|
||||
opaquePorts = opaqueports.DefaultOpaquePorts
|
||||
opaquePorts = et.defaultOpaquePorts
|
||||
}
|
||||
wa, err = toWeightedAddr(address, opaquePorts, et.enableH2Upgrade, et.identityTrustDomain, et.controllerNS, et.log)
|
||||
} else {
|
||||
|
|
|
@ -146,6 +146,7 @@ metadata:
|
|||
true,
|
||||
"service-name.service-ns",
|
||||
"test-123",
|
||||
map[uint32]struct{}{},
|
||||
k8sAPI.Node(),
|
||||
mockGetServer,
|
||||
logging.WithField("test", t.Name()),
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
sp "github.com/linkerd/linkerd2/controller/gen/apis/serviceprofile/v1alpha2"
|
||||
"github.com/linkerd/linkerd2/controller/k8s"
|
||||
labels "github.com/linkerd/linkerd2/pkg/k8s"
|
||||
"github.com/linkerd/linkerd2/pkg/opaqueports"
|
||||
"github.com/linkerd/linkerd2/pkg/prometheus"
|
||||
"github.com/linkerd/linkerd2/pkg/util"
|
||||
logging "github.com/sirupsen/logrus"
|
||||
|
@ -37,6 +36,7 @@ type (
|
|||
controllerNS string
|
||||
identityTrustDomain string
|
||||
clusterDomain string
|
||||
defaultOpaquePorts map[uint32]struct{}
|
||||
|
||||
k8sAPI *k8s.API
|
||||
log *logging.Entry
|
||||
|
@ -64,14 +64,16 @@ func NewServer(
|
|||
enableEndpointSlices bool,
|
||||
k8sAPI *k8s.API,
|
||||
clusterDomain string,
|
||||
defaultOpaquePorts map[uint32]struct{},
|
||||
shutdown <-chan struct{},
|
||||
) *grpc.Server {
|
||||
log := logging.WithFields(logging.Fields{
|
||||
"addr": addr,
|
||||
"component": "server",
|
||||
})
|
||||
|
||||
endpoints := watcher.NewEndpointsWatcher(k8sAPI, log, enableEndpointSlices)
|
||||
opaquePorts := watcher.NewOpaquePortsWatcher(k8sAPI, log)
|
||||
opaquePorts := watcher.NewOpaquePortsWatcher(k8sAPI, log, defaultOpaquePorts)
|
||||
profiles := watcher.NewProfileWatcher(k8sAPI, log)
|
||||
trafficSplits := watcher.NewTrafficSplitWatcher(k8sAPI, log)
|
||||
ips := watcher.NewIPWatcher(k8sAPI, endpoints, log)
|
||||
|
@ -87,6 +89,7 @@ func NewServer(
|
|||
controllerNS,
|
||||
identityTrustDomain,
|
||||
clusterDomain,
|
||||
defaultOpaquePorts,
|
||||
k8sAPI,
|
||||
log,
|
||||
shutdown,
|
||||
|
@ -118,6 +121,7 @@ func (s *server) Get(dest *pb.GetDestination, stream pb.Destination_GetServer) e
|
|||
s.enableH2Upgrade,
|
||||
dest.GetPath(),
|
||||
token.NodeName,
|
||||
s.defaultOpaquePorts,
|
||||
s.nodes,
|
||||
stream,
|
||||
log,
|
||||
|
@ -225,7 +229,7 @@ func (s *server) GetProfile(dest *pb.GetDestination, stream pb.Destination_GetPr
|
|||
// If the opaque ports annotation was not set, then set the
|
||||
// endpoint's opaque ports to the default value.
|
||||
if !ok {
|
||||
opaquePorts = opaqueports.DefaultOpaquePorts
|
||||
opaquePorts = s.defaultOpaquePorts
|
||||
}
|
||||
endpoint, err = toWeightedAddr(podSet.Addresses[podID], opaquePorts, s.enableH2Upgrade, s.identityTrustDomain, s.controllerNS, log)
|
||||
if err != nil {
|
||||
|
|
|
@ -217,9 +217,17 @@ metadata:
|
|||
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
||||
}
|
||||
log := logging.WithField("test", t.Name())
|
||||
defaultOpaquePorts := map[uint32]struct{}{
|
||||
25: {},
|
||||
443: {},
|
||||
587: {},
|
||||
3306: {},
|
||||
5432: {},
|
||||
11211: {},
|
||||
}
|
||||
|
||||
endpoints := watcher.NewEndpointsWatcher(k8sAPI, log, false)
|
||||
opaquePorts := watcher.NewOpaquePortsWatcher(k8sAPI, log)
|
||||
opaquePorts := watcher.NewOpaquePortsWatcher(k8sAPI, log, defaultOpaquePorts)
|
||||
profiles := watcher.NewProfileWatcher(k8sAPI, log)
|
||||
trafficSplits := watcher.NewTrafficSplitWatcher(k8sAPI, log)
|
||||
ips := watcher.NewIPWatcher(k8sAPI, endpoints, log)
|
||||
|
@ -239,6 +247,7 @@ metadata:
|
|||
"linkerd",
|
||||
"trust.domain",
|
||||
"mycluster.local",
|
||||
defaultOpaquePorts,
|
||||
k8sAPI,
|
||||
log,
|
||||
make(<-chan struct{}),
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"github.com/linkerd/linkerd2-proxy-init/ports"
|
||||
"github.com/linkerd/linkerd2/controller/k8s"
|
||||
labels "github.com/linkerd/linkerd2/pkg/k8s"
|
||||
"github.com/linkerd/linkerd2/pkg/opaqueports"
|
||||
"github.com/linkerd/linkerd2/pkg/util"
|
||||
log "github.com/sirupsen/logrus"
|
||||
logging "github.com/sirupsen/logrus"
|
||||
|
@ -20,9 +19,10 @@ type (
|
|||
// opaque ports annotation is added to a service, the watcher will update
|
||||
// listeners—if any—subscribed to that service.
|
||||
OpaquePortsWatcher struct {
|
||||
subscriptions map[ServiceID]*svcSubscriptions
|
||||
k8sAPI *k8s.API
|
||||
log *logging.Entry
|
||||
subscriptions map[ServiceID]*svcSubscriptions
|
||||
k8sAPI *k8s.API
|
||||
log *logging.Entry
|
||||
defaultOpaquePorts map[uint32]struct{}
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
|
@ -39,11 +39,12 @@ type (
|
|||
|
||||
// NewOpaquePortsWatcher creates a OpaquePortsWatcher and begins watching for
|
||||
// k8sAPI for service changes.
|
||||
func NewOpaquePortsWatcher(k8sAPI *k8s.API, log *logging.Entry) *OpaquePortsWatcher {
|
||||
func NewOpaquePortsWatcher(k8sAPI *k8s.API, log *logging.Entry, opaquePorts map[uint32]struct{}) *OpaquePortsWatcher {
|
||||
opw := &OpaquePortsWatcher{
|
||||
subscriptions: make(map[ServiceID]*svcSubscriptions),
|
||||
k8sAPI: k8sAPI,
|
||||
log: log.WithField("component", "opaque-ports-watcher"),
|
||||
subscriptions: make(map[ServiceID]*svcSubscriptions),
|
||||
k8sAPI: k8sAPI,
|
||||
log: log.WithField("component", "opaque-ports-watcher"),
|
||||
defaultOpaquePorts: opaquePorts,
|
||||
}
|
||||
k8sAPI.Svc().Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: opw.addService,
|
||||
|
@ -69,7 +70,7 @@ func (opw *OpaquePortsWatcher) Subscribe(id ServiceID, listener OpaquePortsUpdat
|
|||
// and no opaque ports
|
||||
if !ok {
|
||||
opw.subscriptions[id] = &svcSubscriptions{
|
||||
opaquePorts: opaqueports.DefaultOpaquePorts,
|
||||
opaquePorts: opw.defaultOpaquePorts,
|
||||
listeners: []OpaquePortsUpdateListener{listener},
|
||||
}
|
||||
return nil
|
||||
|
@ -121,7 +122,7 @@ func (opw *OpaquePortsWatcher) addService(obj interface{}) {
|
|||
// If the opaque ports annotation was not set, then set the service's
|
||||
// opaque ports to the default value.
|
||||
if !ok {
|
||||
opaquePorts = opaqueports.DefaultOpaquePorts
|
||||
opaquePorts = opw.defaultOpaquePorts
|
||||
}
|
||||
ss, ok := opw.subscriptions[id]
|
||||
// If there are no subscriptions for this service, create one with the
|
||||
|
@ -172,7 +173,7 @@ func (opw *OpaquePortsWatcher) deleteService(obj interface{}) {
|
|||
return
|
||||
}
|
||||
old := ss.opaquePorts
|
||||
ss.opaquePorts = opaqueports.DefaultOpaquePorts
|
||||
ss.opaquePorts = opw.defaultOpaquePorts
|
||||
// Do not send an update if the service already had the default opaque ports
|
||||
if portsEqual(old, ss.opaquePorts) {
|
||||
return
|
||||
|
|
|
@ -88,6 +88,15 @@ func (bopl *testOpaquePortsListener) UpdateService(ports map[uint32]struct{}) {
|
|||
}
|
||||
|
||||
func TestOpaquePortsWatcher(t *testing.T) {
|
||||
defaultOpaquePorts := map[uint32]struct{}{
|
||||
25: {},
|
||||
443: {},
|
||||
587: {},
|
||||
3306: {},
|
||||
5432: {},
|
||||
11211: {},
|
||||
}
|
||||
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
initialState []string
|
||||
|
@ -176,7 +185,7 @@ func TestOpaquePortsWatcher(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("NewFakeAPI returned an error: %s", err)
|
||||
}
|
||||
watcher := NewOpaquePortsWatcher(k8sAPI, logging.WithField("test", t.Name()))
|
||||
watcher := NewOpaquePortsWatcher(k8sAPI, logging.WithField("test", t.Name()), defaultOpaquePorts)
|
||||
k8sAPI.Sync(nil)
|
||||
listener := newTestOpaquePortsListener()
|
||||
watcher.Subscribe(tt.service, listener)
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/linkerd/linkerd2/pkg/flags"
|
||||
pkgK8s "github.com/linkerd/linkerd2/pkg/k8s"
|
||||
"github.com/linkerd/linkerd2/pkg/trace"
|
||||
"github.com/linkerd/linkerd2/pkg/util"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
@ -30,6 +31,8 @@ func Main(args []string) {
|
|||
enableEndpointSlices := cmd.Bool("enable-endpoint-slices", false, "Enable the usage of EndpointSlice informers and resources")
|
||||
trustDomain := cmd.String("identity-trust-domain", "", "configures the name suffix used for identities")
|
||||
clusterDomain := cmd.String("cluster-domain", "", "kubernetes cluster domain")
|
||||
defaultOpaquePorts := cmd.String("default-opaque-ports", "", "configures the default opaque ports")
|
||||
|
||||
traceCollector := flags.AddTraceFlags(cmd)
|
||||
|
||||
flags.ConfigureAndParse(cmd, args)
|
||||
|
@ -58,6 +61,13 @@ func Main(args []string) {
|
|||
log.Warnf("expected cluster domain through args (falling back to %s)", *clusterDomain)
|
||||
}
|
||||
|
||||
opaquePorts, err := util.ParsePorts(*defaultOpaquePorts)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse opaque Ports %s: %s", *defaultOpaquePorts, err)
|
||||
}
|
||||
|
||||
log.Infof("Using default opaque ports: %v", opaquePorts)
|
||||
|
||||
if *traceCollector != "" {
|
||||
if err := trace.InitializeTracing("linkerd-destination", *traceCollector); err != nil {
|
||||
log.Warnf("failed to initialize tracing: %s", err)
|
||||
|
@ -106,6 +116,7 @@ func Main(args []string) {
|
|||
*enableEndpointSlices,
|
||||
k8sAPI,
|
||||
*clusterDomain,
|
||||
opaquePorts,
|
||||
done,
|
||||
)
|
||||
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
package opaqueports
|
||||
|
||||
// DefaultOpaquePorts is the default list of opaque ports that the destination
|
||||
// server will use to determine whether a destination is an opaque protocol.
|
||||
// When a pod or service already has its own annotation, that value will have
|
||||
// priority of this.
|
||||
//
|
||||
// Note: Keep in sync with proxy.opaquePorts in values.yaml
|
||||
var DefaultOpaquePorts = map[uint32]struct{}{
|
||||
25: {},
|
||||
443: {},
|
||||
587: {},
|
||||
3306: {},
|
||||
5432: {},
|
||||
11211: {},
|
||||
}
|
|
@ -10,6 +10,28 @@ import (
|
|||
corev1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
// ParsePorts parses the given ports string into a map of ports;
|
||||
// this includes converting port ranges into separate ports
|
||||
func ParsePorts(portsString string) (map[uint32]struct{}, error) {
|
||||
opaquePorts := make(map[uint32]struct{})
|
||||
if portsString != "" {
|
||||
portRanges := GetPortRanges(portsString)
|
||||
for _, portRange := range portRanges {
|
||||
pr := portRange.GetPortRange()
|
||||
portsRange, err := ports.ParsePortRange(pr)
|
||||
if err != nil {
|
||||
log.Warnf("Invalid port range [%v]: %s", pr, err)
|
||||
continue
|
||||
}
|
||||
for i := portsRange.LowerBound; i <= portsRange.UpperBound; i++ {
|
||||
opaquePorts[uint32(i)] = struct{}{}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return opaquePorts, nil
|
||||
}
|
||||
|
||||
// ParseContainerOpaquePorts parses the opaque ports annotation into a list of ports;
|
||||
// this includes converting port ranges into separate ports and named ports
|
||||
// into their port number equivalents.
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParsePorts(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ports string
|
||||
result map[uint32]struct{}
|
||||
}{
|
||||
{
|
||||
"25,443,587,3306,5432,11211",
|
||||
map[uint32]struct{}{
|
||||
25: {},
|
||||
443: {},
|
||||
587: {},
|
||||
3306: {},
|
||||
5432: {},
|
||||
11211: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
"25,443-447,3306,5432-5435,11211",
|
||||
map[uint32]struct{}{
|
||||
25: {},
|
||||
443: {},
|
||||
444: {},
|
||||
445: {},
|
||||
446: {},
|
||||
447: {},
|
||||
3306: {},
|
||||
5432: {},
|
||||
5433: {},
|
||||
5434: {},
|
||||
5435: {},
|
||||
11211: {},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc // pin
|
||||
t.Run(fmt.Sprintf("test %s", tc.ports), func(t *testing.T) {
|
||||
ports, err := ParsePorts(tc.ports)
|
||||
if err != nil {
|
||||
t.Fatalf("could not parse ports: %v", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(ports, tc.result) {
|
||||
t.Fatalf("Expected output: \"%v\", got: \"%v\"", tc.result, ports)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue