Skip to content

Comments

[data] Auto-detect --publish flag#286

Open
kkozoriz wants to merge 3 commits intomainfrom
feature/auto-detect-data-publish
Open

[data] Auto-detect --publish flag#286
kkozoriz wants to merge 3 commits intomainfrom
feature/auto-detect-data-publish

Conversation

@kkozoriz
Copy link
Contributor

Description

When --publish is not explicitly provided, the CLI now auto-detects whether the user is inside the target cluster by probing the default/kubernetes service via its ClusterIP.

How it works

  1. Read Service default/kubernetes via the normal kubeconfig endpoint to get its ClusterIP and UID.
  2. Probe the same service directly at https://<ClusterIP>:443 with a short timeout (3s).
  3. Compare UIDs of both responses:
    • Same UID - user is inside the cluster, publish=false.
    • UID mismatch - ClusterIP reached a different cluster (e.g. local minikube/kind), publish=true.
    • Network unreachable / timeout - ClusterIP is not routable from the current environment, publish=true.
    • Other errors (TLS, RBAC, etc.) - ambiguous, fail fast with a hint to set --publish explicitly.

Changes

  • internal/data/publish.go - PublishFlag struct and ParsePublishFlag for three-state flag parsing (explicit true / explicit false / not set).
  • internal/data/publish_detect.go - ResolvePublish, DetectPublish, and isNetworkUnreachable implementing the auto-detection logic.
  • pkg/libsaferequest/client/http.go - SetProbeEndpoint and Copy methods on SafeClient to configure and clone the probe client without mutating the original.
  • internal/data/dataexport/cmd/{create,download,list} - integrated ParsePublishFlag + ResolvePublish replacing direct GetBool("publish").
  • internal/data/dataimport/cmd/{create,upload} - same integration for import commands.
  • internal/data/data{export,import}/util/util.go - GetData{Export,Import}WithRestart now accepts publish bool for publish reconciliation.
  • internal/data/publish_detect_test.go - unit tests covering isNetworkUnreachable, ResolvePublish, getKubeService, and DetectPublish.

Usage

In cluster

Commands run from a node inside the target cluster. Auto-detection probes the ClusterIP successfully, UIDs match -> publish=false.

d8 data export create

Note: auto-detect selects publish=false, DataExport has no Public URL - accessible only within the cluster.

tfadm@k-kozoriz-master-0:~/demo/d8/builds$ k get dataexport -A
No resources found

tfadm@k-kozoriz-master-0:~/demo/d8/builds$ ./d8-new data export -n de-test create test-de1 pvc/dataexport-experiment-pvc --ttl 5m 
publish_detect.go:62: INFO Auto-detecting publish mode
publish_detect.go:136: INFO Publish autodetect: internal endpoint is reachable, selecting publish=false
create.go:133: INFO DataExport created name=test-de1 namespace=de-test

tfadm@k-kozoriz-master-0:~/demo/d8/builds$ k get dataexport -A
NAMESPACE   NAME       URL                          PUBLIC URL   STATUS     AGE
de-test     test-de1   https://10.112.1.111:8085/                PodReady   30s

tfadm@k-kozoriz-master-0:~/demo/d8/builds$ k get dataexport -A -o yaml | grep publish:
    publish: false

d8 data export download

tfadm@k-kozoriz-master-0:~/demo/d8/builds$ ls ../tmp/

tfadm@k-kozoriz-master-0:~/demo/d8/builds$ ./d8-new data export -n de-test download test-de1 / -o ~/demo/d8/tmp/download
publish_detect.go:62: INFO Auto-detecting publish mode
publish_detect.go:136: INFO Publish autodetect: internal endpoint is reachable, selecting publish=false
download.go:260: INFO DataExport created name=test-de1 namespace=de-test
util.go:246: INFO Waiting for DataExport to be ready name=test-de1 namespace=de-test
util.go:274: INFO DataExport is ready name=test-de1 namespace=de-test url=https://10.112.1.111:8085/ volumeMode=Filesystem
download.go:285: INFO Start downloading url=https://10.112.1.111:8085/api/v1/files/ dstPath=/home/deckhouse/tfadm/demo/d8/tmp/download
download.go:213: INFO Downloaded file path=/home/deckhouse/tfadm/demo/d8/tmp/download/file_link
download.go:213: INFO Downloaded file path=/home/deckhouse/tfadm/demo/d8/tmp/download/file
download.go:213: INFO Downloaded file path=/home/deckhouse/tfadm/demo/d8/tmp/download/dir_link
download.go:213: INFO Downloaded file path=/home/deckhouse/tfadm/demo/d8/tmp/download/dir/nested_file
download.go:213: INFO Downloaded file path=/home/deckhouse/tfadm/demo/d8/tmp/download/dir/nested_link
download.go:291: INFO All files have been downloaded dst_path=/home/deckhouse/tfadm/demo/d8/tmp/download

