Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated argument types are unusably large #12

Closed
lukehoban opened this issue Feb 13, 2018 · 7 comments
Closed

Generated argument types are unusably large #12

lukehoban opened this issue Feb 13, 2018 · 7 comments

Comments

@lukehoban
Copy link
Member

lukehoban commented Feb 13, 2018

The types we generate for arguments and properties on Kubernetes resources are VERY large.

This leads to:

  1. It's very hard to actually create these property bags - as they have so much complicated internal structure without independent named types which can be created (and shared) independently.
  2. At least in VSCode, this brings the IDE to it's knees, and completion lists, error checking, etc. start failing or taking >1minute.

We should see if we can factor out some of the shared structure and create named types for these and then overlay those on top of the actual resources.

In source, it's all on a single line:

    readonly spec: pulumi.Input<{ minReadySeconds?: pulumi.Input<number>, replicas?: pulumi.Input<number>, selector?: pulumi.Input<{[key: string]: any}>, strategy?: pulumi.Input<{ rollingUpdate?: pulumi.Input<{ maxSurge?: pulumi.Input<string>, maxUnavailable?: pulumi.Input<string> }[]>, type?: pulumi.Input<string> }[]>, template: pulumi.Input<{ activeDeadlineSeconds?: pulumi.Input<string>, automountServiceAccountToken?: pulumi.Input<string>, container?: pulumi.Input<string>, dnsPolicy?: pulumi.Input<string>, hostIpc?: pulumi.Input<string>, hostNetwork?: pulumi.Input<string>, hostPid?: pulumi.Input<string>, hostname?: pulumi.Input<string>, metadata?: pulumi.Input<{ annotations?: pulumi.Input<{[key: string]: any}>, generateName?: pulumi.Input<string>, generation?: pulumi.Input<number>, labels?: pulumi.Input<{[key: string]: any}>, name?: pulumi.Input<string>, resourceVersion?: pulumi.Input<string>, selfLink?: pulumi.Input<string>, uid?: pulumi.Input<string> }[]>, nodeName?: pulumi.Input<string>, nodeSelector?: pulumi.Input<string>, restartPolicy?: pulumi.Input<string>, securityContext?: pulumi.Input<string>, serviceAccountName?: pulumi.Input<string>, spec: pulumi.Input<{ activeDeadlineSeconds?: pulumi.Input<number>, automountServiceAccountToken?: pulumi.Input<boolean>, container?: pulumi.Input<{ args?: pulumi.Input<pulumi.Input<string>[]>, command?: pulumi.Input<pulumi.Input<string>[]>, env?: pulumi.Input<{ name: pulumi.Input<string>, value?: pulumi.Input<string>, valueFrom?: pulumi.Input<{ configMapKeyRef?: pulumi.Input<{ key?: pulumi.Input<string>, name?: pulumi.Input<string> }[]>, fieldRef?: pulumi.Input<{ apiVersion?: pulumi.Input<string>, fieldPath?: pulumi.Input<string> }[]>, resourceFieldRef?: pulumi.Input<{ containerName?: pulumi.Input<string>, resource: pulumi.Input<string> }[]>, secretKeyRef?: pulumi.Input<{ key?: pulumi.Input<string>, name?: pulumi.Input<string> }[]> }[]> }[]>, envFrom?: pulumi.Input<{ configMapRef?: pulumi.Input<{ name?: pulumi.Input<string>, optional?: pulumi.Input<boolean> }[]>, prefix?: pulumi.Input<string>, secretRef?: pulumi.Input<{ name?: pulumi.Input<string>, optional?: pulumi.Input<boolean> }[]> }[]>, image?: pulumi.Input<string>, imagePullPolicy?: pulumi.Input<string>, lifecycle?: pulumi.Input<{ postStart?: pulumi.Input<{ exec?: pulumi.Input<{ command?: pulumi.Input<pulumi.Input<string>[]> }[]>, httpGet?: pulumi.Input<{ host?: pulumi.Input<string>, httpHeader?: pulumi.Input<{ name?: pulumi.Input<string>, value?: pulumi.Input<string> }[]>, path?: pulumi.Input<string>, port?: pulumi.Input<string>, scheme?: pulumi.Input<string> }[]>, tcpSocket?: pulumi.Input<{ port: pulumi.Input<string> }[]> }[]>, preStop?: pulumi.Input<{ exec?: pulumi.Input<{ command?: pulumi.Input<pulumi.Input<string>[]> }[]>, httpGet?: pulumi.Input<{ host?: pulumi.Input<string>, httpHeader?: pulumi.Input<{ name?: pulumi.Input<string>, value?: pulumi.Input<string> }[]>, path?: pulumi.Input<string>, port?: pulumi.Input<string>, scheme?: pulumi.Input<string> }[]>, tcpSocket?: pulumi.Input<{ port: pulumi.Input<string> }[]> }[]> }[]>, livenessProbe?: pulumi.Input<{ exec?: pulumi.Input<{ command?: pulumi.Input<pulumi.Input<string>[]> }[]>, failureThreshold?: pulumi.Input<number>, httpGet?: pulumi.Input<{ host?: pulumi.Input<string>, httpHeader?: pulumi.Input<{ name?: pulumi.Input<string>, value?: pulumi.Input<string> }[]>, path?: pulumi.Input<string>, port?: pulumi.Input<string>, scheme?: pulumi.Input<string> }[]>, initialDelaySeconds?: pulumi.Input<number>, periodSeconds?: pulumi.Input<number>, successThreshold?: pulumi.Input<number>, tcpSocket?: pulumi.Input<{ port: pulumi.Input<string> }[]>, timeoutSeconds?: pulumi.Input<number> }[]>, name: pulumi.Input<string>, port?: pulumi.Input<{ containerPort: pulumi.Input<number>, hostIp?: pulumi.Input<string>, hostPort?: pulumi.Input<number>, name?: pulumi.Input<string>, protocol?: pulumi.Input<string> }[]>, readinessProbe?: pulumi.Input<{ exec?: pulumi.Input<{ command?: pulumi.Input<pulumi.Input<string>[]> }[]>, failureThreshold?: pulumi.Input<number>, httpGet?: pulumi.Input<{ host?: pulumi.Input<string>, httpHeader?: pulumi.Input<{ name?: pulumi.Input<string>, value?: pulumi.Input<string> }[]>, path?: pulumi.Input<string>, port?: pulumi.Input<string>, scheme?: pulumi.Input<string> }[]>, initialDelaySeconds?: pulumi.Input<number>, periodSeconds?: pulumi.Input<number>, successThreshold?: pulumi.Input<number>, tcpSocket?: pulumi.Input<{ port: pulumi.Input<string> }[]>, timeoutSeconds?: pulumi.Input<number> }[]>, resources?: pulumi.Input<{ limits?: pulumi.Input<{ cpu?: pulumi.Input<string>, memory?: pulumi.Input<string> }[]>, requests?: pulumi.Input<{ cpu?: pulumi.Input<string>, memory?: pulumi.Input<string> }[]> }[]>, securityContext?: pulumi.Input<{ capabilities?: pulumi.Input<{ add?: pulumi.Input<pulumi.Input<string>[]>, drop?: pulumi.Input<pulumi.Input<string>[]> }[]>, privileged?: pulumi.Input<boolean>, readOnlyRootFilesystem?: pulumi.Input<boolean>, runAsNonRoot?: pulumi.Input<boolean>, runAsUser?: pulumi.Input<number>, seLinuxOptions?: pulumi.Input<{ level?: pulumi.Input<string>, role?: pulumi.Input<string>, type?: pulumi.Input<string>, user?: pulumi.Input<string> }[]> }[]>, stdin?: pulumi.Input<boolean>, stdinOnce?: pulumi.Input<boolean>, terminationMessagePath?: pulumi.Input<string>, tty?: pulumi.Input<boolean>, volumeMount?: pulumi.Input<{ mountPath: pulumi.Input<string>, name: pulumi.Input<string>, readOnly?: pulumi.Input<boolean>, subPath?: pulumi.Input<string> }[]>, workingDir?: pulumi.Input<string> }[]>, dnsPolicy?: pulumi.Input<string>, hostIpc?: pulumi.Input<boolean>, hostNetwork?: pulumi.Input<boolean>, hostPid?: pulumi.Input<boolean>, hostname?: pulumi.Input<string>, imagePullSecrets?: pulumi.Input<{ name: pulumi.Input<string> }[]>, initContainer?: pulumi.Input<{ args?: pulumi.Input<pulumi.Input<string>[]>, command?: pulumi.Input<pulumi.Input<string>[]>, env?: pulumi.Input<{ name: pulumi.Input<string>, value?: pulumi.Input<string>, valueFrom?: pulumi.Input<{ configMapKeyRef?: pulumi.Input<{ key?: pulumi.Input<string>, name?: pulumi.Input<string> }[]>, fieldRef?: pulumi.Input<{ apiVersion?: pulumi.Input<string>, fieldPath?: pulumi.Input<string> }[]>, resourceFieldRef?: pulumi.Input<{ containerName?: pulumi.Input<string>, resource: pulumi.Input<string> }[]>, secretKeyRef?: pulumi.Input<{ key?: pulumi.Input<string>, name?: pulumi.Input<string> }[]> }[]> }[]>, envFrom?: pulumi.Input<{ configMapRef?: pulumi.Input<{ name?: pulumi.Input<string>, optional?: pulumi.Input<boolean> }[]>, prefix?: pulumi.Input<string>, secretRef?: pulumi.Input<{ name?: pulumi.Input<string>, optional?: pulumi.Input<boolean> }[]> }[]>, image?: pulumi.Input<string>, imagePullPolicy?: pulumi.Input<string>, lifecycle?: pulumi.Input<{ postStart?: pulumi.Input<{ exec?: pulumi.Input<{ command?: pulumi.Input<pulumi.Input<string>[]> }[]>, httpGet?: pulumi.Input<{ host?: pulumi.Input<string>, httpHeader?: pulumi.Input<{ name?: pulumi.Input<string>, value?: pulumi.Input<string> }[]>, path?: pulumi.Input<string>, port?: pulumi.Input<string>, scheme?: pulumi.Input<string> }[]>, tcpSocket?: pulumi.Input<{ port: pulumi.Input<string> }[]> }[]>, preStop?: pulumi.Input<{ exec?: pulumi.Input<{ command?: pulumi.Input<pulumi.Input<string>[]> }[]>, httpGet?: pulumi.Input<{ host?: pulumi.Input<string>, httpHeader?: pulumi.Input<{ name?: pulumi.Input<string>, value?: pulumi.Input<string> }[]>, path?: pulumi.Input<string>, port?: pulumi.Input<string>, scheme?: pulumi.Input<string> }[]>, tcpSocket?: pulumi.Input<{ port: pulumi.Input<string> }[]> }[]> }[]>, livenessProbe?: pulumi.Input<{ exec?: pulumi.Input<{ command?: pulumi.Input<pulumi.Input<string>[]> }[]>, failureThreshold?: pulumi.Input<number>, httpGet?: pulumi.Input<{ host?: pulumi.Input<string>, httpHeader?: pulumi.Input<{ name?: pulumi.Input<string>, value?: pulumi.Input<string> }[]>, path?: pulumi.Input<string>, port?: pulumi.Input<string>, scheme?: pulumi.Input<string> }[]>, initialDelaySeconds?: pulumi.Input<number>, periodSeconds?: pulumi.Input<number>, successThreshold?: pulumi.Input<number>, tcpSocket?: pulumi.Input<{ port: pulumi.Input<string> }[]>, timeoutSeconds?: pulumi.Input<number> }[]>, name: pulumi.Input<string>, port?: pulumi.Input<{ containerPort: pulumi.Input<number>, hostIp?: pulumi.Input<string>, hostPort?: pulumi.Input<number>, name?: pulumi.Input<string>, protocol?: pulumi.Input<string> }[]>, readinessProbe?: pulumi.Input<{ exec?: pulumi.Input<{ command?: pulumi.Input<pulumi.Input<string>[]> }[]>, failureThreshold?: pulumi.Input<number>, httpGet?: pulumi.Input<{ host?: pulumi.Input<string>, httpHeader?: pulumi.Input<{ name?: pulumi.Input<string>, value?: pulumi.Input<string> }[]>, path?: pulumi.Input<string>, port?: pulumi.Input<string>, scheme?: pulumi.Input<string> }[]>, initialDelaySeconds?: pulumi.Input<number>, periodSeconds?: pulumi.Input<number>, successThreshold?: pulumi.Input<number>, tcpSocket?: pulumi.Input<{ port: pulumi.Input<string> }[]>, timeoutSeconds?: pulumi.Input<number> }[]>, resources?: pulumi.Input<{ limits?: pulumi.Input<{ cpu?: pulumi.Input<string>, memory?: pulumi.Input<string> }[]>, requests?: pulumi.Input<{ cpu?: pulumi.Input<string>, memory?: pulumi.Input<string> }[]> }[]>, securityContext?: pulumi.Input<{ capabilities?: pulumi.Input<{ add?: pulumi.Input<pulumi.Input<string>[]>, drop?: pulumi.Input<pulumi.Input<string>[]> }[]>, privileged?: pulumi.Input<boolean>, readOnlyRootFilesystem?: pulumi.Input<boolean>, runAsNonRoot?: pulumi.Input<boolean>, runAsUser?: pulumi.Input<number>, seLinuxOptions?: pulumi.Input<{ level?: pulumi.Input<string>, role?: pulumi.Input<string>, type?: pulumi.Input<string>, user?: pulumi.Input<string> }[]> }[]>, stdin?: pulumi.Input<boolean>, stdinOnce?: pulumi.Input<boolean>, terminationMessagePath?: pulumi.Input<string>, tty?: pulumi.Input<boolean>, volumeMount?: pulumi.Input<{ mountPath: pulumi.Input<string>, name: pulumi.Input<string>, readOnly?: pulumi.Input<boolean>, subPath?: pulumi.Input<string> }[]>, workingDir?: pulumi.Input<string> }[]>, nodeName?: pulumi.Input<string>, nodeSelector?: pulumi.Input<{[key: string]: any}>, restartPolicy?: pulumi.Input<string>, securityContext?: pulumi.Input<{ fsGroup?: pulumi.Input<number>, runAsNonRoot?: pulumi.Input<boolean>, runAsUser?: pulumi.Input<number>, seLinuxOptions?: pulumi.Input<{ level?: pulumi.Input<string>, role?: pulumi.Input<string>, type?: pulumi.Input<string>, user?: pulumi.Input<string> }[]>, supplementalGroups?: pulumi.Input<pulumi.Input<number>[]> }[]>, serviceAccountName?: pulumi.Input<string>, subdomain?: pulumi.Input<string>, terminationGracePeriodSeconds?: pulumi.Input<number>, volume?: pulumi.Input<{ awsElasticBlockStore?: pulumi.Input<{ fsType?: pulumi.Input<string>, partition?: pulumi.Input<number>, readOnly?: pulumi.Input<boolean>, volumeId: pulumi.Input<string> }[]>, azureDisk?: pulumi.Input<{ cachingMode: pulumi.Input<string>, dataDiskUri: pulumi.Input<string>, diskName: pulumi.Input<string>, fsType?: pulumi.Input<string>, readOnly?: pulumi.Input<boolean> }[]>, azureFile?: pulumi.Input<{ readOnly?: pulumi.Input<boolean>, secretName: pulumi.Input<string>, shareName: pulumi.Input<string> }[]>, cephFs?: pulumi.Input<{ monitors: pulumi.Input<pulumi.Input<string>[]>, path?: pulumi.Input<string>, readOnly?: pulumi.Input<boolean>, secretFile?: pulumi.Input<string>, secretRef?: pulumi.Input<{ name?: pulumi.Input<string> }[]>, user?: pulumi.Input<string> }[]>, cinder?: pulumi.Input<{ fsType?: pulumi.Input<string>, readOnly?: pulumi.Input<boolean>, volumeId: pulumi.Input<string> }[]>, configMap?: pulumi.Input<{ defaultMode?: pulumi.Input<number>, items?: pulumi.Input<{ key?: pulumi.Input<string>, mode?: pulumi.Input<number>, path?: pulumi.Input<string> }[]>, name?: pulumi.Input<string> }[]>, downwardApi?: pulumi.Input<{ defaultMode?: pulumi.Input<number>, items?: pulumi.Input<{ fieldRef: pulumi.Input<{ apiVersion?: pulumi.Input<string>, fieldPath?: pulumi.Input<string> }[]>, mode?: pulumi.Input<number>, path: pulumi.Input<string>, resourceFieldRef?: pulumi.Input<{ containerName: pulumi.Input<string>, quantity?: pulumi.Input<string>, resource: pulumi.Input<string> }[]> }[]> }[]>, emptyDir?: pulumi.Input<{ medium?: pulumi.Input<string> }[]>, fc?: pulumi.Input<{ fsType?: pulumi.Input<string>, lun: pulumi.Input<number>, readOnly?: pulumi.Input<boolean>, targetWwNs: pulumi.Input<pulumi.Input<string>[]> }[]>, flexVolume?: pulumi.Input<{ driver: pulumi.Input<string>, fsType?: pulumi.Input<string>, options?: pulumi.Input<{[key: string]: any}>, readOnly?: pulumi.Input<boolean>, secretRef?: pulumi.Input<{ name?: pulumi.Input<string> }[]> }[]>, flocker?: pulumi.Input<{ datasetName?: pulumi.Input<string>, datasetUuid?: pulumi.Input<string> }[]>, gcePersistentDisk?: pulumi.Input<{ fsType?: pulumi.Input<string>, partition?: pulumi.Input<number>, pdName: pulumi.Input<string>, readOnly?: pulumi.Input<boolean> }[]>, gitRepo?: pulumi.Input<{ directory?: pulumi.Input<string>, repository?: pulumi.Input<string>, revision?: pulumi.Input<string> }[]>, glusterfs?: pulumi.Input<{ endpointsName: pulumi.Input<string>, path: pulumi.Input<string>, readOnly?: pulumi.Input<boolean> }[]>, hostPath?: pulumi.Input<{ path?: pulumi.Input<string> }[]>, iscsi?: pulumi.Input<{ fsType?: pulumi.Input<string>, iqn: pulumi.Input<string>, iscsiInterface?: pulumi.Input<string>, lun?: pulumi.Input<number>, readOnly?: pulumi.Input<boolean>, targetPortal: pulumi.Input<string> }[]>, name?: pulumi.Input<string>, nfs?: pulumi.Input<{ path: pulumi.Input<string>, readOnly?: pulumi.Input<boolean>, server: pulumi.Input<string> }[]>, persistentVolumeClaim?: pulumi.Input<{ claimName?: pulumi.Input<string>, readOnly?: pulumi.Input<boolean> }[]>, photonPersistentDisk?: pulumi.Input<{ fsType?: pulumi.Input<string>, pdId: pulumi.Input<string> }[]>, quobyte?: pulumi.Input<{ group?: pulumi.Input<string>, readOnly?: pulumi.Input<boolean>, registry: pulumi.Input<string>, user?: pulumi.Input<string>, volume: pulumi.Input<string> }[]>, rbd?: pulumi.Input<{ cephMonitors: pulumi.Input<pulumi.Input<string>[]>, fsType?: pulumi.Input<string>, keyring?: pulumi.Input<string>, radosUser?: pulumi.Input<string>, rbdImage: pulumi.Input<string>, rbdPool?: pulumi.Input<string>, readOnly?: pulumi.Input<boolean>, secretRef?: pulumi.Input<{ name?: pulumi.Input<string> }[]> }[]>, secret?: pulumi.Input<{ defaultMode?: pulumi.Input<number>, items?: pulumi.Input<{ key?: pulumi.Input<string>, mode?: pulumi.Input<number>, path?: pulumi.Input<string> }[]>, optional?: pulumi.Input<boolean>, secretName?: pulumi.Input<string> }[]>, vsphereVolume?: pulumi.Input<{ fsType?: pulumi.Input<string>, volumePath: pulumi.Input<string> }[]> }[]> }[]>, subdomain?: pulumi.Input<string>, terminationGracePeriodSeconds?: pulumi.Input<string>, volume?: pulumi.Input<string> }[]> }[]>;

