Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Ad hoc aggregations of registration data for a particular entity could be performed to give descriptive information about client config compatibility to the user. For example, all versions of clients that registered with an entity along with the supported configs for each version of client could be aggregated and returned to the user in the DescribeClientConfigsResponse

Public Interfaces

Admin Client Changes

Admin client calls will be added to support {Describe, Alter}ClientConfigs.

...


Network Protocol

Code Block
titleDescribeClientConfigs
{
  "apiKey": 50,
  "type": "request",
  "name": "DescribeClientConfigsRequest",
  "validVersions": "0",
  "flexibleVersions": "none",
  "fields": [
    { "name": "Components", "type": "[]ComponentData", "versions": "0+",
      "about": "Filter components to apply to config entities.", "fields": [
      { "name": "EntityType", "type": "string", "versions": "0+",
        "about": "The entity type that the filter component applies to." },
      { "name": "MatchType", "type": "int8", "versions": "0+",
        "about": "How to match the entity {0 = exact name, 1 = default name, 2 = any specified name}." },
      { "name": "Match", "type": "string", "versions": "0+", "nullableVersions": "0+",
        "about": "The string to match against, or null if unused for the match type." }
    ]},
    { "name": "SupportedConfigs", "type": "[]string", "versions": "0+", "nullableVersions": "0+",
      "about": "The configuration keys to register, or null if not registering configuration keys." },
    { "name": "ResolveEntity", "type": "bool", "versions": "0+",
      "about": "True if an application is requesting dynamic configs for itself, false otherwise." },
    { "name": "Strict", "type": "bool", "versions": "0+",
      "about": "Whether the match is strict, i.e. should exclude entities with unspecified entity types." }
  ]
}


{
  "apiKey": 50,
  "type": "response",
  "name": "DescribeClientConfigsResponse",
  "validVersions": "0",
  "flexibleVersions": "none",
  "fields": [
    { "name": "ThrottleTimeMs", "type": "int32", "versions": "0+",
      "about": "The duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota." },
    { "name": "ErrorCode", "type": "int16", "versions": "0+",
      "about": "The error code, or `0` if the config description succeeded." },
    { "name": "ErrorMessage", "type": "string", "versions": "0+", "nullableVersions": "0+",
      "about": "The error message, or `null` if the config description succeeded." },
    { "name": "Entries", "type": "[]EntryData", "versions": "0+", "nullableVersions": "0+",
      "about": "A result entry.", "fields": [
      { "name": "Entity", "type": "[]EntityData", "versions": "0+",
        "about": "The config entity description.", "fields": [
        { "name": "EntityType", "type": "string", "versions": "0+",
          "about": "The entity type." },
        { "name": "EntityName", "type": "string", "versions": "0+", "nullableVersions": "0+",
          "about": "The entity name, or null if the default." },
        { "name": "EntityCompatibility", "type": "[]VersionData", "versions": "0+",
			"about": "Every software name and version of clients that registered configs with the broker along with the configs supported by that software name and version.", "fields": [
            { "name": "ClientInformation", "type": "string", "versions": "0+", 
              "about": "The software name and version of one or more clients that registered configs under this entity." },
            { "name": "SupportedConfigs", "type": "[]string", "versions": "0+",
              "about": "The dynamic configs available for the clients with this software name and version." }
          ]}
        ]},
      	{ "name": "Values", "type": "[]ValueData", "versions": "0+",
		  "about": "The config values for the entity.", "fields": [
          { "name": "Key", "type": "string", "versions": "0+",
            "about": "The configuration key." },
          { "name": "Value", "type": "string", "versions": "0+",
            "about": "The configuration value." }
        ]}
      ]}

    ]}
  ]
}


...

