Ignore pubsub topic if it already created

Viewed 722

I have a simple script to deploy a pubsub application.

This script will run on every deploy of my Cloud Run service and I have a line with:

gcloud pubsub topics create some-topic

I want to improve my script if the topic already exist, currently if I run my script, the output will be:

ERROR: Failed to create topic [projects/project-id/topics/some-topic]: Resource already exists in the project (resource=some-topic).

ERROR: (gcloud.pubsub.topics.create) Failed to create the following: [some-topic].

I tried the flag --no-user-output-enabled but no success.

Is there a way to ignore if the resource already exists, or a way to check before create?

2 Answers

Yes.

You can repeat the operation knowing that, if the topic didn't exist beforehand, it will if the command succeeds.

You can swallow stderr (with 2>/dev/null) and then check whether the previous command ($?) succeeded (0):

gcloud pubsub topic create do-something 2>/dev/null
if [ $? -eq 0 ]
then
  # Command succeeded, topic did not exist
  echo "Topic ${TOPIC} did not exist, created."
else
  # Command did not succeed, topic may (!) not have existed
  echo "Failure"
fi

NOTE This approach misses the fact that, the command may fail and the topic didn't exist (i.e. some other issue).

Alternatively (more accurately and more expensively!) you can enumerate the topics first and then try (!) to create it if it doesn't exist:

TOPIC="some-topic"
RESULT=$(\
  gcloud pubsub topics list \
  --filter="name.scope(topics)=${TOPIC}" \
  --format="value(name)" 2>/dev/null)

if [ "${RESULT}" == "" ]
then
  echo "Topic ${TOPIC} does not exist, creating..."
  gcloud pubsub topics create ${TOPIC}
  if [ $? -eq 0 ]
  then
    # Command succeeded, topic created
  else
    # Command did not succeed, topic was not created
  fi
fi

Depending on the complexity of your needs, you can automate using:

  • any of Google's (Pub/Sub) libraries which provide better error-handling and retry capabilities.
  • Terraform e.g. google_pubsub_topic

I had this same issue so I thought I'd try to give a full-fledged function to address this. Building on what @DazWilkin posted, below is a bash script that takes 2 inputs

  1. Project you want to point to
  2. Topic/Subscription Name (In this example the topic and subscription names are the same, however, it's quite straightforward to have an additional input be assigned to the subscription name)

The function will:

  1. Check if the current working project is the same. If not it will set it
  2. Check if the topic exists in the project. If not it will attempt to create it and wait for the response
  3. Check if the subscription exists in the project. If not it will also attempt to create it and wait for a response
function create_pubsub() {
    # Get Current Project
    current_project=$(gcloud config get-value project)
    echo "Current Project is: ${current_project}"

    # Check if Current project matches the specified project
    if [[ "$current_project" != "$1" ]]; then
        gcloud config set project $1
    else
        echo "The project provided matches the current working project"
    fi
    # Check if topic exists in project
    _topic=$(gcloud pubsub topics list \
        --filter="name.scope(topics)=$2" \
        --format="value(name)" 2>/dev/null)
    # React accordingly
    if [[ "${_topic}" != "" ]]; then
        echo "Topic $2 already exists in project ${current_project}"
    else
        echo "The topic '$2' does not exist in project ${current_project}. Creating it now..."
        gcloud pubsub topics create $2
        # Check if command executed successfully
        if [ $? -eq 0 ]; then
            echo "Topic $2 was created successfully"
        else
            echo "An error occured. Topic was NOT created"
        fi
    fi
    # Check if subscription exists in project
    _subscription=$(gcloud pubsub subscriptions list \
    --filter="name=projects/$1/subscriptions/$2" \
    --format="value(name)" 2>/dev/null)
    # React Accordingly
    if [[ "${_subscription}" != "" ]]; then
        echo "Subscription $2 already exists in project ${current_project}"
    else
        echo "The subscription '$2' does not exist in project ${current_project}. Creating it now..."
        gcloud pubsub subscriptions create $2 --topic=$2
        # Check if command executed successfully
        if [ $? -eq 0 ]; then
            echo "Subscription $2 was created successfully"
        else
            echo "An error occured. Subscription was NOT created"
        fi
    fi
    
}

After adding this function to your bashrc or zshrc file, the way you would call this function in the terminal would be create_pubsub <PROJECT_ID> <TOPIC_ID>

Hope this is helpful.

Related