tfadm@k-kozoriz-master-0:~/demo/d8/builds$ ls ../tmp/
download

d8 data export list

tfadm@k-kozoriz-master-0:~/demo/d8/builds$ ./d8-new data export -n de-test list test-de1 /
publish_detect.go:62: INFO Auto-detecting publish mode
publish_detect.go:136: INFO Publish autodetect: internal endpoint is reachable, selecting publish=false
list.go:199: INFO DataExport created name=test-de1 namespace=de-test
util.go:246: INFO Waiting for DataExport to be ready name=test-de1 namespace=de-test
util.go:274: INFO DataExport is ready name=test-de1 namespace=de-test url=https://10.112.1.111:8085/ volumeMode=Filesystem
list.go:113: INFO Start listing url=https://10.112.1.111:8085/api/v1/files/ srcPath=/
{"apiVersion": "v1", "items": [{"name":"dir_link","type":"link","uri":"dir_link","targetPath":"/outer_dir","attributes":{"gid":0,"modtime":"2026-02-17T17:36:25Z","permissions":"0777","uid":0}}
,{"name":"file_link","type":"link","uri":"file_link","targetPath":"/data/file","attributes":{"gid":0,"modtime":"2026-02-17T17:36:25Z","permissions":"0777","uid":0}}
,{"name":"dir","type":"dir","uri":"dir/","attributes":{"gid":0,"modtime":"2026-02-17T17:36:25Z","permissions":"0755","uid":0}}
,{"name":"file","type":"file","uri":"file","attributes":{"gid":0,"modtime":"2026-02-17T17:36:25Z","permissions":"0644","size":5,"uid":0}}
]}

Out of cluster

Commands run from a developer laptop. ClusterIP is not routable -> auto-detect selects publish=true.

d8 data export create

Note: auto-detect selects publish=true, DataExport gets a Public URL for external access.

konstantin@MacBook-Pro-Konstantin bin % KUBECONFIG=~/.kube/dev-external-config ./d8 k get DataExport -A
No resources found

konstantin@MacBook-Pro-Konstantin bin % KUBECONFIG=~/.kube/dev-external-config ./d8 data export -n de-test create test-de1 pvc/dataexport-experiment-pvc --ttl 5m 
publish_detect.go:62: INFO Auto-detecting publish mode
publish_detect.go:120: INFO Publish autodetect: internal endpoint is unreachable, selecting publish=true
create.go:133: INFO DataExport created name=test-de1 namespace=de-test

konstantin@MacBook-Pro-Konstantin bin % KUBECONFIG=~/.kube/dev-external-config kubectl get DataExport -A                                                          
NAMESPACE   NAME       URL                          PUBLIC URL                                                                            STATUS     AGE
de-test     test-de1   https://10.112.4.107:8085/   https://api.k-kozoriz.storage.foxtrot-dev.ru/de-test/pvc/dataexport-experiment-pvc/   PodReady   94s

konstantin@MacBook-Pro-Konstantin bin % KUBECONFIG=~/.kube/dev-external-config ./d8 k get DataExport -A -o yaml | grep publish:
    publish: true

d8 data export download

konstantin@MacBook-Pro-Konstantin bin % ls
d8

konstantin@MacBook-Pro-Konstantin bin % KUBECONFIG=~/.kube/dev-external-config ./d8 data export -n de-test download test-de1 / -o ./download
publish_detect.go:62: INFO Auto-detecting publish mode
publish_detect.go:120: INFO Publish autodetect: internal endpoint is unreachable, selecting publish=true
download.go:260: INFO DataExport created name=test-de1 namespace=de-test
util.go:246: INFO Waiting for DataExport to be ready name=test-de1 namespace=de-test
util.go:274: INFO DataExport is ready name=test-de1 namespace=de-test url=https://api.k-kozoriz.storage.foxtrot-dev.ru/de-test/pvc/dataexport-experiment-pvc/ volumeMode=Filesystem
download.go:285: INFO Start downloading url=https://api.k-kozoriz.storage.foxtrot-dev.ru/de-test/pvc/dataexport-experiment-pvc/api/v1/files/ dstPath=./download
download.go:213: INFO Downloaded file path=download/file_link
download.go:213: INFO Downloaded file path=download/dir_link
download.go:213: INFO Downloaded file path=download/file
download.go:213: INFO Downloaded file path=download/dir/nested_file
download.go:213: INFO Downloaded file path=download/dir/nested_link
download.go:291: INFO All files have been downloaded dst_path=./download

konstantin@MacBook-Pro-Konstantin bin % ls
d8              download

d8 data export list