Code Block
titleAlterClientConfigs
{
  "apiKey": 51,
  "type": "request",
  "name": "AlterClientConfigsRequest",
  "validVersions": "0",
  "flexibleVersions": "none",
  "fields": [
    { "name": "Entries", "type": "[]EntryData", "versions": "0+",
      "about": "The configuration entries to alter.", "fields": [
      { "name": "Entity", "type": "[]EntityData", "versions": "0+",
        "about": "The config entity to alter.", "fields": [
        { "name": "EntityType", "type": "string", "versions": "0+",
          "about": "The entity type." },
        { "name": "EntityName", "type": "string", "versions": "0+", "nullableVersions": "0+",
          "about": "The name of the entity, or null if the default." }
      ]},
      { "name": "Ops", "type": "[]OpData", "versions": "0+",
        "about": "An individual configuration entry to alter.", "fields": [
        { "name": "Key", "type": "string", "versions": "0+",
          "about": "The configuration key." },
        { "name": "Value", "type": "string", "versions": "0+",
          "about": "The value to set, otherwise ignored if the value is to be removed." },
        { "name": "Remove", "type": "bool", "versions": "0+",
          "about": "Whether the configuration value should be removed, otherwise set." }
      ]}
    ]},
    { "name": "ValidateOnly", "type": "bool", "versions": "0+",
      "about": "Whether the alteration should be validated, but not performed." }
  ]
}

{
  "apiKey": 51,
  "type": "response",
  "name": "AlterClientConfigsResponse",
  "validVersions": "0",
  "flexibleVersions": "none",
  "fields": [
    { "name": "ThrottleTimeMs", "type": "int32", "versions": "0+",
      "about": "The duration in milliseconds for which the request was throttled due to a quota violation, or zero if the request did not violate any quota." },
    { "name": "Entries", "type": "[]EntryData", "versions": "0+",
      "about": "The configuration entries to alter.", "fields": [
      { "name": "ErrorCode", "type": "int16", "versions": "0+",
        "about": "The error code, or `0` if the config alteration succeeded." },
      { "name": "ErrorMessage", "type": "string", "versions": "0+", "nullableVersions": "0+",
        "about": "The error message, or `null` if the config alteration succeeded." },
      { "name": "Entity", "type": "[]EntityData", "versions": "0+",
        "about": "The config entity to alter.", "fields": [
        { "name": "EntityType", "type": "string", "versions": "0+",
          "about": "The entity type." },
        { "name": "EntityName", "type": "string", "versions": "0+", "nullableVersions": "0+",
          "about": "The name of the entity, or null if the default." }
      ]}
    ]}
  ]
}

Proposed Changes

...

Admin Client Changes

Admin client calls will be added to support {Describe, Alter}ClientConfigs.

Broker Changes

If a {Describe, Alter}ClientConfigsRequest is made without a user component, an InvalidRequest error code will be returned to the client. Apart from this, when the EntityRequest field is not set to true, the mechanics of the <user, client-id> or user config entity descriptions are very similar to the mechanics outlined in KIP-546. This is because the bulk of the code in the brokers that handles fetching client quota entity configs from zookeeper can be reused for dynamic client configs.

...

  1. If a new client with this feature attempts to send a DescribeClientConfigsRequest to an old broker, the broker will send back an InvalidRequest error code and the client will disable this feature.

  2. In the case that an old client is talking to a new broker, nothing will change since the old client will never send a DescribeClientConfigsRequest.

  3. In the case that both the broker and client are up to date with this change, the client will take advantage of the feature.

  4. Clients will register and update their dynamic configs upon starting up through the initial a DescribeClientConfigsRequest. This registration registrations will be tied to written to an internal topic. The record key will be the <user, client-id> by adding the config supported.config to the entity config. The value of this config will be a JSON that maps software names and versions to the list of supported configs for that software name and version. The user will be able to refresh this compatibility information by deleting the configentity and the record value will be the keys that the client supports appended to the ClientInformation. This gives descriptive information about client config compatibility to the user.

Rejected Alternatives

...

  • Introducing new entity types for kafka-configs.sh that producers and consumers can associate themselves with. This would make the tool more cumbersome to use and it is most intuitive that client configurations be dynamically altered with the clients and users entity types.

  • Use the {Describe, IncrementalAlter}Configs APIs. Client config entities are more dynamic than entities with a singular resource name and type which makes it hard to fit them into generic APIs that expect a distinct entity name and type.
  • Use the <user/client-id> hierarchy implemented for client quotas in KIP-55 and extended for the admin client in KIP-546. Quotas are inherently hierarchical but client configs are not, so it seems reasonable to use a hierarchy of shallow depth for dynamic client configs.
  • Interesting config hierarchies could be constructed if the Java producer and consumer resolved the dynamic configs instead of the broker. For example,  from most precedent to least precedent:
    • /config/users/<user>/clients/<client-id>
    • .properties file configs
    • /config/users/<user>
    • Static default configs defined in ProducerConfig and ConsumerConfig.

...