In the generated .d.ts it gets pretty printed as a 571-line long type literal.

    readonly spec: pulumi.Input<{
        minReadySeconds?: pulumi.Input<number>;
        replicas?: pulumi.Input<number>;
        selector?: pulumi.Input<{
            [key: string]: any;
        }>;
        strategy?: pulumi.Input<{
            rollingUpdate?: pulumi.Input<{
                maxSurge?: pulumi.Input<string>;
                maxUnavailable?: pulumi.Input<string>;
            }[]>;
            type?: pulumi.Input<string>;
        }[]>;
        template: pulumi.Input<{
            activeDeadlineSeconds?: pulumi.Input<string>;
            automountServiceAccountToken?: pulumi.Input<string>;
            container?: pulumi.Input<string>;
            dnsPolicy?: pulumi.Input<string>;
            hostIpc?: pulumi.Input<string>;
            hostNetwork?: pulumi.Input<string>;
            hostPid?: pulumi.Input<string>;
            hostname?: pulumi.Input<string>;
            metadata?: pulumi.Input<{
                annotations?: pulumi.Input<{
                    [key: string]: any;
                }>;
                generateName?: pulumi.Input<string>;
                generation?: pulumi.Input<number>;
                labels?: pulumi.Input<{
                    [key: string]: any;
                }>;
                name?: pulumi.Input<string>;
                resourceVersion?: pulumi.Input<string>;
                selfLink?: pulumi.Input<string>;
                uid?: pulumi.Input<string>;
            }[]>;
            nodeName?: pulumi.Input<string>;
            nodeSelector?: pulumi.Input<string>;
            restartPolicy?: pulumi.Input<string>;
            securityContext?: pulumi.Input<string>;
            serviceAccountName?: pulumi.Input<string>;
            spec: pulumi.Input<{
                activeDeadlineSeconds?: pulumi.Input<number>;
                automountServiceAccountToken?: pulumi.Input<boolean>;
                container?: pulumi.Input<{
                    args?: pulumi.Input<pulumi.Input<string>[]>;
                    command?: pulumi.Input<pulumi.Input<string>[]>;
                    env?: pulumi.Input<{
                        name: pulumi.Input<string>;
                        value?: pulumi.Input<string>;
                        valueFrom?: pulumi.Input<{
                            configMapKeyRef?: pulumi.Input<{
                                key?: pulumi.Input<string>;
                                name?: pulumi.Input<string>;
                            }[]>;
                            fieldRef?: pulumi.Input<{
                                apiVersion?: pulumi.Input<string>;
                                fieldPath?: pulumi.Input<string>;
                            }[]>;
                            resourceFieldRef?: pulumi.Input<{
                                containerName?: pulumi.Input<string>;
                                resource: pulumi.Input<string>;
                            }[]>;
                            secretKeyRef?: pulumi.Input<{
                                key?: pulumi.Input<string>;
                                name?: pulumi.Input<string>;
                            }[]>;
                        }[]>;
                    }[]>;
                    envFrom?: pulumi.Input<{
                        configMapRef?: pulumi.Input<{
                            name?: pulumi.Input<string>;
                            optional?: pulumi.Input<boolean>;
                        }[]>;
                        prefix?: pulumi.Input<string>;
                        secretRef?: pulumi.Input<{
                            name?: pulumi.Input<string>;
                            optional?: pulumi.Input<boolean>;
                        }[]>;
                    }[]>;
                    image?: pulumi.Input<string>;
                    imagePullPolicy?: pulumi.Input<string>;
                    lifecycle?: pulumi.Input<{
                        postStart?: pulumi.Input<{
                            exec?: pulumi.Input<{
                                command?: pulumi.Input<pulumi.Input<string>[]>;
                            }[]>;
                            httpGet?: pulumi.Input<{
                                host?: pulumi.Input<string>;
                                httpHeader?: pulumi.Input<{
                                    name?: pulumi.Input<string>;
                                    value?: pulumi.Input<string>;
                                }[]>;
                                path?: pulumi.Input<string>;
                                port?: pulumi.Input<string>;
                                scheme?: pulumi.Input<string>;
                            }[]>;
                            tcpSocket?: pulumi.Input<{
                                port: pulumi.Input<string>;
                            }[]>;
                        }[]>;
                        preStop?: pulumi.Input<{
                            exec?: pulumi.Input<{
                                command?: pulumi.Input<pulumi.Input<string>[]>;
                            }[]>;
                            httpGet?: pulumi.Input<{
                                host?: pulumi.Input<string>;
                                httpHeader?: pulumi.Input<{
                                    name?: pulumi.Input<string>;
                                    value?: pulumi.Input<string>;
                                }[]>;
                                path?: pulumi.Input<string>;
                                port?: pulumi.Input<string>;
                                scheme?: pulumi.Input<string>;
                            }[]>;
                            tcpSocket?: pulumi.Input<{
                                port: pulumi.Input<string>;
                            }[]>;
                        }[]>;
                    }[]>;
                    livenessProbe?: pulumi.Input<{
                        exec?: pulumi.Input<{
                            command?: pulumi.Input<pulumi.Input<string>[]>;
                        }[]>;
                        failureThreshold?: pulumi.Input<number>;
                        httpGet?: pulumi.Input<{
                            host?: pulumi.Input<string>;
                            httpHeader?: pulumi.Input<{
                                name?: pulumi.Input<string>;
                                value?: pulumi.Input<string>;
                            }[]>;
                            path?: pulumi.Input<string>;
                            port?: pulumi.Input<string>;
                            scheme?: pulumi.Input<string>;
                        }[]>;
                        initialDelaySeconds?: pulumi.Input<number>;
                        periodSeconds?: pulumi.Input<number>;
                        successThreshold?: pulumi.Input<number>;
                        tcpSocket?: pulumi.Input<{
                            port: pulumi.Input<string>;
                        }[]>;
                        timeoutSeconds?: pulumi.Input<number>;
                    }[]>;
                    name: pulumi.Input<string>;
                    port?: pulumi.Input<{
                        containerPort: pulumi.Input<number>;
                        hostIp?: pulumi.Input<string>;
                        hostPort?: pulumi.Input<number>;
                        name?: pulumi.Input<string>;
                        protocol?: pulumi.Input<string>;
                    }[]>;
                    readinessProbe?: pulumi.Input<{
                        exec?: pulumi.Input<{
                            command?: pulumi.Input<pulumi.Input<string>[]>;
                        }[]>;
                        failureThreshold?: pulumi.Input<number>;
                        httpGet?: pulumi.Input<{
                            host?: pulumi.Input<string>;
                            httpHeader?: pulumi.Input<{
                                name?: pulumi.Input<string>;
                                value?: pulumi.Input<string>;
                            }[]>;
                            path?: pulumi.Input<string>;
                            port?: pulumi.Input<string>;
                            scheme?: pulumi.Input<string>;
                        }[]>;
                        initialDelaySeconds?: pulumi.Input<number>;
                        periodSeconds?: pulumi.Input<number>;
                        successThreshold?: pulumi.Input<number>;
                        tcpSocket?: pulumi.Input<{
                            port: pulumi.Input<string>;
                        }[]>;
                        timeoutSeconds?: pulumi.Input<number>;
                    }[]>;
                    resources?: pulumi.Input<{
                        limits?: pulumi.Input<{
                            cpu?: pulumi.Input<string>;
                            memory?: pulumi.Input<string>;
                        }[]>;
                        requests?: pulumi.Input<{
                            cpu?: pulumi.Input<string>;
                            memory?: pulumi.Input<string>;
                        }[]>;
                    }[]>;
                    securityContext?: pulumi.Input<{
                        capabilities?: pulumi.Input<{
                            add?: pulumi.Input<pulumi.Input<string>[]>;
                            drop?: pulumi.Input<pulumi.Input<string>[]>;
                        }[]>;
                        privileged?: pulumi.Input<boolean>;
                        readOnlyRootFilesystem?: pulumi.Input<boolean>;
                        runAsNonRoot?: pulumi.Input<boolean>;
                        runAsUser?: pulumi.Input<number>;
                        seLinuxOptions?: pulumi.Input<{
                            level?: pulumi.Input<string>;
                            role?: pulumi.Input<string>;
                            type?: pulumi.Input<string>;
                            user?: pulumi.Input<string>;
                        }[]>;
                    }[]>;
                    stdin?: pulumi.Input<boolean>;
                    stdinOnce?: pulumi.Input<boolean>;
                    terminationMessagePath?: pulumi.Input<string>;
                    tty?: pulumi.Input<boolean>;
                    volumeMount?: pulumi.Input<{
                        mountPath: pulumi.Input<string>;
                        name: pulumi.Input<string>;
                        readOnly?: pulumi.Input<boolean>;
                        subPath?: pulumi.Input<string>;
                    }[]>;
                    workingDir?: pulumi.Input<string>;
                }[]>;
                dnsPolicy?: pulumi.Input<string>;
                hostIpc?: pulumi.Input<boolean>;
                hostNetwork?: pulumi.Input<boolean>;
                hostPid?: pulumi.Input<boolean>;
                hostname?: pulumi.Input<string>;
                imagePullSecrets?: pulumi.Input<{
                    name: pulumi.Input<string>;
                }[]>;
                initContainer?: pulumi.Input<{
                    args?: pulumi.Input<pulumi.Input<string>[]>;
                    command?: pulumi.Input<pulumi.Input<string>[]>;
                    env?: pulumi.Input<{
                        name: pulumi.Input<string>;
                        value?: pulumi.Input<string>;
                        valueFrom?: pulumi.Input<{
                            configMapKeyRef?: pulumi.Input<{
                                key?: pulumi.Input<string>;
                                name?: pulumi.Input<string>;
                            }[]>;
                            fieldRef?: pulumi.Input<{
                                apiVersion?: pulumi.Input<string>;
                                fieldPath?: pulumi.Input<string>;
                            }[]>;
                            resourceFieldRef?: pulumi.Input<{
                                containerName?: pulumi.Input<string>;
                                resource: pulumi.Input<string>;
                            }[]>;
                            secretKeyRef?: pulumi.Input<{
                                key?: pulumi.Input<string>;
                                name?: pulumi.Input<string>;
                            }[]>;
                        }[]>;
                    }[]>;
                    envFrom?: pulumi.Input<{
                        configMapRef?: pulumi.Input<{
                            name?: pulumi.Input<string>;
                            optional?: pulumi.Input<boolean>;
                        }[]>;
                        prefix?: pulumi.Input<string>;
                        secretRef?: pulumi.Input<{
                            name?: pulumi.Input<string>;
                            optional?: pulumi.Input<boolean>;
                        }[]>;
                    }[]>;
                    image?: pulumi.Input<string>;
                    imagePullPolicy?: pulumi.Input<string>;
                    lifecycle?: pulumi.Input<{
                        postStart?: pulumi.Input<{
                            exec?: pulumi.Input<{
                                command?: pulumi.Input<pulumi.Input<string>[]>;
                            }[]>;
                            httpGet?: pulumi.Input<{
                                host?: pulumi.Input<string>;
                                httpHeader?: pulumi.Input<{
                                    name?: pulumi.Input<string>;
                                    value?: pulumi.Input<string>;
                                }[]>;
                                path?: pulumi.Input<string>;
                                port?: pulumi.Input<string>;
                                scheme?: pulumi.Input<string>;
                            }[]>;
                            tcpSocket?: pulumi.Input<{
                                port: pulumi.Input<string>;
                            }[]>;
                        }[]>;
                        preStop?: pulumi.Input<{
                            exec?: pulumi.Input<{
                                command?: pulumi.Input<pulumi.Input<string>[]>;
                            }[]>;
                            httpGet?: pulumi.Input<{
                                host?: pulumi.Input<string>;
                                httpHeader?: pulumi.Input<{
                                    name?: pulumi.Input<string>;
                                    value?: pulumi.Input<string>;
                                }[]>;
                                path?: pulumi.Input<string>;
                                port?: pulumi.Input<string>;
                                scheme?: pulumi.Input<string>;
                            }[]>;
                            tcpSocket?: pulumi.Input<{
                                port: pulumi.Input<string>;
                            }[]>;
                        }[]>;
                    }[]>;
                    livenessProbe?: pulumi.Input<{
                        exec?: pulumi.Input<{
                            command?: pulumi.Input<pulumi.Input<string>[]>;
                        }[]>;
                        failureThreshold?: pulumi.Input<number>;
                        httpGet?: pulumi.Input<{
                            host?: pulumi.Input<string>;
                            httpHeader?: pulumi.Input<{
                                name?: pulumi.Input<string>;
                                value?: pulumi.Input<string>;
                            }[]>;
                            path?: pulumi.Input<string>;
                            port?: pulumi.Input<string>;
                            scheme?: pulumi.Input<string>;
                        }[]>;
                        initialDelaySeconds?: pulumi.Input<number>;
                        periodSeconds?: pulumi.Input<number>;
                        successThreshold?: pulumi.Input<number>;
                        tcpSocket?: pulumi.Input<{
                            port: pulumi.Input<string>;
                        }[]>;
                        timeoutSeconds?: pulumi.Input<number>;
                    }[]>;
                    name: pulumi.Input<string>;
                    port?: pulumi.Input<{
                        containerPort: pulumi.Input<number>;
                        hostIp?: pulumi.Input<string>;
                        hostPort?: pulumi.Input<number>;
                        name?: pulumi.Input<string>;
                        protocol?: pulumi.Input<string>;
                    }[]>;
                    readinessProbe?: pulumi.Input<{
                        exec?: pulumi.Input<{
                            command?: pulumi.Input<pulumi.Input<string>[]>;
                        }[]>;
                        failureThreshold?: pulumi.Input<number>;
                        httpGet?: pulumi.Input<{
                            host?: pulumi.Input<string>;
                            httpHeader?: pulumi.Input<{
                                name?: pulumi.Input<string>;
                                value?: pulumi.Input<string>;
                            }[]>;
                            path?: pulumi.Input<string>;
                            port?: pulumi.Input<string>;
                            scheme?: pulumi.Input<string>;
                        }[]>;
                        initialDelaySeconds?: pulumi.Input<number>;
                        periodSeconds?: pulumi.Input<number>;
                        successThreshold?: pulumi.Input<number>;
                        tcpSocket?: pulumi.Input<{
                            port: pulumi.Input<string>;
                        }[]>;
                        timeoutSeconds?: pulumi.Input<number>;
                    }[]>;
                    resources?: pulumi.Input<{
                        limits?: pulumi.Input<{
                            cpu?: pulumi.Input<string>;
                            memory?: pulumi.Input<string>;
                        }[]>;
                        requests?: pulumi.Input<{
                            cpu?: pulumi.Input<string>;
                            memory?: pulumi.Input<string>;
                        }[]>;
                    }[]>;
                    securityContext?: pulumi.Input<{
                        capabilities?: pulumi.Input<{
                            add?: pulumi.Input<pulumi.Input<string>[]>;
                            drop?: pulumi.Input<pulumi.Input<string>[]>;
                        }[]>;
                        privileged?: pulumi.Input<boolean>;
                        readOnlyRootFilesystem?: pulumi.Input<boolean>;
                        runAsNonRoot?: pulumi.Input<boolean>;
                        runAsUser?: pulumi.Input<number>;
                        seLinuxOptions?: pulumi.Input<{
                            level?: pulumi.Input<string>;
                            role?: pulumi.Input<string>;
                            type?: pulumi.Input<string>;
                            user?: pulumi.Input<string>;
                        }[]>;
                    }[]>;
                    stdin?: pulumi.Input<boolean>;
                    stdinOnce?: pulumi.Input<boolean>;
                    terminationMessagePath?: pulumi.Input<string>;
                    tty?: pulumi.Input<boolean>;
                    volumeMount?: pulumi.Input<{
                        mountPath: pulumi.Input<string>;
                        name: pulumi.Input<string>;
                        readOnly?: pulumi.Input<boolean>;
                        subPath?: pulumi.Input<string>;
                    }[]>;
                    workingDir?: pulumi.Input<string>;
                }[]>;
                nodeName?: pulumi.Input<string>;
                nodeSelector?: pulumi.Input<{
                    [key: string]: any;
                }>;
                restartPolicy?: pulumi.Input<string>;
                securityContext?: pulumi.Input<{
                    fsGroup?: pulumi.Input<number>;
                    runAsNonRoot?: pulumi.Input<boolean>;
                    runAsUser?: pulumi.Input<number>;
                    seLinuxOptions?: pulumi.Input<{
                        level?: pulumi.Input<string>;
                        role?: pulumi.Input<string>;
                        type?: pulumi.Input<string>;
                        user?: pulumi.Input<string>;
                    }[]>;
                    supplementalGroups?: pulumi.Input<pulumi.Input<number>[]>;
                }[]>;
                serviceAccountName?: pulumi.Input<string>;
                subdomain?: pulumi.Input<string>;
                terminationGracePeriodSeconds?: pulumi.Input<number>;
                volume?: pulumi.Input<{
                    awsElasticBlockStore?: pulumi.Input<{
                        fsType?: pulumi.Input<string>;
                        partition?: pulumi.Input<number>;
                        readOnly?: pulumi.Input<boolean>;
                        volumeId: pulumi.Input<string>;
                    }[]>;
                    azureDisk?: pulumi.Input<{
                        cachingMode: pulumi.Input<string>;
                        dataDiskUri: pulumi.Input<string>;
                        diskName: pulumi.Input<string>;
                        fsType?: pulumi.Input<string>;
                        readOnly?: pulumi.Input<boolean>;
                    }[]>;
                    azureFile?: pulumi.Input<{
                        readOnly?: pulumi.Input<boolean>;
                        secretName: pulumi.Input<string>;
                        shareName: pulumi.Input<string>;
                    }[]>;
                    cephFs?: pulumi.Input<{
                        monitors: pulumi.Input<pulumi.Input<string>[]>;
                        path?: pulumi.Input<string>;
                        readOnly?: pulumi.Input<boolean>;
                        secretFile?: pulumi.Input<string>;
                        secretRef?: pulumi.Input<{
                            name?: pulumi.Input<string>;
                        }[]>;
                        user?: pulumi.Input<string>;
                    }[]>;
                    cinder?: pulumi.Input<{
                        fsType?: pulumi.Input<string>;
                        readOnly?: pulumi.Input<boolean>;
                        volumeId: pulumi.Input<string>;
                    }[]>;
                    configMap?: pulumi.Input<{
                        defaultMode?: pulumi.Input<number>;
                        items?: pulumi.Input<{
                            key?: pulumi.Input<string>;
                            mode?: pulumi.Input<number>;
                            path?: pulumi.Input<string>;
                        }[]>;
                        name?: pulumi.Input<string>;
                    }[]>;
                    downwardApi?: pulumi.Input<{
                        defaultMode?: pulumi.Input<number>;
                        items?: pulumi.Input<{
                            fieldRef: pulumi.Input<{
                                apiVersion?: pulumi.Input<string>;
                                fieldPath?: pulumi.Input<string>;
                            }[]>;
                            mode?: pulumi.Input<number>;
                            path: pulumi.Input<string>;
                            resourceFieldRef?: pulumi.Input<{
                                containerName: pulumi.Input<string>;
                                quantity?: pulumi.Input<string>;
                                resource: pulumi.Input<string>;
                            }[]>;
                        }[]>;
                    }[]>;
                    emptyDir?: pulumi.Input<{
                        medium?: pulumi.Input<string>;
                    }[]>;
                    fc?: pulumi.Input<{
                        fsType?: pulumi.Input<string>;
                        lun: pulumi.Input<number>;
                        readOnly?: pulumi.Input<boolean>;
                        targetWwNs: pulumi.Input<pulumi.Input<string>[]>;
                    }[]>;
                    flexVolume?: pulumi.Input<{
                        driver: pulumi.Input<string>;
                        fsType?: pulumi.Input<string>;
                        options?: pulumi.Input<{
                            [key: string]: any;
                        }>;
                        readOnly?: pulumi.Input<boolean>;
                        secretRef?: pulumi.Input<{
                            name?: pulumi.Input<string>;
                        }[]>;
                    }[]>;
                    flocker?: pulumi.Input<{
                        datasetName?: pulumi.Input<string>;
                        datasetUuid?: pulumi.Input<string>;
                    }[]>;
                    gcePersistentDisk?: pulumi.Input<{
                        fsType?: pulumi.Input<string>;
                        partition?: pulumi.Input<number>;
                        pdName: pulumi.Input<string>;
                        readOnly?: pulumi.Input<boolean>;
                    }[]>;
                    gitRepo?: pulumi.Input<{
                        directory?: pulumi.Input<string>;
                        repository?: pulumi.Input<string>;
                        revision?: pulumi.Input<string>;
                    }[]>;
                    glusterfs?: pulumi.Input<{
                        endpointsName: pulumi.Input<string>;
                        path: pulumi.Input<string>;
                        readOnly?: pulumi.Input<boolean>;
                    }[]>;
                    hostPath?: pulumi.Input<{
                        path?: pulumi.Input<string>;
                    }[]>;
                    iscsi?: pulumi.Input<{
                        fsType?: pulumi.Input<string>;
                        iqn: pulumi.Input<string>;
                        iscsiInterface?: pulumi.Input<string>;
                        lun?: pulumi.Input<number>;
                        readOnly?: pulumi.Input<boolean>;
                        targetPortal: pulumi.Input<string>;
                    }[]>;
                    name?: pulumi.Input<string>;
                    nfs?: pulumi.Input<{
                        path: pulumi.Input<string>;
                        readOnly?: pulumi.Input<boolean>;
                        server: pulumi.Input<string>;
                    }[]>;
                    persistentVolumeClaim?: pulumi.Input<{
                        claimName?: pulumi.Input<string>;
                        readOnly?: pulumi.Input<boolean>;
                    }[]>;
                    photonPersistentDisk?: pulumi.Input<{
                        fsType?: pulumi.Input<string>;
                        pdId: pulumi.Input<string>;
                    }[]>;
                    quobyte?: pulumi.Input<{
                        group?: pulumi.Input<string>;
                        readOnly?: pulumi.Input<boolean>;
                        registry: pulumi.Input<string>;
                        user?: pulumi.Input<string>;
                        volume: pulumi.Input<string>;
                    }[]>;
                    rbd?: pulumi.Input<{
                        cephMonitors: pulumi.Input<pulumi.Input<string>[]>;
                        fsType?: pulumi.Input<string>;
                        keyring?: pulumi.Input<string>;
                        radosUser?: pulumi.Input<string>;
                        rbdImage: pulumi.Input<string>;
                        rbdPool?: pulumi.Input<string>;
                        readOnly?: pulumi.Input<boolean>;
                        secretRef?: pulumi.Input<{
                            name?: pulumi.Input<string>;
                        }[]>;
                    }[]>;
                    secret?: pulumi.Input<{
                        defaultMode?: pulumi.Input<number>;
                        items?: pulumi.Input<{
                            key?: pulumi.Input<string>;
                            mode?: pulumi.Input<number>;
                            path?: pulumi.Input<string>;
                        }[]>;
                        optional?: pulumi.Input<boolean>;
                        secretName?: pulumi.Input<string>;
                    }[]>;
                    vsphereVolume?: pulumi.Input<{
                        fsType?: pulumi.Input<string>;
                        volumePath: pulumi.Input<string>;
                    }[]>;
                }[]>;
            }[]>;
            subdomain?: pulumi.Input<string>;
            terminationGracePeriodSeconds?: pulumi.Input<string>;
            volume?: pulumi.Input<string>;
        }[]>;
    }[]>;
@joeduffy
Copy link
Member

WHOAH!!!!

Should we move this issue to pulumi-terraform? We even have a TODO for this at the moment: https://github.com/pulumi/pulumi-terraform/blob/master/pkg/tfgen/generate_nodejs.go#L895. Frankly, it wouldn't be too difficult, the primary challenge is giving the types good names; I suppose we could derive them from the property name... but then I worry we will have 100s of types in the top level of our Kubernetes package, cluttering everything up...

/cc @CyrusNajmabadi in case he has ideas on this.

@lukehoban
Copy link
Member Author

lukehoban commented Feb 17, 2018

So - I think we're going to have to take a different approach here.

Kubernetes actually has a very well formalized type system - see for example: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#podspec-v1-core. We really need to project this whole type system into our model so that we can talk about, name, and design APIs over the parts of the configuration bags given to these high level objects - like Deployment.

Unfortunately, that metadata simply isn't really directly present in the Terraform provider - it's all inlined into one big bag. There is no mention of things like PodSpec, PodTemplate, PodTemplateSpec.

I think we're going to want to project each of these granular types/shapes from core Kuberenets API object specifications, and make sure that these are compatible with the shapes that the TF provider accepts (which really they better be - or else we will want to suggest changes to the official TF Kuberenets provider and/or will need to create a TF provider that does actually map these 1:1 and use that instead). We would then introduce these types as an overlay so that things showed up with nice typing. That would though mean we'll need to maintain the versioning of these types separately from the versioning of the TF provider.

This will, for example, also ensure we can support things like what ksonnet does with having simple factories that build parts of Kuberentes objects from references to other objects and pieces of objects. Without these granular types, there will be no way to offer that in a type-safe way - which would be a big shame.

@lukehoban
Copy link
Member Author

I think we're going to want to project each of these granular types/shapes from core Kuberenets API object specifications, and make sure that these are compatible with the shapes that the TF provider accepts.

I took a pass at doing this manually to see what this would need to look like. Results below. Just unwinding Deployment into all it's constituent parts leads to >60 distinct type definitions. Overall, Kube has a little over 200 types defined.

A few takeaways:

  1. We'll need both input and output shapes for every type - as these are different (optional vs. not, some properties which can't be provided as input but are added by Kube itself)
  2. We cannot build these types directly from terraform-provider-kubernetes, as it dynamically builds up the large types using helpers - without ever having a fixed named type for the constituent parts.
  3. We also can't build this purely from Kube docs - we need to know the rules by which the TF provider is mapping things (like struct embedding/pluralization, precise typing used in TF (for example, one place where Kube allows string | number but TF only allows string), etc.). We have to get the TF provider types exactly right to be able to use them as an overlay. We have to hope that the TF provider consistently maps same named type in each place it is used (it looks like it will largely do this just because of reuse of dynamic helpers).
  4. We really have to fix List parameters should be flattened if MaxItems == 1 pulumi-terraform#37 and Pluralize? pulumi-terraform#11.
  5. These types are necessary to be able to offer any meaningful sort of abstraction and componentization for Kubernetes use cases (assuming we want strong typing) - that is, to offer a strogly-typed language-aligned way of doing what tools like ksonnet do today (but better!).