konstantin@MacBook-Pro-Konstantin bin % KUBECONFIG=~/.kube/dev-external-config ./d8 data export -n de-test list test-de1 /
publish_detect.go:62: INFO Auto-detecting publish mode
publish_detect.go:120: INFO Publish autodetect: internal endpoint is unreachable, selecting publish=true
list.go:199: INFO DataExport created name=test-de1 namespace=de-test
util.go:246: INFO Waiting for DataExport to be ready name=test-de1 namespace=de-test
util.go:274: INFO DataExport is ready name=test-de1 namespace=de-test url=https://api.k-kozoriz.storage.foxtrot-dev.ru/de-test/pvc/dataexport-experiment-pvc/ volumeMode=Filesystem
list.go:113: INFO Start listing url=https://api.k-kozoriz.storage.foxtrot-dev.ru/de-test/pvc/dataexport-experiment-pvc/api/v1/files/ srcPath=/
{"apiVersion": "v1", "items": [{"name":"dir_link","type":"link","uri":"dir_link","targetPath":"/outer_dir","attributes":{"gid":0,"modtime":"2026-02-17T17:36:25Z","permissions":"0777","uid":0}}
,{"name":"file_link","type":"link","uri":"file_link","targetPath":"/data/file","attributes":{"gid":0,"modtime":"2026-02-17T17:36:25Z","permissions":"0777","uid":0}}
,{"name":"dir","type":"dir","uri":"dir/","attributes":{"gid":0,"modtime":"2026-02-17T17:36:25Z","permissions":"0755","uid":0}}
,{"name":"file","type":"file","uri":"file","attributes":{"gid":0,"modtime":"2026-02-17T17:36:25Z","permissions":"0644","size":5,"uid":0}}
]}

d8 data export download (when DataExport.Spec.Publish=false)

Demonstrates one-way reconciliation: DataExport was created with spec.publish=false from inside the cluster. When download runs from outside, auto-detect resolves publish=true and patches the existing DataExport - Public URL appears, download uses it.

konstantin@MacBook-Pro-Konstantin bin % KUBECONFIG=~/.kube/dev-external-config kubectl get DataExport -A                        
NAMESPACE   NAME       URL                          PUBLIC URL   STATUS     AGE
de-test     test-de1   https://10.112.4.130:8085/                PodReady   57s

konstantin@MacBook-Pro-Konstantin bin % KUBECONFIG=~/.kube/dev-external-config kubectl get DataExport -A -o yaml | grep publish:
    publish: false

konstantin@MacBook-Pro-Konstantin bin % ls
d8

konstantin@MacBook-Pro-Konstantin bin % KUBECONFIG=~/.kube/dev-external-config ./d8 data export -n de-test download test-de1 / -o ./download
publish_detect.go:62: INFO Auto-detecting publish mode
publish_detect.go:120: INFO Publish autodetect: internal endpoint is unreachable, selecting publish=true
download.go:260: INFO DataExport created name=test-de1 namespace=de-test
util.go:246: INFO Waiting for DataExport to be ready name=test-de1 namespace=de-test
util.go:274: INFO DataExport is ready name=test-de1 namespace=de-test url=https://api.k-kozoriz.storage.foxtrot-dev.ru/de-test/pvc/dataexport-experiment-pvc/ volumeMode=Filesystem
download.go:285: INFO Start downloading url=https://api.k-kozoriz.storage.foxtrot-dev.ru/de-test/pvc/dataexport-experiment-pvc/api/v1/files/ dstPath=./download
download.go:213: INFO Downloaded file path=download/file
download.go:213: INFO Downloaded file path=download/file_link
download.go:213: INFO Downloaded file path=download/dir_link
download.go:213: INFO Downloaded file path=download/dir/nested_file
download.go:213: INFO Downloaded file path=download/dir/nested_link
download.go:291: INFO All files have been downloaded dst_path=./download

konstantin@MacBook-Pro-Konstantin bin % KUBECONFIG=~/.kube/dev-external-config kubectl get DataExport -A                                    
NAMESPACE   NAME       URL                          PUBLIC URL                                                                            STATUS     AGE
de-test     test-de1   https://10.112.4.130:8085/   https://api.k-kozoriz.storage.foxtrot-dev.ru/de-test/pvc/dataexport-experiment-pvc/   PodReady   91s

konstantin@MacBook-Pro-Konstantin bin % KUBECONFIG=~/.kube/dev-external-config kubectl get DataExport -A -o yaml | grep publish:            
    publish: true

konstantin@MacBook-Pro-Konstantin bin % ls
d8              download

Signed-off-by: Konstantin Kozoriz <konstantin.kozoriz@flant.com>
When --publish is not explicitly set, detect whether the client
is inside the target cluster by probing the ClusterIP of the
default/kubernetes service and comparing UIDs.

Signed-off-by: Konstantin Kozoriz <konstantin.kozoriz@flant.com>
Signed-off-by: Konstantin Kozoriz <konstantin.kozoriz@flant.com>
@kkozoriz kkozoriz requested a review from ldmonster as a code owner February 19, 2026 15:09
@kkozoriz kkozoriz requested a review from AleksZimin February 19, 2026 15:10
@kkozoriz kkozoriz self-assigned this Feb 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant