cue-lang / cue

The home of the CUE language! Validate and define text-based and dynamic configuration
https://cuelang.org
Apache License 2.0
5.14k stars 294 forks source link

net.IP constraint takes too long or deadlocks. #3442

Open freeformz opened 2 months ago

freeformz commented 2 months ago

What version of CUE are you using (cue version)?

$ cue version
cue version v0.10.0

go version go1.23.0
      -buildmode exe
       -compiler gc
       -trimpath true
     CGO_ENABLED 0
          GOARCH arm64
            GOOS darwin
         GOARM64 v8.0
cue.lang.version v0.10.0

But I also tried it with master from sometime last week and had the same issue.

Does this issue reproduce with the latest stable release?

Yes.

What did you do?

I have some defines like this in a module that are then used in another module

#AllowlistIP: string & net.IPCIDR

#Route: {
    host:   string
    prefix: string
}

#MTLSVault: {
    ca_cert_key_name: string
    path:             string
    ca_crl_key_name?: string
}

#MTLS: {
    enabled?: bool
    vault?:   #MTLSVault
}

#TLSVault: {
    cert_key_name:     string
    path:              string
    priv_key_key_name: string
}

#TLSWOProvider: {
    enabled?:  bool
    issuer?:   string
    mtls?:     #MTLS
    provider?: "auto" | "vault"
    vault?:    #TLSVault
}

#TLSWVaultProvider: #TLSWOProvider & {
    provider: "vault"
    vault:    #TLSVault
}

#TLS: #TLSWOProvider | #TLSWVaultProvider

#PortIngressHTTP: http: {
    annotations?: #Annotations
    internal?:    bool
    name?:        string
    source_ip_allowlist?: [...#AllowlistIP]
    tls?: #TLS
    routes: [...#Route]
    routes: list.MinItems(1)
}

#PortIngressTCP: tcp: {
    dns_name:  string
    internal?: bool
    source_ip_allowlist?: [...#AllowlistIP]
    static_ip?: string // & net.IP <-- seems to deadlock the cue CLI
}
#PortIngressUDP: udp: {
    dns_name:  string
    internal?: bool
    source_ip_allowlist?: [...#AllowlistIP]
    static_ip?: string // & net.IP <-- seems to deadlock the cue CLI
}

#PortIngress: {
    #PortIngressTCP | #PortIngressUDP | #PortIngressHTTP
}

#ContainerPort: {
    number:   int & >=0 & <=65535
    protocol: "HTTP" | "http" | "TCP" | "tcp" | "UDP" | "udp"
    expose?:  bool
    ingress?: #PortIngress
    target?:  int & >=0 & <=65535
}

#Container: {
   // ... other stuff
   ports?: [...#ContainerPort]
}

Container is then used in the other module a bunch of times.

When static_ip? has the & net.IP constraint applied the cue export we run in our Makefile effectively takes forever and never finishes. I waited minutes and gave up. Commented out it takes ~5s max ... usually more like 1-2 seconds.

What did you expect to see?

The net.IP constraint applied and the export completing.

What did you see instead?

cue export essentially hung.

mvdan commented 2 months ago

Thanks for raising this issue. Are you able to provide a full reproducer for this issue? If your project is private, you can also add it to Unity: https://cuelabs.dev/unity/

Have you tried the new evaluator by any chance? Plenty of work remains to be done to make it the default, but its main aim is to allow significantly better performance in cases like the one you describe - the old evaluator tends to re-do a lot of work. In your case, the old evaluator is likely causing many repeated calls to net.IP. See https://github.com/cue-lang/cue/issues/2566 for example, which describes a similar issue with function calls.

freeformz commented 2 months ago

I tried with cue v0.10 & v0.11-alpha.1 with export CUE_EXPERIMENT=evalv3 and it seemed just as slow, if not worse.

some timing info on an M3 Max MBP on one of the several exports we do...

cue v0.10 w/o & net.IP

time cue export -T --out yaml ./apps/config/prd/awsusw2/sds/esdailyrollups | yq 'sort_keys(..)' > workloads/prd-awsusw2/sds/esdailyrollups.yaml

________________________________________________________
Executed in  932.52 millis    fish           external
   usr time    1.62 secs      0.08 millis    1.62 secs
   sys time    0.09 secs      2.07 millis    0.08 secs

cue v0.11-alpha.1 w/o & net.IP

$ time cue export -T --out yaml ./apps/config/prd/awsusw2/sds/esdailyrollups | yq 'sort_keys(..)' > workloads/prd-awsusw2/sds/esdailyrollups.yaml

________________________________________________________
Executed in  894.78 millis    fish           external
   usr time    1.59 secs      0.08 millis    1.59 secs
   sys time    0.07 secs      1.52 millis    0.07 secs

cue v0.10 w/o &net.IP, with CUE_EXPERIMENT=evalv3 - CTRL-C after ~1min cue v0.11-alpha.1 w/o &net.IP, with CUE_EXPERIMENT=evalv3 - CTRL-C after ~1min

cue v0.10 w/ &net.IP

$ time cue export -T --out yaml ./apps/config/prd/awsusw2/sds/esdailyrollups | yq 'sort_keys(..)' > workloads/prd-awsusw2/sds/esdailyrollups.yaml

________________________________________________________
Executed in   21.52 secs    fish           external
   usr time   27.57 secs    0.08 millis   27.57 secs
   sys time    0.41 secs    1.41 millis    0.41 secs

cue v0.11-alpha.1 w/ &net.IP

$ time cue export -T --out yaml ./apps/config/prd/awsusw2/sds/esdailyrollups | yq 'sort_keys(..)' > workloads/prd-awsusw2/sds/esdailyrollups.yaml

________________________________________________________
Executed in   21.56 secs    fish           external
   usr time   27.31 secs    0.08 millis   27.31 secs
   sys time    0.39 secs    1.36 millis    0.39 secs

I'll upload unity stuff next week.

freeformz commented 2 months ago

cue v0.11-alpha.1 w/ &net.IP, with CUE_EXPERIMENT=evalv3 -CTRL-C after running over the weekend.

$ time cue export -T --out yaml ./apps/config/prd/awsusw2/sds/esdailyrollups | yq 'sort_keys(..)' > workloads/prd-awsusw2/sds/esdailyrollups.yaml
________________________________________________________
Executed in  3862.98 mins    fish           external
   usr time  5092.13 mins    0.10 millis  5092.13 mins
   sys time  350.43 mins    2.81 millis  350.43 mins
freeformz commented 2 months ago

I finally understand what unity is and I can't install that in our org/repo