Frankly, I think we're going to have to do this manually at least initially, and then use these manually defined types as overlays. We'll need to be careful to confirm that these types are assignment compatible in the appropriate directions with the raw types that the TF provider would create automatically so that we don't break the TF bridge at runtime.

import * as pulumi from "pulumi";

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#objectmeta-v1-meta
export interface ObjectMeta {
    annotations?: pulumi.Input<{ [key: string]: any }>;
    generateName?: pulumi.Input<string>;
    generation?: pulumi.Input<number>;
    labels?: pulumi.Input<{ [key: string]: any }>;
    name?: pulumi.Input<string>;
    namespace?: pulumi.Input<string>;
    resourceVersion?: pulumi.Input<string>;
    selfLink?: pulumi.Input<string>;
    uid?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#rollingupdatedeployment-v1-apps
export interface RollingUpdateDeployment {
    maxSurge?: pulumi.Input<string>;
    maxUnavailable?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#deploymentstrategy-v1-apps
export interface DeploymentStrategy {
    rollingUpdate?: pulumi.Input<RollingUpdateDeployment[]>;
    type?: pulumi.Input<string>; // "Recreate" | "RollingUpdate"
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#podtemplatespec-v1-core
export interface PodTemplateSpec {
    metadata?: pulumi.Input<ObjectMeta[]>;
    spec: pulumi.Input<PodSpec[]>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#execaction-v1-core
export interface ExecAction {
    command?: pulumi.Input<pulumi.Input<string>[]>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#httpheader-v1-core
export interface HttpHeader {
    name?: pulumi.Input<string>;
    value?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#httpgetaction-v1-core
export interface HTTPGetAction {
    host?: pulumi.Input<string>
    httpHeader?: pulumi.Input<HttpHeader[]>
    path?: pulumi.Input<string>;
    port?: pulumi.Input<string>;
    scheme?: pulumi.Input<string>;
}

export interface TCPSocketAction {
    // host?: string
    port: pulumi.Input<string>
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#handler-v1-core
export interface Handler {
    exec?: pulumi.Input<ExecAction[]>;
    httpGet?: pulumi.Input<HTTPGetAction[]>;
    tcpSocket?: pulumi.Input<TCPSocketAction[]>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#lifecycle-v1-core
export interface Lifecycle {
    postStart?: pulumi.Input<Handler[]>;
    preStop?: pulumi.Input<Handler[]>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#probe-v1-core
export interface Probe {
    exec?: pulumi.Input<ExecAction[]>;
    failureThreshold?: pulumi.Input<number>;
    httpGet?: pulumi.Input<HTTPGetAction[]>;
    initialDelaySeconds?: pulumi.Input<number>;
    periodSeconds?: pulumi.Input<number>;
    successThreshold?: pulumi.Input<number>;
    tcpSocket?: pulumi.Input<TCPSocketAction[]>;
    timeoutSeconds?: pulumi.Input<number>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#configmapkeyselector-v1-core
export interface ConfigMapKeySelector {
    key?: pulumi.Input<string>;
    name?: pulumi.Input<string>;
    // optional: boolean
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#objectfieldselector-v1-core
export interface ObjectFieldSelector {
    apiVersion?: pulumi.Input<string>;
    fieldPath?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#secretkeyselector-v1-core
export interface SecretKeySelector {
    key?: pulumi.Input<string>;
    name?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#envvarsource-v1-core
export interface EnvVarSource {
    configMapKeyRef?: pulumi.Input<ConfigMapKeySelector[]>;
    fieldRef?: pulumi.Input<ObjectFieldSelector[]>;
    resourceFieldRef?: pulumi.Input<ResourceFieldSelector[]>;
    secretKeyRef?: pulumi.Input<SecretKeySelector[]>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#envvar-v1-core
export interface EnvVar {
    name: pulumi.Input<string>;
    value?: pulumi.Input<string>;
    valueFrom?: pulumi.Input<EnvVarSource[]>;
}

export interface ConfigMapEnvSource {
    name?: pulumi.Input<string>;
    optional?: pulumi.Input<boolean>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#secretenvsource-v1-core
export interface SecretEnvSource {
    name?: pulumi.Input<string>;
    optional?: pulumi.Input<boolean>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#envfromsource-v1-core
export interface EnvFromSource {
    configMapRef?: pulumi.Input<ConfigMapEnvSource[]>;
    prefix?: pulumi.Input<string>;
    secretRef?: pulumi.Input<SecretEnvSource[]>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#containerport-v1-core
export interface ContainerPort {
    containerPort: pulumi.Input<number>;
    hostIp?: pulumi.Input<string>;
    hostPort?: pulumi.Input<number>;
    name?: pulumi.Input<string>;
    protocol?: pulumi.Input<string>; // "TCP" | "UDP"
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#capabilities-v1-core
export interface Capabilities {
    add?: pulumi.Input<pulumi.Input<string>[]>;
    drop?: pulumi.Input<pulumi.Input<string>[]>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#securitycontext-v1-core
export interface SecurityContext {
    // allowPrivilegeEscalation: boolean
    capabilities?: pulumi.Input<Capabilities[]>;
    privileged?: pulumi.Input<boolean>;
    readOnlyRootFilesystem?: pulumi.Input<boolean>;
    runAsNonRoot?: pulumi.Input<boolean>;
    runAsUser?: pulumi.Input<number>;
    seLinuxOptions?: pulumi.Input<SELinuxOptions[]>;
}

export interface ResourceRequirementsObject {
    cpu?: pulumi.Input<string>;
    memory?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#resourcerequirements-v1-core
export interface ResourceRequirements {
    limits?: pulumi.Input<ResourceRequirementsObject[]>;
    requests?: pulumi.Input<ResourceRequirementsObject[]>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#volumemount-v1-core
export interface VolumeMount {
    mountPath: pulumi.Input<string>;
    // mountPropagation?: string
    name: pulumi.Input<string>;
    readOnly?: pulumi.Input<boolean>;
    subPath?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#container-v1-core
export interface Container {
    args?: pulumi.Input<pulumi.Input<string>[]>;
    command?: pulumi.Input<pulumi.Input<string>[]>;
    env?: pulumi.Input<EnvVar[]>;
    envFrom?: pulumi.Input<EnvFromSource[]>;
    image?: pulumi.Input<string>;
    imagePullPolicy?: pulumi.Input<string>;
    lifecycle?: pulumi.Input<Lifecycle[]>;
    livenessProbe?: pulumi.Input<Probe[]>;
    name: pulumi.Input<string>;
    port?: pulumi.Input<ContainerPort[]>;
    readinessProbe?: pulumi.Input<Probe[]>;
    resources?: pulumi.Input<ResourceRequirements[]>;
    securityContext?: pulumi.Input<SecurityContext[]>;
    stdin?: pulumi.Input<boolean>;
    stdinOnce?: pulumi.Input<boolean>;
    terminationMessagePath?: pulumi.Input<string>;
    tty?: pulumi.Input<boolean>;
    volumeMount?: pulumi.Input<VolumeMount[]>;
    workingDir?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#localobjectreference-v1-core
export interface LocalObjectReference {
    name: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#selinuxoptions-v1-core
export interface SELinuxOptions {
    level?: pulumi.Input<string>;
    role?: pulumi.Input<string>;
    type?: pulumi.Input<string>;
    user?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#podsecuritycontext-v1-core
export interface PodSecurityContext {
    fsGroup?: pulumi.Input<number>;
    runAsNonRoot?: pulumi.Input<boolean>;
    runAsUser?: pulumi.Input<number>;
    seLinuxOptions?: pulumi.Input<SELinuxOptions[]>;
    supplementalGroups?: pulumi.Input<pulumi.Input<number>[]>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#nodeselector-v1-core
export interface NodeSelector {
    [key: string]: any
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#podspec-v1-core
export interface PodSpec {
    activeDeadlineSeconds?: pulumi.Input<number>;
    // affinity: Affinity
    automountServiceAccountToken?: pulumi.Input<boolean>;
    container?: pulumi.Input<Container[]>;
    // dnsConfig: PodDNSConfig;
    dnsPolicy?: pulumi.Input<string>;
    // hostAliases: HostAlias[];
    hostIpc?: pulumi.Input<boolean>;
    hostNetwork?: pulumi.Input<boolean>;
    hostPid?: pulumi.Input<boolean>;
    hostname?: pulumi.Input<string>;
    imagePullSecrets?: pulumi.Input<LocalObjectReference[]>;
    initContainer?: pulumi.Input<Container[]>;
    nodeName?: pulumi.Input<string>;
    nodeSelector?: pulumi.Input<NodeSelector>;
    // priority
    // priorityClassName
    restartPolicy?: pulumi.Input<string>;
    // schedulerName
    securityContext?: pulumi.Input<PodSecurityContext[]>;
    serviceAccountName?: pulumi.Input<string>;
    subdomain?: pulumi.Input<string>;
    terminationGracePeriodSeconds?: pulumi.Input<number>;
    volume?: pulumi.Input<Volume[]>
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#awselasticblockstorevolumesource-v1-core
export interface AWSElasticBlockStoreVolumeSource {
    fsType?: pulumi.Input<string>;
    partition?: pulumi.Input<number>;
    readOnly?: pulumi.Input<boolean>;
    volumeId: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#azurediskvolumesource-v1-core
export interface AzureDiskVolumeSource {
    cachingMode: pulumi.Input<string>;
    dataDiskUri: pulumi.Input<string>;
    diskName: pulumi.Input<string>;
    fsType?: pulumi.Input<string>;
    readOnly?: pulumi.Input<boolean>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#vspherevirtualdiskvolumesource-v1-core
export interface VsphereVirtualDiskVolumeSource {
    fsType?: pulumi.Input<string>;
    volumePath: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#secretreference-v1-core
export interface SecretReference {
    name?: pulumi.Input<string>
    // namespace?: string
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#rbdvolumesource-v1-core
export interface RBDVolumeSource {
    cephMonitors: pulumi.Input<pulumi.Input<string>[]>;
    fsType?: pulumi.Input<string>;
    keyring?: pulumi.Input<string>;
    radosUser?: pulumi.Input<string>;
    rbdImage: pulumi.Input<string>;
    rbdPool?: pulumi.Input<string>;
    readOnly?: pulumi.Input<boolean>;
    secretRef?: pulumi.Input<SecretReference[]>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#keytopath-v1-core
export interface KeyToPath {
    key?: pulumi.Input<string>;
    mode?: pulumi.Input<number>;
    path?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#secretvolumesource-v1-core
export interface SecretVolumeSource {
    defaultMode?: pulumi.Input<number>;
    items?: pulumi.Input<KeyToPath[]>;
    optional?: pulumi.Input<boolean>;
    secretName?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#quobytevolumesource-v1-core
export interface QuobyteVolumeSource {
    group?: pulumi.Input<string>;
    readOnly?: pulumi.Input<boolean>;
    registry: pulumi.Input<string>;
    user?: pulumi.Input<string>;
    volume: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#objectfieldselector-v1-core
export interface ObjectFieldSelector {
    apiVersion?: pulumi.Input<string>;
    fieldPath?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#resourcefieldselector-v1-core
export interface ResourceFieldSelector {
    containerName: pulumi.Input<string>;
    quantity?: pulumi.Input<string>;
    resource: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#downwardapivolumefile-v1-core
export interface DownwardAPIVolumeFile {
    fieldRef: pulumi.Input<ObjectFieldSelector[]>;
    mode?: pulumi.Input<number>;
    path: pulumi.Input<string>;
    resourceFieldRef?: pulumi.Input<ResourceFieldSelector[]>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#downwardapivolumesource-v1-core
export interface DownwardAPIVolumeSource {
    defaultMode?: pulumi.Input<number>
    items?: pulumi.Input<DownwardAPIVolumeFile[]>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#azurefilevolumesource-v1-core
export interface AzureFileVolumeSource {
    readOnly?: pulumi.Input<boolean>;
    secretName: pulumi.Input<string>;
    shareName: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#cephfsvolumesource-v1-core
export interface CephFSVolumeSource {
    monitors: pulumi.Input<pulumi.Input<string>[]>;
    path?: pulumi.Input<string>;
    readOnly?: pulumi.Input<boolean>;
    secretFile?: pulumi.Input<string>;
    secretRef?: pulumi.Input<{ name?: pulumi.Input<string> }[]>;
    user?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#cindervolumesource-v1-core
export interface CinderVolumeSource {
    fsType?: pulumi.Input<string>;
    readOnly?: pulumi.Input<boolean>;
    volumeId: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#configmapvolumesource-v1-core
export interface ConfigMapVolumeSource {
    defaultMode?: pulumi.Input<number>;
    items?: pulumi.Input<KeyToPath[]>;
    name?: pulumi.Input<string>;
    // optional
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#fcvolumesource-v1-core
export interface FCVolumeSource {
    fsType?: pulumi.Input<string>;
    lun: pulumi.Input<number>;
    readOnly?: pulumi.Input<boolean>;
    targetWwNs: pulumi.Input<pulumi.Input<string>[]>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#flexvolumesource-v1-core
export interface FlexVolumeSource {
    driver: pulumi.Input<string>;
    fsType?: pulumi.Input<string>;
    options?: pulumi.Input<{ [key: string]: any }>;
    readOnly?: pulumi.Input<boolean>;
    secretRef?: pulumi.Input<{ name?: pulumi.Input<string> }[]>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#iscsivolumesource-v1-core
export interface ISCSIVolumeSource {
    fsType?: pulumi.Input<string>;
    iqn: pulumi.Input<string>;
    iscsiInterface?: pulumi.Input<string>;
    lun?: pulumi.Input<number>;
    readOnly?: pulumi.Input<boolean>;
    targetPortal: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#gcepersistentdiskvolumesource-v1-core
export interface GCEPersistentDiskVolumeSource {
    fsType?: pulumi.Input<string>;
    partition?: pulumi.Input<number>;
    pdName: pulumi.Input<string>;
    readOnly?: pulumi.Input<boolean>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#flockervolumesource-v1-core
export interface FlockerVolumeSource {
    datasetName?: pulumi.Input<string>;
    datasetUuid?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#gitrepovolumesource-v1-core
export interface GitRepoVolumeSource {
    directory?: pulumi.Input<string>;
    repository?: pulumi.Input<string>;
    revision?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#glusterfsvolumesource-v1-core
export interface GlusterfsVolumeSource {
    endpointsName: pulumi.Input<string>;
    path: pulumi.Input<string>;
    readOnly?: pulumi.Input<boolean>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#hostpathvolumesource-v1-core
export interface HostPathVolumeSource{
    path?: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#nfsvolumesource-v1-core
export interface NFSVolumeSource {
    path: pulumi.Input<string>;
    readOnly?: pulumi.Input<boolean>;
    server: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#persistentvolumeclaimvolumesource-v1-core
export interface PersistentVolumeClaimVolumeSource {
    claimName?: pulumi.Input<string>;
    readOnly?: pulumi.Input<boolean>;
}

export interface EmptyDirVolumeSource {
    medium?: pulumi.Input<string>;
}

export interface PhotonPersistentDiskVolumeSource {
    fsType?: pulumi.Input<string>;
    pdId: pulumi.Input<string>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#volume-v1-core
export interface Volume {
    awsElasticBlockStore?: pulumi.Input<AWSElasticBlockStoreVolumeSource[]>
    azureDisk?: pulumi.Input<AzureDiskVolumeSource[]>
    azureFile?: pulumi.Input<AzureFileVolumeSource[]>
    cephFs?: pulumi.Input<CephFSVolumeSource[]>;
    cinder?: pulumi.Input<CinderVolumeSource[]>;
    configMap?: pulumi.Input<ConfigMapVolumeSource[]>;
    downwardApi?: pulumi.Input<DownwardAPIVolumeSource[]>;
    emptyDir?: pulumi.Input<EmptyDirVolumeSource[]>;
    fc?: pulumi.Input<FCVolumeSource[]>;
    flexVolume?: pulumi.Input<FlexVolumeSource[]>;
    flocker?: pulumi.Input<FlockerVolumeSource[]>;
    gcePersistentDisk?: pulumi.Input<GCEPersistentDiskVolumeSource[]>;
    gitRepo?: pulumi.Input<GitRepoVolumeSource[]>;
    glusterfs?: pulumi.Input<GlusterfsVolumeSource[]>;
    hostPath?: pulumi.Input<HostPathVolumeSource[]>;
    iscsi?: pulumi.Input<ISCSIVolumeSource[]>;
    name?: pulumi.Input<string>;
    nfs?: pulumi.Input<NFSVolumeSource[]>;
    persistentVolumeClaim?: pulumi.Input<PersistentVolumeClaimVolumeSource[]>;
    photonPersistentDisk?: pulumi.Input<PhotonPersistentDiskVolumeSource[]>;
    quobyte?: pulumi.Input<QuobyteVolumeSource[]>;
    rbd?: pulumi.Input<RBDVolumeSource[]>;
    secret?: pulumi.Input<SecretVolumeSource[]>;
    vsphereVolume?: pulumi.Input<VsphereVirtualDiskVolumeSource[]>;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#labelselector-v1-meta
export interface LabelSelector {
    [key: string]: any;
    // matchExpressions: LabelSelectorRequirement[]
    // matchLabels: any
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#deploymentspec-v1-apps
export interface DeploymentSpec {
    minReadySeconds?: pulumi.Input<number>;
    replicas?: pulumi.Input<number>;
    selector?: pulumi.Input<LabelSelector>;
    strategy?: pulumi.Input<DeploymentStrategy[]>;
    template: pulumi.Input<PodTemplateSpec[]>;
    // paused: boolean;
    // progressDeadlineSeconds: number;
    // revisionHistoryLimit: number;
}

// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.9/#deployment-v1-apps
export interface Deployment {
    metadata?: pulumi.Input<ObjectMeta[]>;
    spec: pulumi.Input<DeploymentSpec[]>;
    // apiVersion
    // kind
    // status
}

@joeduffy
Copy link
Member

Do you think doing some code-gen based on https://raw.githubusercontent.com/kubernetes/kubernetes/master/api/openapi-spec/swagger.json would give us a decent start, even if mapping to the TF provider is a manual exercise? Or do they vary too much?

@lukehoban
Copy link
Member Author

Do you think doing some code-gen based on https://raw.githubusercontent.com/kubernetes/kubernetes/master/api/openapi-spec/swagger.json would give us a decent start, even if mapping to the TF provider is a manual exercise? Or do they vary too much?

Probably - at least a decent start. Having it as a persistent source of truth with configured divergences (like we do for TFGen), seems a little more complex, given lots of little divergences - but definitely not impossible. Probably worth trying to write that tool and see how close we can get it.

@lukehoban
Copy link
Member Author

BTW - point (3) above addresses some of the challenges with generating this from Kube docs / API specs.

@lukehoban
Copy link
Member Author

This was addressed as part of #37.

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

No branches or pull requests

2 participants